Обновление ZF.
This commit is contained in:
Exile 2015-04-13 03:29:26 +03:00
commit 5914baf7f9
603 changed files with 14278 additions and 6152 deletions

View file

@ -0,0 +1,90 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Authentication\Adapter;
use Exception;
use Zend\Authentication\Exception\InvalidArgumentException;
use Zend\Authentication\Exception\RuntimeException;
use Zend\Authentication\Result;
/**
* Authentication Adapter authenticates using callback function.
*
* The Callback function must return an identity on authentication success,
* and false on authentication failure.
*/
class Callback extends AbstractAdapter
{
/**
* @var callable
*/
protected $callback;
/**
* @param callable $callback The authentication callback
*/
public function __construct($callback = null)
{
if (null !== $callback) {
$this->setCallback($callback);
}
}
/**
* Authenticate using the provided callback
*
* @return Result The authentication result
* @throws RuntimeException
*/
public function authenticate()
{
$callback = $this->getCallback();
if (! $callback) {
throw new RuntimeException('No callback provided');
}
try {
$identity = call_user_func($callback, $this->getIdentity(), $this->getCredential());
} catch (Exception $e) {
return new Result(Result::FAILURE_UNCATEGORIZED, null, array($e->getMessage()));
}
if (! $identity) {
return new Result(Result::FAILURE, null, array('Authentication failure'));
}
return new Result(Result::SUCCESS, $identity, array('Authentication success'));
}
/**
* Gets the value of callback.
*
* @return null|callable
*/
public function getCallback()
{
return $this->callback;
}
/**
* Sets the value of callback.
*
* @param callable $callback the callback
* @throws InvalidArgumentException
*/
public function setCallback($callback)
{
if (! is_callable($callback)) {
throw new InvalidArgumentException('Invalid callback provided');
}
$this->callback = $callback;
}
}

View file

@ -148,7 +148,7 @@ abstract class AbstractAdapter extends BaseAdapter
public function setAmbiguityIdentity($flag) public function setAmbiguityIdentity($flag)
{ {
if (is_int($flag)) { if (is_int($flag)) {
$this->ambiguityIdentity = (1 === $flag ? true : false); $this->ambiguityIdentity = (1 === $flag);
} elseif (is_bool($flag)) { } elseif (is_bool($flag)) {
$this->ambiguityIdentity = $flag; $this->ambiguityIdentity = $flag;
} }

View file

@ -125,14 +125,14 @@ class Http implements AdapterInterface
* *
* @var bool * @var bool
*/ */
protected $imaProxy; protected $imaProxy = false;
/** /**
* Flag indicating the client is IE and didn't bother to return the opaque string * Flag indicating the client is IE and didn't bother to return the opaque string
* *
* @var bool * @var bool
*/ */
protected $ieNoOpaque; protected $ieNoOpaque = false;
/** /**
* Constructor * Constructor
@ -149,10 +149,6 @@ class Http implements AdapterInterface
*/ */
public function __construct(array $config) public function __construct(array $config)
{ {
$this->request = null;
$this->response = null;
$this->ieNoOpaque = false;
if (empty($config['accept_schemes'])) { if (empty($config['accept_schemes'])) {
throw new Exception\InvalidArgumentException('Config key "accept_schemes" is required'); throw new Exception\InvalidArgumentException('Config key "accept_schemes" is required');
} }
@ -181,6 +177,9 @@ class Http implements AdapterInterface
} }
if (in_array('digest', $this->acceptSchemes)) { if (in_array('digest', $this->acceptSchemes)) {
$this->useOpaque = true;
$this->algo = 'MD5';
if (empty($config['digest_domains']) || if (empty($config['digest_domains']) ||
!ctype_print($config['digest_domains']) || !ctype_print($config['digest_domains']) ||
strpos($config['digest_domains'], '"') !== false) { strpos($config['digest_domains'], '"') !== false) {
@ -204,22 +203,16 @@ class Http implements AdapterInterface
// We use the opaque value unless explicitly told not to // We use the opaque value unless explicitly told not to
if (isset($config['use_opaque']) && false == (bool) $config['use_opaque']) { if (isset($config['use_opaque']) && false == (bool) $config['use_opaque']) {
$this->useOpaque = false; $this->useOpaque = false;
} else {
$this->useOpaque = true;
} }
if (isset($config['algorithm']) && in_array($config['algorithm'], $this->supportedAlgos)) { if (isset($config['algorithm']) && in_array($config['algorithm'], $this->supportedAlgos)) {
$this->algo = $config['algorithm']; $this->algo = (string) $config['algorithm'];
} else {
$this->algo = 'MD5';
} }
} }
// Don't be a proxy unless explicitly told to do so // Don't be a proxy unless explicitly told to do so
if (isset($config['proxy_auth']) && true == (bool) $config['proxy_auth']) { if (isset($config['proxy_auth']) && true == (bool) $config['proxy_auth']) {
$this->imaProxy = true; // I'm a Proxy $this->imaProxy = true; // I'm a Proxy
} else {
$this->imaProxy = false;
} }
} }
@ -727,7 +720,7 @@ class Http implements AdapterInterface
if (!$ret || empty($temp[1])) { if (!$ret || empty($temp[1])) {
return false; return false;
} }
if (32 != strlen($temp[1]) || !ctype_xdigit($temp[1])) { if (!$this->isValidMd5Hash($temp[1])) {
return false; return false;
} }
@ -778,7 +771,7 @@ class Http implements AdapterInterface
// This implementation only sends MD5 hex strings in the opaque value // This implementation only sends MD5 hex strings in the opaque value
if (!$this->ieNoOpaque && if (!$this->ieNoOpaque &&
(32 != strlen($temp[1]) || !ctype_xdigit($temp[1]))) { !$this->isValidMd5Hash($temp[1])) {
return false; return false;
} }
@ -811,8 +804,17 @@ class Http implements AdapterInterface
} }
$data['nc'] = $temp[1]; $data['nc'] = $temp[1];
$temp = null;
return $data; return $data;
} }
/**
* validates if $value is a valid Md5 hash
* @param string $value
* @return bool
*/
private function isValidMd5Hash($value)
{
return 32 == strlen($value) && ctype_xdigit($value);
}
} }

View file

@ -144,7 +144,7 @@ class AuthenticationService implements AuthenticationServiceInterface
$storage = $this->getStorage(); $storage = $this->getStorage();
if ($storage->isEmpty()) { if ($storage->isEmpty()) {
return null; return;
} }
return $storage->read(); return $storage->read();

View file

@ -85,7 +85,7 @@ class Result
*/ */
public function isValid() public function isValid()
{ {
return ($this->code > 0) ? true : false; return ($this->code > 0);
} }
/** /**

View file

@ -8,11 +8,10 @@
], ],
"homepage": "https://github.com/zendframework/zf2", "homepage": "https://github.com/zendframework/zf2",
"autoload": { "autoload": {
"psr-0": { "psr-4": {
"Zend\\Authentication\\": "" "Zend\\Authentication\\": ""
} }
}, },
"target-dir": "Zend/Authentication",
"require": { "require": {
"php": ">=5.3.23", "php": ">=5.3.23",
"zendframework/zend-stdlib": "self.version" "zendframework/zend-stdlib": "self.version"

View file

@ -10,6 +10,7 @@
namespace Zend\Barcode; namespace Zend\Barcode;
use Traversable; use Traversable;
use Zend\Barcode\Renderer\RendererInterface;
use Zend\Stdlib\ArrayUtils; use Zend\Stdlib\ArrayUtils;
/** /**
@ -92,7 +93,7 @@ abstract class Barcode
* @param mixed $barcodeConfig OPTIONAL; an array or Traversable object with barcode parameters. * @param mixed $barcodeConfig OPTIONAL; an array or Traversable object with barcode parameters.
* @param mixed $rendererConfig OPTIONAL; an array or Traversable object with renderer parameters. * @param mixed $rendererConfig OPTIONAL; an array or Traversable object with renderer parameters.
* @param bool $automaticRenderError OPTIONAL; set the automatic rendering of exception * @param bool $automaticRenderError OPTIONAL; set the automatic rendering of exception
* @return Barcode * @return RendererInterface
* @throws Exception\ExceptionInterface * @throws Exception\ExceptionInterface
*/ */
public static function factory( public static function factory(

View file

@ -874,7 +874,7 @@ abstract class AbstractObject implements ObjectInterface
* @param string $font * @param string $font
* @param int $color * @param int $color
* @param string $alignment * @param string $alignment
* @param float $orientation * @param float|int $orientation
*/ */
protected function addText( protected function addText(
$text, $text,

View file

@ -52,13 +52,13 @@ abstract class AbstractRenderer implements RendererInterface
/** /**
* Horizontal position of the barcode in the rendering resource * Horizontal position of the barcode in the rendering resource
* @var int * @var string
*/ */
protected $horizontalPosition = 'left'; protected $horizontalPosition = 'left';
/** /**
* Vertical position of the barcode in the rendering resource * Vertical position of the barcode in the rendering resource
* @var int * @var string
*/ */
protected $verticalPosition = 'top'; protected $verticalPosition = 'top';
@ -501,7 +501,7 @@ abstract class AbstractRenderer implements RendererInterface
* @param string $font * @param string $font
* @param int $color * @param int $color
* @param string $alignment * @param string $alignment
* @param float $orientation * @param float|int $orientation
*/ */
abstract protected function drawText( abstract protected function drawText(
$text, $text,

View file

@ -204,6 +204,11 @@ class Image extends AbstractRenderer
$height = $this->userHeight; $height = $this->userHeight;
} }
// Cast width and height to ensure they are correct type for image
// operations
$width = (int) $width;
$height = (int) $height;
$this->resource = imagecreatetruecolor($width, $height); $this->resource = imagecreatetruecolor($width, $height);
$white = imagecolorallocate($this->resource, 255, 255, 255); $white = imagecolorallocate($this->resource, 255, 255, 255);
@ -238,8 +243,8 @@ class Image extends AbstractRenderer
$this->resource, $this->resource,
$this->leftOffset, $this->leftOffset,
$this->topOffset, $this->topOffset,
$this->leftOffset + $barcodeWidth - 1, (int) ($this->leftOffset + $barcodeWidth - 1),
$this->topOffset + $barcodeHeight - 1, (int) ($this->topOffset + $barcodeHeight - 1),
$this->imageBackgroundColor $this->imageBackgroundColor
); );
} }
@ -358,7 +363,7 @@ class Image extends AbstractRenderer
* @param string $font * @param string $font
* @param int $color * @param int $color
* @param string $alignment * @param string $alignment
* @param float $orientation * @param float|int $orientation
* @throws Exception\RuntimeException * @throws Exception\RuntimeException
*/ */
protected function drawText($text, $size, $position, $font, $color, $alignment = 'center', $orientation = 0) protected function drawText($text, $size, $position, $font, $color, $alignment = 'center', $orientation = 0)
@ -382,7 +387,7 @@ class Image extends AbstractRenderer
* imagestring() doesn't allow orientation, if orientation * imagestring() doesn't allow orientation, if orientation
* needed: a TTF font is required. * needed: a TTF font is required.
* Throwing an exception here, allow to use automaticRenderError * Throwing an exception here, allow to use automaticRenderError
* to informe user of the problem instead of simply not drawing * to inform user of the problem instead of simply not drawing
* the text * the text
*/ */
throw new Exception\RuntimeException( throw new Exception\RuntimeException(

View file

@ -8,11 +8,10 @@
], ],
"homepage": "https://github.com/zendframework/zf2", "homepage": "https://github.com/zendframework/zf2",
"autoload": { "autoload": {
"psr-0": { "psr-4": {
"Zend\\Barcode\\": "" "Zend\\Barcode\\": ""
} }
}, },
"target-dir": "Zend/Barcode",
"require": { "require": {
"php": ">=5.3.23", "php": ">=5.3.23",
"zendframework/zend-stdlib": "self.version", "zendframework/zend-stdlib": "self.version",

View file

@ -59,7 +59,7 @@ class CallbackCache extends AbstractPattern
$cacheOutput = $options->getCacheOutput(); $cacheOutput = $options->getCacheOutput();
if ($cacheOutput) { if ($cacheOutput) {
ob_start(); ob_start();
ob_implicit_flush(false); ob_implicit_flush(0);
} }
// TODO: do not cache on errors using [set|restore]_error_handler // TODO: do not cache on errors using [set|restore]_error_handler
@ -137,9 +137,11 @@ class CallbackCache extends AbstractPattern
$callbackKey = strtolower($callbackKey); $callbackKey = strtolower($callbackKey);
// generate a unique key of object callbacks // generate a unique key of object callbacks
if (is_object($callback)) { // Closures & __invoke if (is_object($callback)) {
// Closures & __invoke
$object = $callback; $object = $callback;
} elseif (isset($callback[0])) { // array($object, 'method') } elseif (isset($callback[0])) {
// array($object, 'method')
$object = $callback[0]; $object = $callback[0];
} }
if (isset($object)) { if (isset($object)) {

View file

@ -35,7 +35,7 @@ class CaptureCache extends AbstractPattern
return false; return false;
}); });
ob_implicit_flush(false); ob_implicit_flush(0);
} }
/** /**

View file

@ -60,7 +60,7 @@ class OutputCache extends AbstractPattern
} }
ob_start(); ob_start();
ob_implicit_flush(false); ob_implicit_flush(0);
$this->keyStack[] = $key; $this->keyStack[] = $key;
return false; return false;
} }

View file

@ -574,7 +574,7 @@ class PatternOptions extends AbstractOptions
* Used by: * Used by:
* - ObjectCache * - ObjectCache
* *
* @param mixed $objectKey * @param null|string $objectKey The object key or NULL to use the objects class name
* @return PatternOptions * @return PatternOptions
*/ */
public function setObjectKey($objectKey) public function setObjectKey($objectKey)
@ -597,7 +597,7 @@ class PatternOptions extends AbstractOptions
*/ */
public function getObjectKey() public function getObjectKey()
{ {
if (!$this->objectKey) { if ($this->objectKey === null) {
return get_class($this->getObject()); return get_class($this->getObject());
} }
return $this->objectKey; return $this->objectKey;

View file

@ -217,11 +217,10 @@ abstract class AbstractAdapter implements StorageInterface, EventsCapableInterfa
{ {
$postEvent = new PostEvent($eventName . '.post', $this, $args, $result); $postEvent = new PostEvent($eventName . '.post', $this, $args, $result);
$eventRs = $this->getEventManager()->trigger($postEvent); $eventRs = $this->getEventManager()->trigger($postEvent);
if ($eventRs->stopped()) {
return $eventRs->last();
}
return $postEvent->getResult(); return $eventRs->stopped()
? $eventRs->last()
: $postEvent->getResult();
} }
/** /**
@ -246,11 +245,9 @@ abstract class AbstractAdapter implements StorageInterface, EventsCapableInterfa
throw $exceptionEvent->getException(); throw $exceptionEvent->getException();
} }
if ($eventRs->stopped()) { return $eventRs->stopped()
return $eventRs->last(); ? $eventRs->last()
} : $exceptionEvent->getResult();
return $exceptionEvent->getResult();
} }
/** /**
@ -338,7 +335,7 @@ abstract class AbstractAdapter implements StorageInterface, EventsCapableInterfa
{ {
if (!$this->getOptions()->getReadable()) { if (!$this->getOptions()->getReadable()) {
$success = false; $success = false;
return null; return;
} }
$this->normalizeKey($key); $this->normalizeKey($key);
@ -357,20 +354,21 @@ abstract class AbstractAdapter implements StorageInterface, EventsCapableInterfa
try { try {
$eventRs = $this->triggerPre(__FUNCTION__, $args); $eventRs = $this->triggerPre(__FUNCTION__, $args);
if ($eventRs->stopped()) {
return $eventRs->last();
}
if ($args->offsetExists('success') && $args->offsetExists('casToken')) { if ($eventRs->stopped()) {
$result = $eventRs->last();
} elseif ($args->offsetExists('success') && $args->offsetExists('casToken')) {
$result = $this->internalGetItem($args['key'], $args['success'], $args['casToken']); $result = $this->internalGetItem($args['key'], $args['success'], $args['casToken']);
} elseif ($args->offsetExists('success')) { } elseif ($args->offsetExists('success')) {
$result = $this->internalGetItem($args['key'], $args['success']); $result = $this->internalGetItem($args['key'], $args['success']);
} else { } else {
$result = $this->internalGetItem($args['key']); $result = $this->internalGetItem($args['key']);
} }
return $this->triggerPost(__FUNCTION__, $args, $result); return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) { } catch (\Exception $e) {
$result = false; $result = null;
$success = false;
return $this->triggerException(__FUNCTION__, $args, $result, $e); return $this->triggerException(__FUNCTION__, $args, $result, $e);
} }
} }
@ -410,11 +408,11 @@ abstract class AbstractAdapter implements StorageInterface, EventsCapableInterfa
try { try {
$eventRs = $this->triggerPre(__FUNCTION__, $args); $eventRs = $this->triggerPre(__FUNCTION__, $args);
if ($eventRs->stopped()) {
return $eventRs->last();
}
$result = $this->internalGetItems($args['keys']); $result = $eventRs->stopped()
? $eventRs->last()
: $this->internalGetItems($args['keys']);
return $this->triggerPost(__FUNCTION__, $args, $result); return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) { } catch (\Exception $e) {
$result = array(); $result = array();
@ -467,11 +465,11 @@ abstract class AbstractAdapter implements StorageInterface, EventsCapableInterfa
try { try {
$eventRs = $this->triggerPre(__FUNCTION__, $args); $eventRs = $this->triggerPre(__FUNCTION__, $args);
if ($eventRs->stopped()) {
return $eventRs->last();
}
$result = $this->internalHasItem($args['key']); $result = $eventRs->stopped()
? $eventRs->last()
: $this->internalHasItem($args['key']);
return $this->triggerPost(__FUNCTION__, $args, $result); return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) { } catch (\Exception $e) {
$result = false; $result = false;
@ -517,11 +515,11 @@ abstract class AbstractAdapter implements StorageInterface, EventsCapableInterfa
try { try {
$eventRs = $this->triggerPre(__FUNCTION__, $args); $eventRs = $this->triggerPre(__FUNCTION__, $args);
if ($eventRs->stopped()) {
return $eventRs->last();
}
$result = $this->internalHasItems($args['keys']); $result = $eventRs->stopped()
? $eventRs->last()
: $this->internalHasItems($args['keys']);
return $this->triggerPost(__FUNCTION__, $args, $result); return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) { } catch (\Exception $e) {
$result = array(); $result = array();
@ -571,11 +569,11 @@ abstract class AbstractAdapter implements StorageInterface, EventsCapableInterfa
try { try {
$eventRs = $this->triggerPre(__FUNCTION__, $args); $eventRs = $this->triggerPre(__FUNCTION__, $args);
if ($eventRs->stopped()) {
return $eventRs->last();
}
$result = $this->internalGetMetadata($args['key']); $result = $eventRs->stopped()
? $eventRs->last()
: $this->internalGetMetadata($args['key']);
return $this->triggerPost(__FUNCTION__, $args, $result); return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) { } catch (\Exception $e) {
$result = false; $result = false;
@ -623,11 +621,11 @@ abstract class AbstractAdapter implements StorageInterface, EventsCapableInterfa
try { try {
$eventRs = $this->triggerPre(__FUNCTION__, $args); $eventRs = $this->triggerPre(__FUNCTION__, $args);
if ($eventRs->stopped()) {
return $eventRs->last();
}
$result = $this->internalGetMetadatas($args['keys']); $result = $eventRs->stopped()
? $eventRs->last()
: $this->internalGetMetadatas($args['keys']);
return $this->triggerPost(__FUNCTION__, $args, $result); return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) { } catch (\Exception $e) {
$result = array(); $result = array();
@ -682,11 +680,11 @@ abstract class AbstractAdapter implements StorageInterface, EventsCapableInterfa
try { try {
$eventRs = $this->triggerPre(__FUNCTION__, $args); $eventRs = $this->triggerPre(__FUNCTION__, $args);
if ($eventRs->stopped()) {
return $eventRs->last();
}
$result = $this->internalSetItem($args['key'], $args['value']); $result = $eventRs->stopped()
? $eventRs->last()
: $this->internalSetItem($args['key'], $args['value']);
return $this->triggerPost(__FUNCTION__, $args, $result); return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) { } catch (\Exception $e) {
$result = false; $result = false;
@ -728,11 +726,11 @@ abstract class AbstractAdapter implements StorageInterface, EventsCapableInterfa
try { try {
$eventRs = $this->triggerPre(__FUNCTION__, $args); $eventRs = $this->triggerPre(__FUNCTION__, $args);
if ($eventRs->stopped()) {
return $eventRs->last();
}
$result = $this->internalSetItems($args['keyValuePairs']); $result = $eventRs->stopped()
? $eventRs->last()
: $this->internalSetItems($args['keyValuePairs']);
return $this->triggerPost(__FUNCTION__, $args, $result); return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) { } catch (\Exception $e) {
$result = array_keys($keyValuePairs); $result = array_keys($keyValuePairs);
@ -784,11 +782,11 @@ abstract class AbstractAdapter implements StorageInterface, EventsCapableInterfa
try { try {
$eventRs = $this->triggerPre(__FUNCTION__, $args); $eventRs = $this->triggerPre(__FUNCTION__, $args);
if ($eventRs->stopped()) {
return $eventRs->last();
}
$result = $this->internalAddItem($args['key'], $args['value']); $result = $eventRs->stopped()
? $eventRs->last()
: $this->internalAddItem($args['key'], $args['value']);
return $this->triggerPost(__FUNCTION__, $args, $result); return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) { } catch (\Exception $e) {
$result = false; $result = false;
@ -836,11 +834,11 @@ abstract class AbstractAdapter implements StorageInterface, EventsCapableInterfa
try { try {
$eventRs = $this->triggerPre(__FUNCTION__, $args); $eventRs = $this->triggerPre(__FUNCTION__, $args);
if ($eventRs->stopped()) {
return $eventRs->last();
}
$result = $this->internalAddItems($args['keyValuePairs']); $result = $eventRs->stopped()
? $eventRs->last()
: $this->internalAddItems($args['keyValuePairs']);
return $this->triggerPost(__FUNCTION__, $args, $result); return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) { } catch (\Exception $e) {
$result = array_keys($keyValuePairs); $result = array_keys($keyValuePairs);
@ -892,11 +890,11 @@ abstract class AbstractAdapter implements StorageInterface, EventsCapableInterfa
try { try {
$eventRs = $this->triggerPre(__FUNCTION__, $args); $eventRs = $this->triggerPre(__FUNCTION__, $args);
if ($eventRs->stopped()) {
return $eventRs->last();
}
$result = $this->internalReplaceItem($args['key'], $args['value']); $result = $eventRs->stopped()
? $eventRs->last()
: $this->internalReplaceItem($args['key'], $args['value']);
return $this->triggerPost(__FUNCTION__, $args, $result); return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) { } catch (\Exception $e) {
$result = false; $result = false;
@ -945,11 +943,11 @@ abstract class AbstractAdapter implements StorageInterface, EventsCapableInterfa
try { try {
$eventRs = $this->triggerPre(__FUNCTION__, $args); $eventRs = $this->triggerPre(__FUNCTION__, $args);
if ($eventRs->stopped()) {
return $eventRs->last();
}
$result = $this->internalReplaceItems($args['keyValuePairs']); $result = $eventRs->stopped()
? $eventRs->last()
: $this->internalReplaceItems($args['keyValuePairs']);
return $this->triggerPost(__FUNCTION__, $args, $result); return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) { } catch (\Exception $e) {
$result = array_keys($keyValuePairs); $result = array_keys($keyValuePairs);
@ -1004,11 +1002,11 @@ abstract class AbstractAdapter implements StorageInterface, EventsCapableInterfa
try { try {
$eventRs = $this->triggerPre(__FUNCTION__, $args); $eventRs = $this->triggerPre(__FUNCTION__, $args);
if ($eventRs->stopped()) {
return $eventRs->last();
}
$result = $this->internalCheckAndSetItem($args['token'], $args['key'], $args['value']); $result = $eventRs->stopped()
? $eventRs->last()
: $this->internalCheckAndSetItem($args['token'], $args['key'], $args['value']);
return $this->triggerPost(__FUNCTION__, $args, $result); return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) { } catch (\Exception $e) {
$result = false; $result = false;
@ -1061,11 +1059,11 @@ abstract class AbstractAdapter implements StorageInterface, EventsCapableInterfa
try { try {
$eventRs = $this->triggerPre(__FUNCTION__, $args); $eventRs = $this->triggerPre(__FUNCTION__, $args);
if ($eventRs->stopped()) {
return $eventRs->last();
}
$result = $this->internalTouchItem($args['key']); $result = $eventRs->stopped()
? $eventRs->last()
: $this->internalTouchItem($args['key']);
return $this->triggerPost(__FUNCTION__, $args, $result); return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) { } catch (\Exception $e) {
$result = false; $result = false;
@ -1115,11 +1113,11 @@ abstract class AbstractAdapter implements StorageInterface, EventsCapableInterfa
try { try {
$eventRs = $this->triggerPre(__FUNCTION__, $args); $eventRs = $this->triggerPre(__FUNCTION__, $args);
if ($eventRs->stopped()) {
return $eventRs->last();
}
$result = $this->internalTouchItems($args['keys']); $result = $eventRs->stopped()
? $eventRs->last()
: $this->internalTouchItems($args['keys']);
return $this->triggerPost(__FUNCTION__, $args, $result); return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) { } catch (\Exception $e) {
return $this->triggerException(__FUNCTION__, $args, $keys, $e); return $this->triggerException(__FUNCTION__, $args, $keys, $e);
@ -1168,11 +1166,11 @@ abstract class AbstractAdapter implements StorageInterface, EventsCapableInterfa
try { try {
$eventRs = $this->triggerPre(__FUNCTION__, $args); $eventRs = $this->triggerPre(__FUNCTION__, $args);
if ($eventRs->stopped()) {
return $eventRs->last();
}
$result = $this->internalRemoveItem($args['key']); $result = $eventRs->stopped()
? $eventRs->last()
: $this->internalRemoveItem($args['key']);
return $this->triggerPost(__FUNCTION__, $args, $result); return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) { } catch (\Exception $e) {
$result = false; $result = false;
@ -1213,11 +1211,11 @@ abstract class AbstractAdapter implements StorageInterface, EventsCapableInterfa
try { try {
$eventRs = $this->triggerPre(__FUNCTION__, $args); $eventRs = $this->triggerPre(__FUNCTION__, $args);
if ($eventRs->stopped()) {
return $eventRs->last();
}
$result = $this->internalRemoveItems($args['keys']); $result = $eventRs->stopped()
? $eventRs->last()
: $this->internalRemoveItems($args['keys']);
return $this->triggerPost(__FUNCTION__, $args, $result); return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) { } catch (\Exception $e) {
return $this->triggerException(__FUNCTION__, $args, $keys, $e); return $this->triggerException(__FUNCTION__, $args, $keys, $e);
@ -1268,11 +1266,11 @@ abstract class AbstractAdapter implements StorageInterface, EventsCapableInterfa
try { try {
$eventRs = $this->triggerPre(__FUNCTION__, $args); $eventRs = $this->triggerPre(__FUNCTION__, $args);
if ($eventRs->stopped()) {
return $eventRs->last();
}
$result = $this->internalIncrementItem($args['key'], $args['value']); $result = $eventRs->stopped()
? $eventRs->last()
: $this->internalIncrementItem($args['key'], $args['value']);
return $this->triggerPost(__FUNCTION__, $args, $result); return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) { } catch (\Exception $e) {
$result = false; $result = false;
@ -1328,11 +1326,11 @@ abstract class AbstractAdapter implements StorageInterface, EventsCapableInterfa
try { try {
$eventRs = $this->triggerPre(__FUNCTION__, $args); $eventRs = $this->triggerPre(__FUNCTION__, $args);
if ($eventRs->stopped()) {
return $eventRs->last();
}
$result = $this->internalIncrementItems($args['keyValuePairs']); $result = $eventRs->stopped()
? $eventRs->last()
: $this->internalIncrementItems($args['keyValuePairs']);
return $this->triggerPost(__FUNCTION__, $args, $result); return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) { } catch (\Exception $e) {
$result = array(); $result = array();
@ -1385,11 +1383,11 @@ abstract class AbstractAdapter implements StorageInterface, EventsCapableInterfa
try { try {
$eventRs = $this->triggerPre(__FUNCTION__, $args); $eventRs = $this->triggerPre(__FUNCTION__, $args);
if ($eventRs->stopped()) {
return $eventRs->last();
}
$result = $this->internalDecrementItem($args['key'], $args['value']); $result = $eventRs->stopped()
? $eventRs->last()
: $this->internalDecrementItem($args['key'], $args['value']);
return $this->triggerPost(__FUNCTION__, $args, $result); return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) { } catch (\Exception $e) {
$result = false; $result = false;
@ -1445,11 +1443,11 @@ abstract class AbstractAdapter implements StorageInterface, EventsCapableInterfa
try { try {
$eventRs = $this->triggerPre(__FUNCTION__, $args); $eventRs = $this->triggerPre(__FUNCTION__, $args);
if ($eventRs->stopped()) {
return $eventRs->last();
}
$result = $this->internalDecrementItems($args['keyValuePairs']); $result = $eventRs->stopped()
? $eventRs->last()
: $this->internalDecrementItems($args['keyValuePairs']);
return $this->triggerPost(__FUNCTION__, $args, $result); return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) { } catch (\Exception $e) {
$result = array(); $result = array();
@ -1492,11 +1490,11 @@ abstract class AbstractAdapter implements StorageInterface, EventsCapableInterfa
try { try {
$eventRs = $this->triggerPre(__FUNCTION__, $args); $eventRs = $this->triggerPre(__FUNCTION__, $args);
if ($eventRs->stopped()) {
return $eventRs->last();
}
$result = $this->internalGetCapabilities(); $result = $eventRs->stopped()
? $eventRs->last()
: $this->internalGetCapabilities();
return $this->triggerPost(__FUNCTION__, $args, $result); return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) { } catch (\Exception $e) {
$result = false; $result = false;

View file

@ -221,7 +221,7 @@ class Apc extends AbstractAdapter implements
$result = apc_fetch($internalKey, $success); $result = apc_fetch($internalKey, $success);
if (!$success) { if (!$success) {
return null; return;
} }
$casToken = $result; $casToken = $result;
@ -361,16 +361,19 @@ class Apc extends AbstractAdapter implements
$options = $this->getOptions(); $options = $this->getOptions();
$namespace = $options->getNamespace(); $namespace = $options->getNamespace();
$prefixL = 0;
if ($namespace === '') { if ($namespace === '') {
$pattern = '/^(' . implode('|', $keysRegExp) . ')' . '$/'; $pattern = '/^(' . implode('|', $keysRegExp) . ')' . '$/';
} else { } else {
$prefix = $namespace . $options->getNamespaceSeparator(); $prefix = $namespace . $options->getNamespaceSeparator();
$prefixL = strlen($prefix);
$pattern = '/^' . preg_quote($prefix, '/') . '(' . implode('|', $keysRegExp) . ')' . '$/'; $pattern = '/^' . preg_quote($prefix, '/') . '(' . implode('|', $keysRegExp) . ')' . '$/';
} }
$format = APC_ITER_ALL ^ APC_ITER_VALUE ^ APC_ITER_TYPE ^ APC_ITER_REFCOUNT; $format = APC_ITER_ALL ^ APC_ITER_VALUE ^ APC_ITER_TYPE ^ APC_ITER_REFCOUNT;
$it = new BaseApcIterator('user', $pattern, $format, 100, APC_LIST_ACTIVE); $it = new BaseApcIterator('user', $pattern, $format, 100, APC_LIST_ACTIVE);
$result = array(); $result = array();
$prefixL = strlen($prefix);
foreach ($it as $internalKey => $metadata) { foreach ($it as $internalKey => $metadata) {
// @see http://pecl.php.net/bugs/bug.php?id=22564 // @see http://pecl.php.net/bugs/bug.php?id=22564
if (!apc_exists($internalKey)) { if (!apc_exists($internalKey)) {
@ -378,7 +381,7 @@ class Apc extends AbstractAdapter implements
} }
$this->normalizeMetadata($metadata); $this->normalizeMetadata($metadata);
$result[substr($internalKey, $prefixL)] = & $metadata; $result[substr($internalKey, $prefixL)] = $metadata;
} }
return $result; return $result;

View file

@ -113,7 +113,7 @@ class BlackHole implements
public function getItem($key, & $success = null, & $casToken = null) public function getItem($key, & $success = null, & $casToken = null)
{ {
$success = false; $success = false;
return null; return;
} }
/** /**

View file

@ -81,7 +81,7 @@ class Dba extends AbstractAdapter implements
* Set options. * Set options.
* *
* @param array|Traversable|DbaOptions $options * @param array|Traversable|DbaOptions $options
* @return Apc * @return self
* @see getOptions() * @see getOptions()
*/ */
public function setOptions($options) public function setOptions($options)
@ -153,7 +153,7 @@ class Dba extends AbstractAdapter implements
/** /**
* Get available space in bytes * Get available space in bytes
* *
* @return int|float * @return float
*/ */
public function getAvailableSpace() public function getAvailableSpace()
{ {
@ -264,7 +264,8 @@ class Dba extends AbstractAdapter implements
$this->_open(); $this->_open();
do { // Workaround for PHP-Bug #62491 & #62492 // Workaround for PHP-Bug #62491 & #62492
do {
$recheck = false; $recheck = false;
$internalKey = dba_firstkey($this->handle); $internalKey = dba_firstkey($this->handle);
while ($internalKey !== false && $internalKey !== null) { while ($internalKey !== false && $internalKey !== null) {
@ -285,7 +286,7 @@ class Dba extends AbstractAdapter implements
/** /**
* Get the storage iterator * Get the storage iterator
* *
* @return ApcIterator * @return DbaIterator
*/ */
public function getIterator() public function getIterator()
{ {
@ -335,7 +336,7 @@ class Dba extends AbstractAdapter implements
if ($value === false) { if ($value === false) {
$success = false; $success = false;
return null; return;
} }
$success = true; $success = true;
@ -377,8 +378,10 @@ class Dba extends AbstractAdapter implements
$prefix = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator(); $prefix = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
$internalKey = $prefix . $normalizedKey; $internalKey = $prefix . $normalizedKey;
$cacheableValue = (string) $value; // dba_replace requires a string
$this->_open(); $this->_open();
if (!dba_replace($internalKey, $value, $this->handle)) { if (!dba_replace($internalKey, $cacheableValue, $this->handle)) {
throw new Exception\RuntimeException("dba_replace('{$internalKey}', ...) failed"); throw new Exception\RuntimeException("dba_replace('{$internalKey}', ...) failed");
} }

View file

@ -117,6 +117,12 @@ class DbaOptions extends AdapterOptions
throw new Exception\ExtensionNotLoadedException("DBA-Handler '{$handler}' not supported"); throw new Exception\ExtensionNotLoadedException("DBA-Handler '{$handler}' not supported");
} }
if ($handler === 'inifile') {
throw new Exception\ExtensionNotLoadedException(
"DBA-Handler 'inifile' does not reliably support write operations"
);
}
$this->triggerOptionEvent('handler', $handler); $this->triggerOptionEvent('handler', $handler);
$this->handler = $handler; $this->handler = $handler;
return $this; return $this;

View file

@ -433,7 +433,7 @@ class Filesystem extends AbstractAdapter implements
* Get available space in bytes * Get available space in bytes
* *
* @throws Exception\RuntimeException * @throws Exception\RuntimeException
* @return int|float * @return float
*/ */
public function getAvailableSpace() public function getAvailableSpace()
{ {
@ -508,14 +508,15 @@ class Filesystem extends AbstractAdapter implements
* @param string $normalizedKey * @param string $normalizedKey
* @param bool $success * @param bool $success
* @param mixed $casToken * @param mixed $casToken
* @return mixed Data on success, null on failure * @return null|mixed Data on success, null on failure
* @throws Exception\ExceptionInterface * @throws Exception\ExceptionInterface
* @throws BaseException
*/ */
protected function internalGetItem(& $normalizedKey, & $success = null, & $casToken = null) protected function internalGetItem(& $normalizedKey, & $success = null, & $casToken = null)
{ {
if (!$this->internalHasItem($normalizedKey)) { if (!$this->internalHasItem($normalizedKey)) {
$success = false; $success = false;
return null; return;
} }
try { try {
@ -915,8 +916,6 @@ class Filesystem extends AbstractAdapter implements
*/ */
protected function internalSetItems(array & $normalizedKeyValuePairs) protected function internalSetItems(array & $normalizedKeyValuePairs)
{ {
$oldUmask = null;
// create an associated array of files and contents to write // create an associated array of files and contents to write
$contents = array(); $contents = array();
foreach ($normalizedKeyValuePairs as $key => & $value) { foreach ($normalizedKeyValuePairs as $key => & $value) {
@ -1499,6 +1498,11 @@ class Filesystem extends AbstractAdapter implements
*/ */
protected function putFileContent($file, $data, $nonBlocking = false, & $wouldblock = null) protected function putFileContent($file, $data, $nonBlocking = false, & $wouldblock = null)
{ {
if (! is_string($data)) {
// Ensure we have a string
$data = (string) $data;
}
$options = $this->getOptions(); $options = $this->getOptions();
$locking = $options->getFileLocking(); $locking = $options->getFileLocking();
$nonBlocking = $locking && $nonBlocking; $nonBlocking = $locking && $nonBlocking;

View file

@ -67,7 +67,7 @@ class Memcache extends AbstractAdapter implements
// reset initialized flag on update option(s) // reset initialized flag on update option(s)
$initialized = & $this->initialized; $initialized = & $this->initialized;
$this->getEventManager()->attach('option', function ($event) use (& $initialized) { $this->getEventManager()->attach('option', function () use (& $initialized) {
$initialized = false; $initialized = false;
}); });
} }
@ -220,7 +220,7 @@ class Memcache extends AbstractAdapter implements
$result = $memc->get($internalKey); $result = $memc->get($internalKey);
$success = ($result !== false); $success = ($result !== false);
if ($result === false) { if ($result === false) {
return null; return;
} }
$casToken = $result; $casToken = $result;

View file

@ -95,6 +95,8 @@ class MemcacheResourceManager
* *
* @param string $id * @param string $id
* @param array|Traversable|MemcacheResource $resource * @param array|Traversable|MemcacheResource $resource
* @param callable $failureCallback
* @param array|Traversable $serverDefaults
* @return MemcacheResourceManager * @return MemcacheResourceManager
*/ */
public function setResource($id, $resource, $failureCallback = null, $serverDefaults = array()) public function setResource($id, $resource, $failureCallback = null, $serverDefaults = array())
@ -184,7 +186,8 @@ class MemcacheResourceManager
* Set compress threshold on a Memcache resource * Set compress threshold on a Memcache resource
* *
* @param MemcacheResource $resource * @param MemcacheResource $resource
* @param array $libOptions * @param int $threshold
* @param float $minSavings
*/ */
protected function setResourceAutoCompressThreshold(MemcacheResource $resource, $threshold, $minSavings) protected function setResourceAutoCompressThreshold(MemcacheResource $resource, $threshold, $minSavings)
{ {
@ -396,7 +399,7 @@ class MemcacheResourceManager
* Get callback for server connection failures * Get callback for server connection failures
* *
* @param string $id * @param string $id
* @return callable|null * @return callable
* @throws Exception\RuntimeException * @throws Exception\RuntimeException
*/ */
public function getFailureCallback($id) public function getFailureCallback($id)

View file

@ -79,7 +79,7 @@ class Memcached extends AbstractAdapter implements
// reset initialized flag on update option(s) // reset initialized flag on update option(s)
$initialized = & $this->initialized; $initialized = & $this->initialized;
$this->getEventManager()->attach('option', function ($event) use (& $initialized) { $this->getEventManager()->attach('option', function () use (& $initialized) {
$initialized = false; $initialized = false;
}); });
} }

View file

@ -84,7 +84,7 @@ class Memory extends AbstractAdapter implements
/** /**
* Get total space in bytes * Get total space in bytes
* *
* @return int|float * @return int
*/ */
public function getTotalSpace() public function getTotalSpace()
{ {
@ -307,7 +307,7 @@ class Memory extends AbstractAdapter implements
} }
if (!$success) { if (!$success) {
return null; return;
} }
$casToken = $data[0]; $casToken = $data[0];

View file

@ -0,0 +1,285 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Cache\Storage\Adapter;
use MongoCollection as MongoResource;
use MongoDate;
use MongoException as MongoResourceException;
use stdClass;
use Zend\Cache\Exception;
use Zend\Cache\Storage\Capabilities;
use Zend\Cache\Storage\FlushableInterface;
class MongoDb extends AbstractAdapter implements FlushableInterface
{
/**
* Has this instance be initialized
*
* @var bool
*/
private $initialized = false;
/**
* the mongodb resource manager
*
* @var null|MongoDbResourceManager
*/
private $resourceManager;
/**
* The mongodb resource id
*
* @var null|string
*/
private $resourceId;
/**
* The namespace prefix
*
* @var string
*/
private $namespacePrefix = '';
/**
* {@inheritDoc}
*
* @throws Exception\ExtensionNotLoadedException
*/
public function __construct($options = null)
{
if (!class_exists('Mongo') || !class_exists('MongoClient')) {
throw new Exception\ExtensionNotLoadedException('MongoDb extension not loaded or Mongo polyfill not included');
}
parent::__construct($options);
$initialized = & $this->initialized;
$this->getEventManager()->attach(
'option',
function () use (& $initialized) {
$initialized = false;
}
);
}
/**
* get mongodb resource
*
* @return MongoResource
*/
private function getMongoDbResource()
{
if (! $this->initialized) {
$options = $this->getOptions();
$this->resourceManager = $options->getResourceManager();
$this->resourceId = $options->getResourceId();
$namespace = $options->getNamespace();
$this->namespacePrefix = ($namespace === '' ? '' : $namespace . $options->getNamespaceSeparator());
$this->initialized = true;
}
return $this->resourceManager->getResource($this->resourceId);
}
/**
* {@inheritDoc}
*/
public function setOptions($options)
{
return parent::setOptions($options instanceof MongoDbOptions ? $options : new MongoDbOptions($options));
}
/**
* Get options.
*
* @return MongoDbOptions
* @see setOptions()
*/
public function getOptions()
{
return $this->options;
}
/**
* {@inheritDoc}
*
* @throws Exception\RuntimeException
*/
protected function internalGetItem(& $normalizedKey, & $success = null, & $casToken = null)
{
$result = $this->fetchFromCollection($normalizedKey);
$success = false;
if (null === $result) {
return;
}
if (isset($result['expires'])) {
if (! $result['expires'] instanceof MongoDate) {
throw new Exception\RuntimeException(sprintf(
"The found item _id '%s' for key '%s' is not a valid cache item"
. ": the field 'expired' isn't an instance of MongoDate, '%s' found instead",
(string) $result['_id'],
$this->namespacePrefix . $normalizedKey,
is_object($result['expires']) ? get_class($result['expires']) : gettype($result['expires'])
));
}
if ($result['expires']->sec < time()) {
$this->internalRemoveItem($key);
return;
}
}
if (! array_key_exists('value', $result)) {
throw new Exception\RuntimeException(sprintf(
"The found item _id '%s' for key '%s' is not a valid cache item: missing the field 'value'",
(string) $result['_id'],
$this->namespacePrefix . $normalizedKey
));
}
$success = true;
return $casToken = $result['value'];
}
/**
* {@inheritDoc}
*
* @throws Exception\RuntimeException
*/
protected function internalSetItem(& $normalizedKey, & $value)
{
$mongo = $this->getMongoDbResource();
$key = $this->namespacePrefix . $normalizedKey;
$ttl = $this->getOptions()->getTTl();
$expires = null;
$cacheItem = array(
'key' => $key,
'value' => $value,
);
if ($ttl > 0) {
$expiresMicro = microtime(true) + $ttl;
$expiresSecs = (int) $expiresMicro;
$cacheItem['expires'] = new MongoDate($expiresSecs, $expiresMicro - $expiresSecs);
}
try {
$mongo->remove(array('key' => $key));
$result = $mongo->insert($cacheItem);
} catch (MongoResourceException $e) {
throw new Exception\RuntimeException($e->getMessage(), $e->getCode(), $e);
}
return null !== $result && ((double) 1) === $result['ok'];
}
/**
* {@inheritDoc}
*
* @throws Exception\RuntimeException
*/
protected function internalRemoveItem(& $normalizedKey)
{
try {
$result = $this->getMongoDbResource()->remove(array('key' => $this->namespacePrefix . $normalizedKey));
} catch (MongoResourceException $e) {
throw new Exception\RuntimeException($e->getMessage(), $e->getCode(), $e);
}
return false !== $result
&& ((double) 1) === $result['ok']
&& $result['n'] > 0;
}
/**
* {@inheritDoc}
*/
public function flush()
{
$result = $this->getMongoDbResource()->drop();
return ((double) 1) === $result['ok'];
}
/**
* {@inheritDoc}
*/
protected function internalGetCapabilities()
{
if ($this->capabilities) {
return $this->capabilities;
}
return $this->capabilities = new Capabilities(
$this,
$this->capabilityMarker = new stdClass(),
array(
'supportedDatatypes' => array(
'NULL' => true,
'boolean' => true,
'integer' => true,
'double' => true,
'string' => true,
'array' => true,
'object' => false,
'resource' => false,
),
'supportedMetadata' => array(
'_id',
),
'minTtl' => 0,
'maxTtl' => 0,
'staticTtl' => true,
'ttlPrecision' => 1,
'useRequestTime' => false,
'expiredRead' => false,
'maxKeyLength' => 255,
'namespaceIsPrefix' => true,
)
);
}
/**
* {@inheritDoc}
*
* @throws Exception\ExceptionInterface
*/
protected function internalGetMetadata(& $normalizedKey)
{
$result = $this->fetchFromCollection($normalizedKey);
return null !== $result ? array('_id' => $result['_id']) : false;
}
/**
* Return raw records from MongoCollection
*
* @param string $normalizedKey
*
* @return array|null
*
* @throws Exception\RuntimeException
*/
private function fetchFromCollection(& $normalizedKey)
{
try {
return $this->getMongoDbResource()->findOne(array('key' => $this->namespacePrefix . $normalizedKey));
} catch (MongoResourceException $e) {
throw new Exception\RuntimeException($e->getMessage(), $e->getCode(), $e);
}
}
}

View file

@ -0,0 +1,158 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Cache\Storage\Adapter;
class MongoDbOptions extends AdapterOptions
{
/**
* The namespace separator
*
* @var string
*/
private $namespaceSeparator = ':';
/**
* The redis resource manager
*
* @var null|RedisResourceManager
*/
private $resourceManager;
/**
* The resource id of the resource manager
*
* @var string
*/
private $resourceId = 'default';
/**
* Set namespace separator
*
* @param string $namespaceSeparator
*
* @return self
*/
public function setNamespaceSeparator($namespaceSeparator)
{
$namespaceSeparator = (string) $namespaceSeparator;
if ($this->namespaceSeparator !== $namespaceSeparator) {
$this->triggerOptionEvent('namespace_separator', $namespaceSeparator);
$this->namespaceSeparator = $namespaceSeparator;
}
return $this;
}
/**
* Get namespace separator
*
* @return string
*/
public function getNamespaceSeparator()
{
return $this->namespaceSeparator;
}
/**
* Set the mongodb resource manager to use
*
* @param null|MongoDbResourceManager $resourceManager
*
* @return self
*/
public function setResourceManager(MongoDbResourceManager $resourceManager = null)
{
if ($this->resourceManager !== $resourceManager) {
$this->triggerOptionEvent('resource_manager', $resourceManager);
$this->resourceManager = $resourceManager;
}
return $this;
}
/**
* Get the mongodb resource manager
*
* @return MongoDbResourceManager
*/
public function getResourceManager()
{
return $this->resourceManager ?: $this->resourceManager = new MongoDbResourceManager();
}
/**
* Get the mongodb resource id
*
* @return string
*/
public function getResourceId()
{
return $this->resourceId;
}
/**
* Set the redis resource id
*
* @param string $resourceId
*
* @return self
*/
public function setResourceId($resourceId)
{
$resourceId = (string) $resourceId;
if ($this->resourceId !== $resourceId) {
$this->triggerOptionEvent('resource_id', $resourceId);
$this->resourceId = $resourceId;
}
return $this;
}
/**
* Set the mongo DB server
*
* @param string $server
* @return self
*/
public function setServer($server)
{
$this->getResourceManager()->setServer($this->getResourceId(), $server);
return $this;
}
public function setConnectionOptions(array $connectionOptions)
{
$this->getResourceManager()->setConnectionOptions($this->getResourceId(), $connectionOptions);
return $this;
}
public function setDriverOptions(array $driverOptions)
{
$this->getResourceManager()->setDriverOptions($this->getResourceId(), $driverOptions);
return $this;
}
public function setDatabase($database)
{
$this->getResourceManager()->setDatabase($this->getResourceId(), $database);
return $this;
}
public function setCollection($collection)
{
$this->getResourceManager()->setCollection($this->getResourceId(), $collection);
return $this;
}
}

View file

@ -0,0 +1,204 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Cache\Storage\Adapter;
use MongoCollection;
use MongoException;
use Zend\Cache\Exception;
class MongoDbResourceManager
{
/**
* Registered resources
*
* @var array[]
*/
private $resources = array();
/**
* Check if a resource exists
*
* @param string $id
*
* @return bool
*/
public function hasResource($id)
{
return isset($this->resources[$id]);
}
/**
* Set a resource
*
* @param string $id
* @param array|MongoCollection $resource
*
* @return self
*
* @throws Exception\RuntimeException
*/
public function setResource($id, $resource)
{
if ($resource instanceof MongoCollection) {
$this->resources[$id] = array(
'db' => (string) $resource->db,
'db_instance' => $resource->db,
'collection' => (string) $resource,
'collection_instance' => $resource,
);
return $this;
}
if (! is_array($resource)) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects an array or MongoCollection; received %s',
__METHOD__,
(is_object($resource) ? get_class($resource) : gettype($resource))
));
}
$this->resources[$id] = $resource;
return $this;
}
/**
* Instantiate and return the MongoCollection resource
*
* @param string $id
* @return MongoCollection
* @throws Exception\RuntimeException
*/
public function getResource($id)
{
if (!$this->hasResource($id)) {
throw new Exception\RuntimeException("No resource with id '{$id}'");
}
$resource = $this->resources[$id];
if (!isset($resource['collection_instance'])) {
try {
if (!isset($resource['db_instance'])) {
if (!isset($resource['client_instance'])) {
$clientClass = version_compare(phpversion('mongo'), '1.3.0', '<') ? 'Mongo' : 'MongoClient';
$resource['client_instance'] = new $clientClass(
isset($resource['server']) ? $resource['server'] : null,
isset($resource['connection_options']) ? $resource['connection_options'] : array(),
isset($resource['driver_options']) ? $resource['driver_options'] : array()
);
}
$resource['db_instance'] = $resource['client_instance']->selectDB(
isset($resource['db']) ? $resource['db'] : ''
);
}
$collection = $resource['db_instance']->selectCollection(
isset($resource['collection']) ? $resource['collection'] : ''
);
$collection->ensureIndex(array('key' => 1));
$this->resources[$id]['collection_instance'] = $collection;
} catch (MongoException $e) {
throw new Exception\RuntimeException($e->getMessage(), $e->getCode(), $e);
}
}
return $this->resources[$id]['collection_instance'];
}
public function setServer($id, $server)
{
$this->resources[$id]['server'] = (string)$server;
unset($this->resource[$id]['client_instance']);
unset($this->resource[$id]['db_instance']);
unset($this->resource[$id]['collection_instance']);
}
public function getServer($id)
{
if (!$this->hasResource($id)) {
throw new Exception\RuntimeException("No resource with id '{$id}'");
}
return isset($this->resources[$id]['server']) ? $this->resources[$id]['server'] : null;
}
public function setConnectionOptions($id, array $connectionOptions)
{
$this->resources[$id]['connection_options'] = $connectionOptions;
unset($this->resource[$id]['client_instance']);
unset($this->resource[$id]['db_instance']);
unset($this->resource[$id]['collection_instance']);
}
public function getConnectionOptions($id)
{
if (!$this->hasResource($id)) {
throw new Exception\RuntimeException("No resource with id '{$id}'");
}
return isset($this->resources[$id]['connection_options'])
? $this->resources[$id]['connection_options']
: array();
}
public function setDriverOptions($id, array $driverOptions)
{
$this->resources[$id]['driver_options'] = $driverOptions;
unset($this->resource[$id]['client_instance']);
unset($this->resource[$id]['db_instance']);
unset($this->resource[$id]['collection_instance']);
}
public function getDriverOptions($id)
{
if (!$this->hasResource($id)) {
throw new Exception\RuntimeException("No resource with id '{$id}'");
}
return isset($this->resources[$id]['driver_options']) ? $this->resources[$id]['driver_options'] : array();
}
public function setDatabase($id, $database)
{
$this->resources[$id]['db'] = (string)$database;
unset($this->resource[$id]['db_instance']);
unset($this->resource[$id]['collection_instance']);
}
public function getDatabase($id)
{
if (!$this->hasResource($id)) {
throw new Exception\RuntimeException("No resource with id '{$id}'");
}
return isset($this->resources[$id]['db']) ? $this->resources[$id]['db'] : '';
}
public function setCollection($id, $collection)
{
$this->resources[$id]['collection'] = (string)$collection;
unset($this->resource[$id]['collection_instance']);
}
public function getCollection($id)
{
if (!$this->hasResource($id)) {
throw new Exception\RuntimeException("No resource with id '{$id}'");
}
return isset($this->resources[$id]['collection']) ? $this->resources[$id]['collection'] : '';
}
}

View file

@ -13,12 +13,14 @@ use Redis as RedisResource;
use RedisException as RedisResourceException; use RedisException as RedisResourceException;
use stdClass; use stdClass;
use Traversable; use Traversable;
use Zend\Cache\Storage\ClearByPrefixInterface;
use Zend\Cache\Exception; use Zend\Cache\Exception;
use Zend\Cache\Storage\Capabilities; use Zend\Cache\Storage\Capabilities;
use Zend\Cache\Storage\FlushableInterface; use Zend\Cache\Storage\FlushableInterface;
use Zend\Cache\Storage\TotalSpaceCapableInterface; use Zend\Cache\Storage\TotalSpaceCapableInterface;
class Redis extends AbstractAdapter implements class Redis extends AbstractAdapter implements
ClearByPrefixInterface,
FlushableInterface, FlushableInterface,
TotalSpaceCapableInterface TotalSpaceCapableInterface
{ {
@ -66,7 +68,7 @@ class Redis extends AbstractAdapter implements
// reset initialized flag on update option(s) // reset initialized flag on update option(s)
$initialized = & $this->initialized; $initialized = & $this->initialized;
$this->getEventManager()->attach('option', function ($event) use (& $initialized) { $this->getEventManager()->attach('option', function () use (& $initialized) {
$initialized = false; $initialized = false;
}); });
} }
@ -151,7 +153,7 @@ class Redis extends AbstractAdapter implements
if ($value === false) { if ($value === false) {
$success = false; $success = false;
return null; return;
} }
$success = true; $success = true;
@ -368,6 +370,32 @@ class Redis extends AbstractAdapter implements
} }
} }
/* ClearByPrefixInterface */
/**
* Remove items matching given prefix
*
* @param string $prefix
* @return bool
*/
public function clearByPrefix($prefix)
{
$redis = $this->getRedisResource();
$prefix = (string) $prefix;
if ($prefix === '') {
throw new Exception\InvalidArgumentException('No prefix given');
}
$options = $this->getOptions();
$namespace = $options->getNamespace();
$prefix = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator() . $prefix;
$redis->delete($redis->keys($prefix.'*'));
return true;
}
/* TotalSpaceCapableInterface */ /* TotalSpaceCapableInterface */
/** /**

View file

@ -105,7 +105,7 @@ class RedisResourceManager
* Gets a redis resource * Gets a redis resource
* *
* @param string $id * @param string $id
* @return RedisResource * @return RedisResourceManager
* @throws Exception\RuntimeException * @throws Exception\RuntimeException
*/ */
public function getResource($id) public function getResource($id)
@ -233,14 +233,14 @@ class RedisResourceManager
} }
if (! is_string($serverUri)) { if (! is_string($serverUri)) {
return null; return;
} }
// parse server from URI host{:?port} // parse server from URI host{:?port}
$server = trim($serverUri); $server = trim($serverUri);
if (strpos($server, '/') === 0) { if (strpos($server, '/') === 0) {
return null; return;
} }
//non unix domain socket connection //non unix domain socket connection
@ -627,7 +627,7 @@ class RedisResourceManager
* *
* @param string $id * @param string $id
* @param int $database * @param int $database
* @return RedisResource * @return RedisResourceManager
*/ */
public function setDatabase($id, $database) public function setDatabase($id, $database)
{ {

View file

@ -152,13 +152,13 @@ class Session extends AbstractAdapter implements
if (!$cntr->offsetExists($ns)) { if (!$cntr->offsetExists($ns)) {
$success = false; $success = false;
return null; return;
} }
$data = $cntr->offsetGet($ns); $data = $cntr->offsetGet($ns);
$success = array_key_exists($normalizedKey, $data); $success = array_key_exists($normalizedKey, $data);
if (!$success) { if (!$success) {
return null; return;
} }
$casToken = $value = $data[$normalizedKey]; $casToken = $value = $data[$normalizedKey];

View file

@ -34,6 +34,7 @@ class AdapterPluginManager extends AbstractPluginManager
'memcache' => 'Zend\Cache\Storage\Adapter\Memcache', 'memcache' => 'Zend\Cache\Storage\Adapter\Memcache',
'memcached' => 'Zend\Cache\Storage\Adapter\Memcached', 'memcached' => 'Zend\Cache\Storage\Adapter\Memcached',
'memory' => 'Zend\Cache\Storage\Adapter\Memory', 'memory' => 'Zend\Cache\Storage\Adapter\Memory',
'mongodb' => 'Zend\Cache\Storage\Adapter\MongoDb',
'redis' => 'Zend\Cache\Storage\Adapter\Redis', 'redis' => 'Zend\Cache\Storage\Adapter\Redis',
'session' => 'Zend\Cache\Storage\Adapter\Session', 'session' => 'Zend\Cache\Storage\Adapter\Session',
'xcache' => 'Zend\Cache\Storage\Adapter\XCache', 'xcache' => 'Zend\Cache\Storage\Adapter\XCache',

View file

@ -26,7 +26,7 @@ class PluginOptions extends AbstractOptions
/** /**
* Used by: * Used by:
* - ExceptionHandler * - ExceptionHandler
* @var callable * @var null|callable
*/ */
protected $exceptionCallback; protected $exceptionCallback;
@ -99,7 +99,7 @@ class PluginOptions extends AbstractOptions
* Used by: * Used by:
* - ExceptionHandler * - ExceptionHandler
* *
* @param callable $exceptionCallback * @param null|callable $exceptionCallback
* @throws Exception\InvalidArgumentException * @throws Exception\InvalidArgumentException
* @return PluginOptions * @return PluginOptions
*/ */
@ -118,7 +118,7 @@ class PluginOptions extends AbstractOptions
* Used by: * Used by:
* - ExceptionHandler * - ExceptionHandler
* *
* @return callable * @return null|callable
*/ */
public function getExceptionCallback() public function getExceptionCallback()
{ {

View file

@ -8,11 +8,10 @@
], ],
"homepage": "https://github.com/zendframework/zf2", "homepage": "https://github.com/zendframework/zf2",
"autoload": { "autoload": {
"psr-0": { "psr-4": {
"Zend\\Cache\\": "" "Zend\\Cache\\": ""
} }
}, },
"target-dir": "Zend/Cache",
"require": { "require": {
"php": ">=5.3.23", "php": ">=5.3.23",
"zendframework/zend-stdlib": "self.version", "zendframework/zend-stdlib": "self.version",
@ -29,7 +28,9 @@
"ext-apc": "APC >= 3.1.6 to use the APC storage adapter", "ext-apc": "APC >= 3.1.6 to use the APC storage adapter",
"ext-dba": "DBA, to use the DBA storage adapter", "ext-dba": "DBA, to use the DBA storage adapter",
"ext-memcached": "Memcached >= 1.0.0 to use the Memcached storage adapter", "ext-memcached": "Memcached >= 1.0.0 to use the Memcached storage adapter",
"ext-wincache": "WinCache, to use the WinCache storage adapter" "ext-mongo": "Mongo, to use MongoDb storage adapter",
"ext-wincache": "WinCache, to use the WinCache storage adapter",
"mongofill/mongofill": "Alternative to ext-mongo - a pure PHP implementation designed as a drop in replacement"
}, },
"extra": { "extra": {
"branch-alias": { "branch-alias": {

View file

@ -8,11 +8,10 @@
], ],
"homepage": "https://github.com/zendframework/zf2", "homepage": "https://github.com/zendframework/zf2",
"autoload": { "autoload": {
"psr-0": { "psr-4": {
"Zend\\Captcha\\": "" "Zend\\Captcha\\": ""
} }
}, },
"target-dir": "Zend/Captcha",
"require": { "require": {
"php": ">=5.3.23", "php": ">=5.3.23",
"zendframework/zend-math": "self.version", "zendframework/zend-math": "self.version",

View file

@ -13,6 +13,8 @@ use Zend\Code\Reflection\ClassReflection;
class ClassGenerator extends AbstractGenerator class ClassGenerator extends AbstractGenerator
{ {
const OBJECT_TYPE = "class";
const FLAG_ABSTRACT = 0x01; const FLAG_ABSTRACT = 0x01;
const FLAG_FINAL = 0x02; const FLAG_FINAL = 0x02;
@ -56,15 +58,20 @@ class ClassGenerator extends AbstractGenerator
*/ */
protected $properties = array(); protected $properties = array();
/**
* @var PropertyGenerator[] Array of constants
*/
protected $constants = array();
/** /**
* @var MethodGenerator[] Array of methods * @var MethodGenerator[] Array of methods
*/ */
protected $methods = array(); protected $methods = array();
/** /**
* @var array Array of string names * @var TraitUsageGenerator Object to encapsulate trait usage logic
*/ */
protected $uses = array(); protected $traitUsageGenerator;
/** /**
* Build a Code Generation Php Object from a Class Reflection * Build a Code Generation Php Object from a Class Reflection
@ -74,7 +81,6 @@ class ClassGenerator extends AbstractGenerator
*/ */
public static function fromReflection(ClassReflection $classReflection) public static function fromReflection(ClassReflection $classReflection)
{ {
// class generator
$cg = new static($classReflection->getName()); $cg = new static($classReflection->getName());
$cg->setSourceContent($cg->getSourceContent()); $cg->setSourceContent($cg->getSourceContent());
@ -93,11 +99,12 @@ class ClassGenerator extends AbstractGenerator
/* @var \Zend\Code\Reflection\ClassReflection $parentClass */ /* @var \Zend\Code\Reflection\ClassReflection $parentClass */
$parentClass = $classReflection->getParentClass(); $parentClass = $classReflection->getParentClass();
$interfaces = $classReflection->getInterfaces();
if ($parentClass) { if ($parentClass) {
$cg->setExtendedClass($parentClass->getName()); $cg->setExtendedClass($parentClass->getName());
$interfaces = array_diff($classReflection->getInterfaces(), $parentClass->getInterfaces());
} else { $interfaces = array_diff($interfaces, $parentClass->getInterfaces());
$interfaces = $classReflection->getInterfaces();
} }
$interfaceNames = array(); $interfaceNames = array();
@ -109,20 +116,36 @@ class ClassGenerator extends AbstractGenerator
$cg->setImplementedInterfaces($interfaceNames); $cg->setImplementedInterfaces($interfaceNames);
$properties = array(); $properties = array();
foreach ($classReflection->getProperties() as $reflectionProperty) { foreach ($classReflection->getProperties() as $reflectionProperty) {
if ($reflectionProperty->getDeclaringClass()->getName() == $classReflection->getName()) { if ($reflectionProperty->getDeclaringClass()->getName() == $classReflection->getName()) {
$properties[] = PropertyGenerator::fromReflection($reflectionProperty); $properties[] = PropertyGenerator::fromReflection($reflectionProperty);
} }
} }
$cg->addProperties($properties); $cg->addProperties($properties);
$constants = array();
foreach ($classReflection->getConstants() as $name => $value) {
$constants[] = array(
'name' => $name,
'value' => $value
);
}
$cg->addConstants($constants);
$methods = array(); $methods = array();
foreach ($classReflection->getMethods() as $reflectionMethod) { foreach ($classReflection->getMethods() as $reflectionMethod) {
$className = ($cg->getNamespaceName())? $cg->getNamespaceName() . "\\" . $cg->getName() : $cg->getName(); $className = ($cg->getNamespaceName()) ? $cg->getNamespaceName() . "\\" . $cg->getName() : $cg->getName();
if ($reflectionMethod->getDeclaringClass()->getName() == $className) { if ($reflectionMethod->getDeclaringClass()->getName() == $className) {
$methods[] = MethodGenerator::fromReflection($reflectionMethod); $methods[] = MethodGenerator::fromReflection($reflectionMethod);
} }
} }
$cg->addMethods($methods); $cg->addMethods($methods);
return $cg; return $cg;
@ -208,6 +231,8 @@ class ClassGenerator extends AbstractGenerator
$methods = array(), $methods = array(),
$docBlock = null $docBlock = null
) { ) {
$this->traitUsageGenerator = new TraitUsageGenerator($this);
if ($name !== null) { if ($name !== null) {
$this->setName($name); $this->setName($name);
} }
@ -421,6 +446,114 @@ class ClassGenerator extends AbstractGenerator
return $this->implementedInterfaces; return $this->implementedInterfaces;
} }
/**
* @param string $constantName
*
* @return PropertyGenerator|false
*/
public function getConstant($constantName)
{
if (isset($this->constants[$constantName])) {
return $this->constants[$constantName];
}
return false;
}
/**
* @return PropertyGenerator[] indexed by constant name
*/
public function getConstants()
{
return $this->constants;
}
/**
* @param string $constantName
* @return bool
*/
public function hasConstant($constantName)
{
return isset($this->constants[$constantName]);
}
/**
* Add constant from PropertyGenerator
*
* @param PropertyGenerator $constant
* @throws Exception\InvalidArgumentException
* @return ClassGenerator
*/
public function addConstantFromGenerator(PropertyGenerator $constant)
{
$constantName = $constant->getName();
if (isset($this->constants[$constantName])) {
throw new Exception\InvalidArgumentException(sprintf(
'A constant by name %s already exists in this class.',
$constantName
));
}
if (! $constant->isConst()) {
throw new Exception\InvalidArgumentException(sprintf(
'The value %s is not defined as a constant.',
$constantName
));
}
$this->constants[$constantName] = $constant;
return $this;
}
/**
* Add Constant
*
* @param string $name
* @param string $value
* @throws Exception\InvalidArgumentException
* @return ClassGenerator
*/
public function addConstant($name, $value)
{
if (!is_string($name)) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects string for name',
__METHOD__
));
}
if (empty($value) || !is_string($value)) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects value for constant, value must be a string',
__METHOD__
));
}
return $this->addConstantFromGenerator(new PropertyGenerator($name, $value, PropertyGenerator::FLAG_CONSTANT));
}
/**
* @param PropertyGenerator[]|array[] $constants
*
* @return ClassGenerator
*/
public function addConstants(array $constants)
{
foreach ($constants as $constant) {
if ($constant instanceof PropertyGenerator) {
$this->addPropertyFromGenerator($constant);
} else {
if (is_array($constant)) {
call_user_func_array(array($this, 'addConstant'), $constant);
}
}
}
return $this;
}
/** /**
* @param array $properties * @param array $properties
* @return ClassGenerator * @return ClassGenerator
@ -455,11 +588,18 @@ class ClassGenerator extends AbstractGenerator
{ {
if (!is_string($name)) { if (!is_string($name)) {
throw new Exception\InvalidArgumentException(sprintf( throw new Exception\InvalidArgumentException(sprintf(
'%s expects string for name', '%s::%s expects string for name',
__METHOD__ get_class($this),
__FUNCTION__
)); ));
} }
// backwards compatibility
// @todo remove this on next major version
if ($flags === PropertyGenerator::FLAG_CONSTANT) {
return $this->addConstant($name, $defaultValue);
}
return $this->addPropertyFromGenerator(new PropertyGenerator($name, $defaultValue, $flags)); return $this->addPropertyFromGenerator(new PropertyGenerator($name, $defaultValue, $flags));
} }
@ -481,24 +621,13 @@ class ClassGenerator extends AbstractGenerator
)); ));
} }
$this->properties[$propertyName] = $property; // backwards compatibility
return $this; // @todo remove this on next major version
} if ($property->isConst()) {
return $this->addConstantFromGenerator($property);
/**
* Add a class to "use" classes
*
* @param string $use
* @param string|null $useAlias
* @return ClassGenerator
*/
public function addUse($use, $useAlias = null)
{
if (!empty($useAlias)) {
$use .= ' as ' . $useAlias;
} }
$this->uses[$use] = $use; $this->properties[$propertyName] = $property;
return $this; return $this;
} }
@ -525,6 +654,19 @@ class ClassGenerator extends AbstractGenerator
return false; return false;
} }
/**
* Add a class to "use" classes
*
* @param string $use
* @param string|null $useAlias
* @return ClassGenerator
*/
public function addUse($use, $useAlias = null)
{
$this->traitUsageGenerator->addUse($use, $useAlias);
return $this;
}
/** /**
* Returns the "use" classes * Returns the "use" classes
* *
@ -532,7 +674,7 @@ class ClassGenerator extends AbstractGenerator
*/ */
public function getUses() public function getUses()
{ {
return array_values($this->uses); return $this->traitUsageGenerator->getUses();
} }
/** /**
@ -585,8 +727,9 @@ class ClassGenerator extends AbstractGenerator
) { ) {
if (!is_string($name)) { if (!is_string($name)) {
throw new Exception\InvalidArgumentException(sprintf( throw new Exception\InvalidArgumentException(sprintf(
'%s expects string for name', '%s::%s expects string for name',
__METHOD__ get_class($this),
__FUNCTION__
)); ));
} }
@ -654,6 +797,92 @@ class ClassGenerator extends AbstractGenerator
return isset($this->methods[strtolower($methodName)]); return isset($this->methods[strtolower($methodName)]);
} }
/**
* @inherit Zend\Code\Generator\TraitUsageInterface
*/
public function addTrait($trait)
{
$this->traitUsageGenerator->addTrait($trait);
return $this;
}
/**
* @inherit Zend\Code\Generator\TraitUsageInterface
*/
public function addTraits(array $traits)
{
$this->traitUsageGenerator->addTraits($traits);
return $this;
}
/**
* @inherit Zend\Code\Generator\TraitUsageInterface
*/
public function hasTrait($traitName)
{
return $this->traitUsageGenerator->hasTrait($traitName);
}
/**
* @inherit Zend\Code\Generator\TraitUsageInterface
*/
public function getTraits()
{
return $this->traitUsageGenerator->getTraits();
}
/**
* @inherit Zend\Code\Generator\TraitUsageInterface
*/
public function removeTrait($traitName)
{
return $this->traitUsageGenerator->removeTrait($traitName);
}
/**
* @inherit Zend\Code\Generator\TraitUsageInterface
*/
public function addTraitAlias($method, $alias, $visibility = null)
{
$this->traitUsageGenerator->addTraitAlias($method, $alias, $visibility);
return $this;
}
/**
* @inherit Zend\Code\Generator\TraitUsageInterface
*/
public function getTraitAliases()
{
return $this->traitUsageGenerator->getTraitAliases();
}
/**
* @inherit Zend\Code\Generator\TraitUsageInterface
*/
public function addTraitOverride($method, $traitsToReplace)
{
$this->traitUsageGenerator->addTraitOverride($method, $traitsToReplace);
return $this;
}
/**
* @inherit Zend\Code\Generator\TraitUsageInterface
*/
public function removeTraitOverride($method, $overridesToRemove = null)
{
$this->traitUsageGenerator->removeTraitOverride($method, $overridesToRemove);
return $this;
}
/**
* @inherit Zend\Code\Generator\TraitUsageInterface
*/
public function getTraitOverrides()
{
return $this->traitUsageGenerator->getTraitOverrides();
}
/** /**
* @return bool * @return bool
*/ */
@ -679,7 +908,7 @@ class ClassGenerator extends AbstractGenerator
} }
/** /**
* @return string * @inherit Zend\Code\Generator\GeneratorInterface
*/ */
public function generate() public function generate()
{ {
@ -690,6 +919,7 @@ class ClassGenerator extends AbstractGenerator
} }
} }
$indent = $this->getIndentation();
$output = ''; $output = '';
if (null !== ($namespace = $this->getNamespaceName())) { if (null !== ($namespace = $this->getNamespaceName())) {
@ -697,10 +927,12 @@ class ClassGenerator extends AbstractGenerator
} }
$uses = $this->getUses(); $uses = $this->getUses();
if (!empty($uses)) { if (!empty($uses)) {
foreach ($uses as $use) { foreach ($uses as $use) {
$output .= 'use ' . $use . ';' . self::LINE_FEED; $output .= 'use ' . $use . ';' . self::LINE_FEED;
} }
$output .= self::LINE_FEED; $output .= self::LINE_FEED;
} }
@ -713,31 +945,37 @@ class ClassGenerator extends AbstractGenerator
$output .= 'abstract '; $output .= 'abstract ';
} }
$output .= 'class ' . $this->getName(); $output .= static::OBJECT_TYPE . ' ' . $this->getName();
if (!empty($this->extendedClass)) { if (!empty($this->extendedClass)) {
$output .= ' extends ' . $this->extendedClass; $output .= ' extends ' . $this->extendedClass;
} }
$implemented = $this->getImplementedInterfaces(); $implemented = $this->getImplementedInterfaces();
if (!empty($implemented)) { if (!empty($implemented)) {
$output .= ' implements ' . implode(', ', $implemented); $output .= ' implements ' . implode(', ', $implemented);
} }
$output .= self::LINE_FEED . '{' . self::LINE_FEED . self::LINE_FEED; $output .= self::LINE_FEED . '{' . self::LINE_FEED . self::LINE_FEED;
$output .= $this->traitUsageGenerator->generate();
$constants = $this->getConstants();
foreach ($constants as $constant) {
$output .= $constant->generate() . self::LINE_FEED . self::LINE_FEED;
}
$properties = $this->getProperties(); $properties = $this->getProperties();
if (!empty($properties)) {
foreach ($properties as $property) { foreach ($properties as $property) {
$output .= $property->generate() . self::LINE_FEED . self::LINE_FEED; $output .= $property->generate() . self::LINE_FEED . self::LINE_FEED;
}
} }
$methods = $this->getMethods(); $methods = $this->getMethods();
if (!empty($methods)) {
foreach ($methods as $method) { foreach ($methods as $method) {
$output .= $method->generate() . self::LINE_FEED; $output .= $method->generate() . self::LINE_FEED;
}
} }
$output .= self::LINE_FEED . '}' . self::LINE_FEED; $output .= self::LINE_FEED . '}' . self::LINE_FEED;

View file

@ -152,7 +152,7 @@ class FileGenerator extends AbstractGenerator
} }
/** /**
* @param DocBlockGenerator|string $docBlock * @param DocBlockGenerator|array|string $docBlock
* @throws Exception\InvalidArgumentException * @throws Exception\InvalidArgumentException
* @return FileGenerator * @return FileGenerator
*/ */

View file

@ -61,11 +61,40 @@ class MethodGenerator extends AbstractMemberGenerator
$method->setParameter(ParameterGenerator::fromReflection($reflectionParameter)); $method->setParameter(ParameterGenerator::fromReflection($reflectionParameter));
} }
$method->setBody($reflectionMethod->getBody()); $method->setBody(static::clearBodyIndention($reflectionMethod->getBody()));
return $method; return $method;
} }
/**
* Identify the space indention from the first line and remove this indention
* from all lines
*
* @param string $body
*
* @return string
*/
protected static function clearBodyIndention($body)
{
if (empty($body)) {
return $body;
}
$lines = explode(PHP_EOL, $body);
$indention = str_replace(trim($lines[1]), '', $lines[1]);
foreach ($lines as $key => $line) {
if (substr($line, 0, strlen($indention)) == $indention) {
$lines[$key] = substr($line, strlen($indention));
}
}
$body = implode(PHP_EOL, $lines);
return $body;
}
/** /**
* Generate from array * Generate from array
* *
@ -171,7 +200,7 @@ class MethodGenerator extends AbstractMemberGenerator
} }
/** /**
* @param ParameterGenerator|string $parameter * @param ParameterGenerator|array|string $parameter
* @throws Exception\InvalidArgumentException * @throws Exception\InvalidArgumentException
* @return MethodGenerator * @return MethodGenerator
*/ */
@ -179,7 +208,13 @@ class MethodGenerator extends AbstractMemberGenerator
{ {
if (is_string($parameter)) { if (is_string($parameter)) {
$parameter = new ParameterGenerator($parameter); $parameter = new ParameterGenerator($parameter);
} elseif (!$parameter instanceof ParameterGenerator) { }
if (is_array($parameter)) {
$parameter = ParameterGenerator::fromArray($parameter);
}
if (!$parameter instanceof ParameterGenerator) {
throw new Exception\InvalidArgumentException(sprintf( throw new Exception\InvalidArgumentException(sprintf(
'%s is expecting either a string, array or an instance of %s\ParameterGenerator', '%s is expecting either a string, array or an instance of %s\ParameterGenerator',
__METHOD__, __METHOD__,
@ -187,9 +222,7 @@ class MethodGenerator extends AbstractMemberGenerator
)); ));
} }
$parameterName = $parameter->getName(); $this->parameters[$parameter->getName()] = $parameter;
$this->parameters[$parameterName] = $parameter;
return $this; return $this;
} }

View file

@ -0,0 +1,173 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Code\Generator;
use Zend\Code\Reflection\ClassReflection;
class TraitGenerator extends ClassGenerator
{
const OBJECT_TYPE = 'trait';
/**
* Build a Code Generation Php Object from a Class Reflection
*
* @param ClassReflection $classReflection
* @return TraitGenerator
*/
public static function fromReflection(ClassReflection $classReflection)
{
// class generator
$cg = new static($classReflection->getName());
$cg->setSourceContent($cg->getSourceContent());
$cg->setSourceDirty(false);
if ($classReflection->getDocComment() != '') {
$cg->setDocBlock(DocBlockGenerator::fromReflection($classReflection->getDocBlock()));
}
// set the namespace
if ($classReflection->inNamespace()) {
$cg->setNamespaceName($classReflection->getNamespaceName());
}
$properties = array();
foreach ($classReflection->getProperties() as $reflectionProperty) {
if ($reflectionProperty->getDeclaringClass()->getName() == $classReflection->getName()) {
$properties[] = PropertyGenerator::fromReflection($reflectionProperty);
}
}
$cg->addProperties($properties);
$methods = array();
foreach ($classReflection->getMethods() as $reflectionMethod) {
$className = ($cg->getNamespaceName())
? $cg->getNamespaceName() . '\\' . $cg->getName()
: $cg->getName();
if ($reflectionMethod->getDeclaringClass()->getName() == $className) {
$methods[] = MethodGenerator::fromReflection($reflectionMethod);
}
}
$cg->addMethods($methods);
return $cg;
}
/**
* Generate from array
*
* @configkey name string [required] Class Name
* @configkey filegenerator FileGenerator File generator that holds this class
* @configkey namespacename string The namespace for this class
* @configkey docblock string The docblock information
* @configkey properties
* @configkey methods
*
* @throws Exception\InvalidArgumentException
* @param array $array
* @return TraitGenerator
*/
public static function fromArray(array $array)
{
if (! isset($array['name'])) {
throw new Exception\InvalidArgumentException(
'Class generator requires that a name is provided for this object'
);
}
$cg = new static($array['name']);
foreach ($array as $name => $value) {
// normalize key
switch (strtolower(str_replace(array('.', '-', '_'), '', $name))) {
case 'containingfile':
$cg->setContainingFileGenerator($value);
break;
case 'namespacename':
$cg->setNamespaceName($value);
break;
case 'docblock':
$docBlock = ($value instanceof DocBlockGenerator) ? $value : DocBlockGenerator::fromArray($value);
$cg->setDocBlock($docBlock);
break;
case 'properties':
$cg->addProperties($value);
break;
case 'methods':
$cg->addMethods($value);
break;
}
}
return $cg;
}
/**
* @param array|string $flags
* @return self
*/
public function setFlags($flags)
{
return $this;
}
/**
* @param string $flag
* @return self
*/
public function addFlag($flag)
{
return $this;
}
/**
* @param string $flag
* @return self
*/
public function removeFlag($flag)
{
return $this;
}
/**
* @param bool $isFinal
* @return self
*/
public function setFinal($isFinal)
{
return $this;
}
/**
* @param string $extendedClass
* @return self
*/
public function setExtendedClass($extendedClass)
{
return $this;
}
/**
* @param array $implementedInterfaces
* @return self
*/
public function setImplementedInterfaces(array $implementedInterfaces)
{
return $this;
}
/**
* @param bool $isAbstract
* @return self
*/
public function setAbstract($isAbstract)
{
return $this;
}
}

View file

@ -0,0 +1,353 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Code\Generator;
use Reflection;
use ReflectionMethod;
class TraitUsageGenerator extends AbstractGenerator
{
/**
* @var ClassGenerator
*/
protected $classGenerator;
/**
* @var array Array of trait names
*/
protected $traits = array();
/**
* @var array Array of trait aliases
*/
protected $traitAliases = array();
/**
* @var array Array of trait overrides
*/
protected $traitOverrides = array();
/**
* @var array Array of string names
*/
protected $uses = array();
public function __construct(ClassGenerator $classGenerator)
{
$this->classGenerator = $classGenerator;
}
/**
* @inherit Zend\Code\Generator\TraitUsageInterface
*/
public function addUse($use, $useAlias = null)
{
if (! empty($useAlias)) {
$use .= ' as ' . $useAlias;
}
$this->uses[$use] = $use;
return $this;
}
/**
* @inherit Zend\Code\Generator\TraitUsageInterface
*/
public function getUses()
{
return array_values($this->uses);
}
/**
* @inherit Zend\Code\Generator\TraitUsageInterface
*/
public function addTrait($trait)
{
$traitName = $trait;
if (is_array($trait)) {
if (! array_key_exists('traitName', $trait)) {
throw new Exception\InvalidArgumentException('Missing required value for traitName');
}
$traitName = $trait['traitName'];
if (array_key_exists('aliases', $trait)) {
foreach ($trait['aliases'] as $alias) {
$this->addAlias($alias);
}
}
if (array_key_exists('insteadof', $trait)) {
foreach ($trait['insteadof'] as $insteadof) {
$this->addTraitOverride($insteadof);
}
}
}
if (! $this->hasTrait($traitName)) {
$this->traits[] = $traitName;
}
return $this;
}
/**
* @inherit Zend\Code\Generator\TraitUsageInterface
*/
public function addTraits(array $traits)
{
foreach ($traits as $trait) {
$this->addTrait($trait);
}
return $this;
}
/**
* @inherit Zend\Code\Generator\TraitUsageInterface
*/
public function hasTrait($traitName)
{
return in_array($traitName, $this->traits);
}
/**
* @inherit Zend\Code\Generator\TraitUsageInterface
*/
public function getTraits()
{
return $this->traits;
}
/**
* @inherit Zend\Code\Generator\TraitUsageInterface
*/
public function removeTrait($traitName)
{
$key = array_search($traitName, $this->traits);
if (false !== $key) {
unset($this->traits[$key]);
}
return $this;
}
/**
* @inherit Zend\Code\Generator\TraitUsageInterface
*/
public function addTraitAlias($method, $alias, $visibility = null)
{
$traitAndMethod = $method;
if (is_array($method)) {
if (! array_key_exists('traitName', $method)) {
throw new Exception\InvalidArgumentException('Missing required argument "traitName" for $method');
}
if (! array_key_exists('method', $method)) {
throw new Exception\InvalidArgumentException('Missing required argument "method" for $method');
}
$traitAndMethod = $method['traitName'] . '::' . $method['method'];
}
// Validations
if (false === strpos($traitAndMethod, "::")) {
throw new Exception\InvalidArgumentException(
'Invalid Format: $method must be in the format of trait::method'
);
}
if (! is_string($alias)) {
throw new Exception\InvalidArgumentException('Invalid Alias: $alias must be a string or array.');
}
if ($this->classGenerator->hasMethod($alias)) {
throw new Exception\InvalidArgumentException('Invalid Alias: Method name already exists on this class.');
}
if (null !== $visibility
&& $visibility !== ReflectionMethod::IS_PUBLIC
&& $visibility !== ReflectionMethod::IS_PRIVATE
&& $visibility !== ReflectionMethod::IS_PROTECTED
) {
throw new Exception\InvalidArgumentException(
'Invalid Type: $visibility must of ReflectionMethod::IS_PUBLIC,'
. ' ReflectionMethod::IS_PRIVATE or ReflectionMethod::IS_PROTECTED'
);
}
list($trait, $method) = explode('::', $traitAndMethod);
if (! $this->hasTrait($trait)) {
throw new Exception\InvalidArgumentException('Invalid trait: Trait does not exists on this class');
}
$this->traitAliases[$traitAndMethod] = array(
'alias' => $alias,
'visibility' => $visibility
);
return $this;
}
/**
* @inherit Zend\Code\Generator\TraitUsageInterface
*/
public function getTraitAliases()
{
return $this->traitAliases;
}
/**
* @inherit Zend\Code\Generator\TraitUsageInterface
*/
public function addTraitOverride($method, $traitsToReplace)
{
if (false === is_array($traitsToReplace)) {
$traitsToReplace = array($traitsToReplace);
}
$traitAndMethod = $method;
if (is_array($method)) {
if (! array_key_exists('traitName', $method)) {
throw new Exception\InvalidArgumentException('Missing required argument "traitName" for $method');
}
if (! array_key_exists('method', $method)) {
throw new Exception\InvalidArgumentException('Missing required argument "method" for $method');
}
$traitAndMethod = (string) $method['traitName'] . '::' . (string) $method['method'];
}
// Validations
if (false === strpos($traitAndMethod, "::")) {
throw new Exception\InvalidArgumentException(
'Invalid Format: $method must be in the format of trait::method'
);
}
list($trait, $method) = explode("::", $traitAndMethod);
if (! $this->hasTrait($trait)) {
throw new Exception\InvalidArgumentException('Invalid trait: Trait does not exists on this class');
}
if (! array_key_exists($traitAndMethod, $this->traitOverrides)) {
$this->traitOverrides[$traitAndMethod] = array();
}
foreach ($traitsToReplace as $traitToReplace) {
if (! is_string($traitToReplace)) {
throw new Exception\InvalidArgumentException(
'Invalid Argument: $traitToReplace must be a string or array of strings'
);
}
if (! in_array($traitToReplace, $this->traitOverrides[$traitAndMethod])) {
$this->traitOverrides[$traitAndMethod][] = $traitToReplace;
}
}
return $this;
}
/**
* @inherit Zend\Code\Generator\TraitUsageInterface
*/
public function removeTraitOverride($method, $overridesToRemove = null)
{
if (! array_key_exists($method, $this->traitOverrides)) {
return $this;
}
if (null === $overridesToRemove) {
unset($this->traitOverrides[$method]);
return $this;
}
$overridesToRemove = (! is_array($overridesToRemove))
? array($overridesToRemove)
: $overridesToRemove;
foreach ($overridesToRemove as $traitToRemove) {
$key = array_search($traitToRemove, $this->traitOverrides[$method]);
if (false !== $key) {
unset($this->traitOverrides[$method][$key]);
}
}
return $this;
}
/**
* @inherit Zend\Code\Generator\TraitUsageInterface
*/
public function getTraitOverrides()
{
return $this->traitOverrides;
}
/**
* @inherit Zend\Code\Generator\GeneratorInterface
*/
public function generate()
{
$output = '';
$indent = $this->getIndentation();
$traits = $this->getTraits();
if (empty($traits)) {
return $output;
}
$output .= $indent . 'use ' . implode(', ', $traits);
$aliases = $this->getTraitAliases();
$overrides = $this->getTraitOverrides();
if (empty($aliases) && empty($overrides)) {
$output .= ";" . self::LINE_FEED . self::LINE_FEED;
return $output;
}
$output .= ' {' . self::LINE_FEED;
foreach ($aliases as $method => $alias) {
$visibility = (null !== $alias['visibility'])
? current(Reflection::getModifierNames($alias['visibility'])) . ' '
: '';
// validation check
if ($this->classGenerator->hasMethod($alias['alias'])) {
throw new Exception\RuntimeException(sprintf(
'Generation Error: Aliased method %s already exists on this class',
$alias['alias']
));
}
$output .=
$indent
. $indent
. $method
. ' as '
. $visibility
. $alias['alias']
. ';'
. self::LINE_FEED;
}
foreach ($overrides as $method => $insteadofTraits) {
foreach ($insteadofTraits as $insteadofTrait) {
$output .=
$indent
. $indent
. $method
. ' insteadof '
. $insteadofTrait
. ';'
. self::LINE_FEED;
}
}
$output .= self::LINE_FEED . $indent . '}' . self::LINE_FEED . self::LINE_FEED;
return $output;
}
}

View file

@ -0,0 +1,159 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Code\Generator;
interface TraitUsageInterface
{
/**
* Add a class to "use" classes
*
* @param string $use
* @param string|null $useAlias
* @return self
*/
public function addUse($use, $useAlias = null);
/**
* Returns the "use" classes
*
* @return array
*/
public function getUses();
/**
* Add trait takes an array of trait options or string as arguments.
*
* Array Format:
* key: traitName value: String
*
* key: aliases value: array of arrays
* key: method value: @see addTraitAlias
* key: alias value: @see addTraitAlias
* key: visibility value: @see addTraitAlias
*
* key: insteadof value: array of arrays
* key: method value: @see self::addTraitOverride
* key: traitToReplace value: @see self::addTraitOverride
*
* @param mixed $trait String | Array
* @return self
*/
public function addTrait($trait);
/**
* Add multiple traits. Trait can be an array of trait names or array of trait
* configurations
*
* @param array $traitName Array of string names or configurations (@see addTrait)
* @return self
*/
public function addTraits(array $traits);
/**
* Check to see if the class has a trait defined
*
* @param strint $traitName
* @return bool
*/
public function hasTrait($traitName);
/**
* Get a list of trait names
*
* @return array
*/
public function getTraits();
/**
* Remove a trait by its name
*
* @param $traitName
*/
public function removeTrait($traitName);
/**
* Add a trait alias. This will be used to generate the AS portion of the use statement.
*
* $method:
* This method provides 2 ways for defining the trait method.
* Option 1: String
* Option 2: Array
* key: traitName value: name of trait
* key: method value: trait method
*
* $alias:
* Alias is a string representing the new method name.
*
* $visibilty:
* ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PRIVATE| ReflectionMethod::IS_PROTECTED
*
* @param mixed $method String or Array
* @param string $alias
* @param int $visiblity
*/
public function addTraitAlias($method, $alias, $visibility = null);
/**
* @return array
*/
public function getTraitAliases();
/**
* Add a trait method override. This will be used to generate the INSTEADOF portion of the use
* statement.
*
* $method:
* This method provides 2 ways for defining the trait method.
* Option 1: String Format: <trait name>::<method name>
* Option 2: Array
* key: traitName value: trait name
* key: method value: method name
*
* $traitToReplace:
* The name of the trait that you wish to supersede.
*
* This method provides 2 ways for defining the trait method.
* Option 1: String of trait to replace
* Option 2: Array of strings of traits to replace
* @param mixed $method
* @param mixed $traitToReplace
*/
public function addTraitOverride($method, $traitsToReplace);
/**
* Remove an override for a given trait::method
*
* $method:
* This method provides 2 ways for defining the trait method.
* Option 1: String Format: <trait name>::<method name>
* Option 2: Array
* key: traitName value: trait name
* key: method value: method name
*
* $overridesToRemove:
* The name of the trait that you wish to remove.
*
* This method provides 2 ways for defining the trait method.
* Option 1: String of trait to replace
* Option 2: Array of strings of traits to replace
*
* @param $traitAndMethod
* @param null $overridesToRemove
* @return $this
*/
public function removeTraitOverride($method, $overridesToRemove = null);
/**
* Return trait overrides
*
* @return array
*/
public function getTraitOverrides();
}

View file

@ -374,6 +374,9 @@ class ValueGenerator extends AbstractGenerator
: ' '; : ' ';
$output .= implode(',' . $padding, $outputParts); $output .= implode(',' . $padding, $outputParts);
if ($this->outputMode == self::OUTPUT_MULTIPLE_LINE) { if ($this->outputMode == self::OUTPUT_MULTIPLE_LINE) {
if (count($outputParts) > 0) {
$output .= ',';
}
$output .= self::LINE_FEED . str_repeat($this->indentation, $this->arrayDepth); $output .= self::LINE_FEED . str_repeat($this->indentation, $this->arrayDepth);
} }
$output .= ')'; $output .= ')';

View file

@ -177,6 +177,21 @@ class ClassReflection extends ReflectionClass implements ReflectionInterface
return $methods; return $methods;
} }
public function getTraits()
{
$vals = array();
$traits = parent::getTraits();
if (! $traits) {
return;
}
foreach ($traits as $trait) {
$vals[] = new ClassReflection($trait->getName());
}
return $vals;
}
/** /**
* Get parent reflection class of reflected class * Get parent reflection class of reflected class
* *
@ -230,11 +245,17 @@ class ClassReflection extends ReflectionClass implements ReflectionInterface
return $zendReflections; return $zendReflections;
} }
/**
* @return string
*/
public function toString() public function toString()
{ {
return parent::__toString(); return parent::__toString();
} }
/**
* @return string
*/
public function __toString() public function __toString()
{ {
return parent::__toString(); return parent::__toString();

View file

@ -80,7 +80,7 @@ class MethodTag implements TagInterface, PhpDocTypedTagInterface
public function getReturnType() public function getReturnType()
{ {
if (empty($this->types)) { if (empty($this->types)) {
return null; return;
} }
return $this->types[0]; return $this->types[0];

View file

@ -66,7 +66,7 @@ class PropertyTag implements TagInterface, PhpDocTypedTagInterface
public function getType() public function getType()
{ {
if (empty($this->types)) { if (empty($this->types)) {
return null; return;
} }
return $this->types[0]; return $this->types[0];

View file

@ -247,7 +247,7 @@ class DocBlockReflection implements ReflectionInterface
return; return;
} }
$docComment = $this->docComment; // localize variable $docComment = preg_replace('#[ ]{0,1}\*/$#', '', $this->docComment);
// create a clean docComment // create a clean docComment
$this->cleanDocComment = preg_replace("#[ \t]*(?:/\*\*|\*/|\*)[ ]{0,1}(.*)?#", '$1', $docComment); $this->cleanDocComment = preg_replace("#[ \t]*(?:/\*\*|\*/|\*)[ ]{0,1}(.*)?#", '$1', $docComment);
@ -264,6 +264,9 @@ class DocBlockReflection implements ReflectionInterface
$this->isReflected = true; $this->isReflected = true;
} }
/**
* @return string
*/
public function toString() public function toString()
{ {
$str = "DocBlock [ /* DocBlock */ ] {" . PHP_EOL . PHP_EOL; $str = "DocBlock [ /* DocBlock */ ] {" . PHP_EOL . PHP_EOL;

View file

@ -34,17 +34,17 @@ class FileReflection implements ReflectionInterface
protected $endLine = null; protected $endLine = null;
/** /**
* @var string * @var string[]
*/ */
protected $namespaces = array(); protected $namespaces = array();
/** /**
* @var array * @var string[]
*/ */
protected $uses = array(); protected $uses = array();
/** /**
* @var array * @var string[]
*/ */
protected $requiredFiles = array(); protected $requiredFiles = array();
@ -105,7 +105,7 @@ class FileReflection implements ReflectionInterface
*/ */
public static function export() public static function export()
{ {
return null; return;
} }
/** /**
@ -115,8 +115,7 @@ class FileReflection implements ReflectionInterface
*/ */
public function getFileName() public function getFileName()
{ {
// @todo get file name from path return basename($this->filePath);
return $this->filePath;
} }
/** /**
@ -162,7 +161,7 @@ class FileReflection implements ReflectionInterface
} }
/** /**
* @return array * @return string[]
*/ */
public function getNamespaces() public function getNamespaces()
{ {
@ -175,7 +174,7 @@ class FileReflection implements ReflectionInterface
public function getNamespace() public function getNamespace()
{ {
if (count($this->namespaces) == 0) { if (count($this->namespaces) == 0) {
return null; return;
} }
return $this->namespaces[0]; return $this->namespaces[0];

View file

@ -203,7 +203,7 @@ class FunctionReflection extends ReflectionFunction implements ReflectionInterfa
/** /**
* Get method body * Get method body
* *
* @return string|bool * @return string|false
*/ */
public function getBody() public function getBody()
{ {
@ -249,6 +249,9 @@ class FunctionReflection extends ReflectionFunction implements ReflectionInterfa
return $body; return $body;
} }
/**
* @return string
*/
public function toString() public function toString()
{ {
return $this->__toString(); return $this->__toString();

View file

@ -184,7 +184,7 @@ class MethodReflection extends PhpReflectionMethod implements ReflectionInterfac
* Get method contents * Get method contents
* *
* @param bool $includeDocBlock * @param bool $includeDocBlock
* @return string|bool * @return string
*/ */
public function getContents($includeDocBlock = true) public function getContents($includeDocBlock = true)
{ {
@ -198,7 +198,7 @@ class MethodReflection extends PhpReflectionMethod implements ReflectionInterfac
/** /**
* Get method body * Get method body
* *
* @return string|bool * @return string
*/ */
public function getBody() public function getBody()
{ {
@ -213,7 +213,7 @@ class MethodReflection extends PhpReflectionMethod implements ReflectionInterfac
*/ */
protected function extractMethodContents($bodyOnly = false) protected function extractMethodContents($bodyOnly = false)
{ {
$fileName = $this->getDeclaringClass()->getFileName(); $fileName = $this->getFileName();
if ((class_exists($this->class) && false === $fileName) || ! file_exists($fileName)) { if ((class_exists($this->class) && false === $fileName) || ! file_exists($fileName)) {
return ''; return '';
@ -331,8 +331,8 @@ class MethodReflection extends PhpReflectionMethod implements ReflectionInterfac
/** /**
* Take current position and find any whitespace * Take current position and find any whitespace
* *
* @param $haystack * @param array $haystack
* @param $position * @param int $position
* @return string * @return string
*/ */
protected function extractPrefixedWhitespace($haystack, $position) protected function extractPrefixedWhitespace($haystack, $position)
@ -361,8 +361,8 @@ class MethodReflection extends PhpReflectionMethod implements ReflectionInterfac
/** /**
* Test for ending brace * Test for ending brace
* *
* @param $haystack * @param array $haystack
* @param $position * @param int $position
* @return bool * @return bool
*/ */
protected function isEndingBrace($haystack, $position) protected function isEndingBrace($haystack, $position)
@ -430,8 +430,9 @@ class MethodReflection extends PhpReflectionMethod implements ReflectionInterfac
* Test to see if current position is valid function or * Test to see if current position is valid function or
* closure. Returns true if it's a function and NOT a closure * closure. Returns true if it's a function and NOT a closure
* *
* @param $haystack * @param array $haystack
* @param $position * @param int $position
* @param string $functionName
* @return bool * @return bool
*/ */
protected function isValidFunction($haystack, $position, $functionName = null) protected function isValidFunction($haystack, $position, $functionName = null)
@ -460,11 +461,17 @@ class MethodReflection extends PhpReflectionMethod implements ReflectionInterfac
return $isValid; return $isValid;
} }
/**
* @return string
*/
public function toString() public function toString()
{ {
return parent::__toString(); return parent::__toString();
} }
/**
* @return string
*/
public function __toString() public function __toString()
{ {
return parent::__toString(); return parent::__toString();

View file

@ -41,7 +41,7 @@ class ParameterReflection extends ReflectionParameter implements ReflectionInter
{ {
$phpReflection = parent::getClass(); $phpReflection = parent::getClass();
if ($phpReflection == null) { if ($phpReflection == null) {
return null; return;
} }
$zendReflection = new ClassReflection($phpReflection->getName()); $zendReflection = new ClassReflection($phpReflection->getName());
@ -87,7 +87,7 @@ class ParameterReflection extends ReflectionParameter implements ReflectionInter
$docBlock = $this->getDeclaringFunction()->getDocBlock(); $docBlock = $this->getDeclaringFunction()->getDocBlock();
if (!$docBlock instanceof DocBlockReflection) { if (!$docBlock instanceof DocBlockReflection) {
return null; return;
} }
$params = $docBlock->getTags('param'); $params = $docBlock->getTags('param');
@ -95,14 +95,20 @@ class ParameterReflection extends ReflectionParameter implements ReflectionInter
return $params[$this->getPosition()]->getType(); return $params[$this->getPosition()]->getType();
} }
return null; return;
} }
/**
* @return string
*/
public function toString() public function toString()
{ {
return parent::__toString(); return parent::__toString();
} }
/**
* @return string
*/
public function __toString() public function __toString()
{ {
return parent::__toString(); return parent::__toString();

View file

@ -89,6 +89,9 @@ class PropertyReflection extends PhpReflectionProperty implements ReflectionInte
return $this->annotations; return $this->annotations;
} }
/**
* @return string
*/
public function toString() public function toString()
{ {
return $this->__toString(); return $this->__toString();

View file

@ -160,7 +160,7 @@ class AnnotationScanner extends AnnotationCollection implements ScannerInterface
} }
$currentChar = $stream[$streamIndex]; $currentChar = $stream[$streamIndex];
$matches = array(); $matches = array();
$currentLine = (preg_match('#(.*)\n#', $stream, $matches, null, $streamIndex) === 1) ? $matches[1] : substr($stream, $streamIndex); $currentLine = (preg_match('#(.*?)(?:\n|\r\n?)#', $stream, $matches, null, $streamIndex) === 1) ? $matches[1] : substr($stream, $streamIndex);
if ($currentChar === ' ') { if ($currentChar === ' ') {
$currentWord = (preg_match('#( +)#', $currentLine, $matches) === 1) ? $matches[1] : $currentLine; $currentWord = (preg_match('#( +)#', $currentLine, $matches) === 1) ? $matches[1] : $currentLine;
} else { } else {
@ -213,7 +213,7 @@ class AnnotationScanner extends AnnotationCollection implements ScannerInterface
} }
if ($MACRO_HAS_CONTEXT($CONTEXT_CLASS)) { if ($MACRO_HAS_CONTEXT($CONTEXT_CLASS)) {
if (in_array($currentChar, array(' ', '(', "\n"))) { if (in_array($currentChar, array(' ', '(', "\n", "\r"))) {
$context &= ~$CONTEXT_CLASS; $context &= ~$CONTEXT_CLASS;
$MACRO_TOKEN_ADVANCE(); $MACRO_TOKEN_ADVANCE();
} else { } else {
@ -225,7 +225,22 @@ class AnnotationScanner extends AnnotationCollection implements ScannerInterface
} }
} }
if ($currentChar === "\n") { // Since we don't know what line endings are used in the file, we check for all scenarios. If we find a
// cariage return (\r), we check the next character for a line feed (\n). If so we consume it and act as
// if the cariage return was a line feed.
$lineEnded = $currentChar === "\n";
if ($currentChar === "\r") {
$lineEnded = true;
$nextChar = $MACRO_STREAM_ADVANCE_CHAR();
if ($nextChar !== "\n") {
$streamIndex--;
}
$currentChar = "\n";
}
if ($lineEnded) {
$MACRO_TOKEN_SET_TYPE('ANNOTATION_NEWLINE'); $MACRO_TOKEN_SET_TYPE('ANNOTATION_NEWLINE');
$MACRO_TOKEN_APPEND_CHAR(); $MACRO_TOKEN_APPEND_CHAR();
$MACRO_TOKEN_ADVANCE(); $MACRO_TOKEN_ADVANCE();

View file

@ -9,6 +9,7 @@
namespace Zend\Code\Scanner; namespace Zend\Code\Scanner;
use ReflectionClass;
use Zend\Code\Annotation; use Zend\Code\Annotation;
use Zend\Code\Exception; use Zend\Code\Exception;
use Zend\Code\NameInformation; use Zend\Code\NameInformation;
@ -45,6 +46,11 @@ class ClassScanner implements ScannerInterface
*/ */
protected $lineEnd = null; protected $lineEnd = null;
/**
* @var bool
*/
protected $isTrait = false;
/** /**
* @var bool * @var bool
*/ */
@ -95,6 +101,16 @@ class ClassScanner implements ScannerInterface
*/ */
protected $infos = array(); protected $infos = array();
/**
* @var array
*/
protected $traits = array();
/**
* @var array
*/
protected $methods = array();
/** /**
* @param array $classTokens * @param array $classTokens
* @param NameInformation|null $nameInformation * @param NameInformation|null $nameInformation
@ -202,6 +218,16 @@ class ClassScanner implements ScannerInterface
return $this->isFinal; return $this->isFinal;
} }
/**
* Verify if class is a trait
* @return bool
*/
public function isTrait()
{
$this->scan();
return $this->isTrait;
}
/** /**
* Verify if class is instantiable * Verify if class is instantiable
* *
@ -344,7 +370,9 @@ class ClassScanner implements ScannerInterface
return false; return false;
} }
} else { } else {
throw new Exception\InvalidArgumentException('Invalid constant name of info index type. Must be of type int or string'); throw new Exception\InvalidArgumentException(
'Invalid constant name of info index type. Must be of type int or string'
);
} }
if (!isset($info)) { if (!isset($info)) {
return false; return false;
@ -447,7 +475,9 @@ class ClassScanner implements ScannerInterface
return false; return false;
} }
} else { } else {
throw new Exception\InvalidArgumentException('Invalid property name of info index type. Must be of type int or string'); throw new Exception\InvalidArgumentException(
'Invalid property name of info index type. Must be of type int or string'
);
} }
if (!isset($info)) { if (!isset($info)) {
return false; return false;
@ -480,6 +510,170 @@ class ClassScanner implements ScannerInterface
return false; return false;
} }
/**
* Retrieve any traits used by the class.
*
* @return ClassScanner[]
*/
public function getTraits()
{
if (! empty($this->traits)) {
return $this->traits;
}
// get list of trait names
$traitNames = $this->getTraitNames();
foreach ($traitNames as $traitName) {
$r = new ReflectionClass($traitName);
if (! $r->isTrait()) {
throw new Exception\RuntimeException(sprintf(
'Non-trait class detected as a trait: %s',
$traitName
));
}
$fileName = $r->getFileName();
$file = new FileScanner($fileName);
$this->traits[] = $file->getClass($traitName);
}
return $this->traits;
}
/**
* Retrieve a list of trait names used by this class.
*
* @return array
*/
public function getTraitNames()
{
$return = array();
foreach ($this->infos as $info) {
if ($info['type'] !== 'use') {
continue;
}
if (is_array($info['use_statements'])) {
foreach ($info['use_statements'] as $trait) {
$traitName = $trait;
if ($this->nameInformation instanceof NameInformation) {
$traitName = $this->nameInformation->resolveName($traitName);
}
$return[] = $traitName;
}
}
break;
}
return $return;
}
/**
* Retrieve a list of aliased traits used by the class.
*
* @return array
*/
public function getTraitAliases()
{
$return = array();
foreach ($this->infos as $info) {
if ($info['type'] !== 'use') {
continue;
}
if (is_array($info['aliases'])) {
foreach ($info['aliases'] as $alias) {
if (null === $alias
|| (! empty($alias['type']) && $alias['type'] !== 'as')
) {
continue;
}
// attempt to get fqcn
list($trait, $method) = explode('::', $alias['original']);
if ($this->nameInformation instanceof NameInformation) {
$trait = $this->nameInformation->resolveName($trait);
}
$return[$alias['alias']] = $trait . '::' . $method;
}
}
break;
}
return $return;
}
/**
* Retrieve visibility for a given alias.
*
* @param mixed $aliasName
* @return string
*/
protected function getVisibilityForAlias($aliasName)
{
$return = null;
foreach ($this->infos as $info) {
if ($info['type'] !== 'use') {
continue;
}
if (is_array($info['aliases'])) {
foreach ($info['aliases'] as $alias) {
if (null === $alias
&& (! empty($alias['type']) && $alias['type'] !== 'as')
) {
continue;
}
if ($alias['alias'] === $aliasName) {
$return = $alias['visibility'];
break 2;
}
}
}
break;
}
return $return;
}
/**
* Return an array of key = trait to keep, value = trait::method to ignore
*
* @return array
*/
protected function getBlockedTraitMethods()
{
$return = array();
foreach ($this->infos as $info) {
if ($info['type'] !== 'use') {
continue;
}
if (is_array($info['aliases'])) {
foreach ($info['aliases'] as $alias) {
if (null === $alias
|| (! empty($alias['type']) && $alias['type'] !== 'insteadof')
) {
continue;
}
// attempt to get fqcn
list($trait, $method) = explode('::', $alias['original']);
if ($this->nameInformation instanceof NameInformation) {
$trait = $this->nameInformation->resolveName($alias['alias']);
}
$return[] = $trait . '::' . $method;
}
}
break;
}
return $return;
}
/** /**
* Return a list of method names * Return a list of method names
* *
@ -489,13 +683,10 @@ class ClassScanner implements ScannerInterface
{ {
$this->scan(); $this->scan();
$methods = $this->getMethods();
$return = array(); $return = array();
foreach ($this->infos as $info) { foreach ($methods as $method) {
if ($info['type'] != 'method') { $return[] = $method->getName();
continue;
}
$return[] = $info['name'];
} }
return $return; return $return;
@ -510,16 +701,82 @@ class ClassScanner implements ScannerInterface
{ {
$this->scan(); $this->scan();
$return = array(); if (! empty($this->methods)) {
return $this->methods;
}
foreach ($this->infos as $info) { foreach ($this->infos as $info) {
if ($info['type'] != 'method') { if ($info['type'] !== 'method' && $info['type'] !== 'use') {
continue; continue;
} }
$return[] = $this->getMethod($info['name']); // Merge in trait methods
if ($info['type'] === "use") {
$traitMethods = array();
$traits = $this->getTraits();
$insteadof = $this->getBlockedTraitMethods();
$aliases = $this->getTraitAliases();
foreach ($traits as $trait) {
$tempMethods = $trait->getMethods();
foreach ($tempMethods as $tempMethod) {
$methodFullName = $trait->getName() . '::' . $tempMethod->getName();
$methodAlias = array_search($methodFullName, $aliases);
if (false !== $methodAlias) {
// trait::method is aliased
// clone the tempMethod as we need to change
// the name and possibly the visibility of the
// scanned method.
//
// @todo setName and setVisibility were added to
// MethodScanner to accomplish this, may not be the
// best option, could use ReflectionClass instead?
$newMethod = clone $tempMethod;
$newMethod->setName($methodAlias);
// if visibility exists, change it on the MethodScanner
$visibility = $this->getVisibilityForAlias($methodAlias);
if (null !== $visibility) {
$newMethod->setVisibility($visibility);
}
$traitMethods[$methodAlias] = $newMethod;
} elseif (in_array($methodFullName, $insteadof)) {
// ignore overridden methods
continue;
} else {
if (array_key_exists($tempMethod->getName(), $traitMethods)) {
throw new Exception\RuntimeException(sprintf(
'Trait method %s has not been applied because there are'
. ' collisions with other trait methods see: (insteadof OR as)',
$tempMethod->getName()
));
}
$traitMethods[$tempMethod->getName()] = $tempMethod;
}
}
}
$this->methods = array_merge($this->methods, array_values($traitMethods));
continue;
}
$m = new MethodScanner(
array_slice(
$this->tokens,
$info['tokenStart'],
$info['tokenEnd'] - $info['tokenStart'] + 1
),
$this->nameInformation
);
$m->setClass($this->name);
$m->setScannerClass($this);
$this->methods[] = $m;
} }
return $return; return $this->methods;
} }
/** /**
@ -538,31 +795,19 @@ class ClassScanner implements ScannerInterface
if ($info['type'] != 'method') { if ($info['type'] != 'method') {
throw new Exception\InvalidArgumentException('Index of info offset is not about a method'); throw new Exception\InvalidArgumentException('Index of info offset is not about a method');
} }
} elseif (is_string($methodNameOrInfoIndex)) { $methodNameOrInfoIndex = $info['name'];
$methodFound = false;
foreach ($this->infos as $info) {
if ($info['type'] === 'method' && $info['name'] === $methodNameOrInfoIndex) {
$methodFound = true;
break;
}
}
if (!$methodFound) {
return false;
}
}
if (!isset($info)) {
// @todo find a way to test this
die('Massive Failure, test this');
} }
$m = new MethodScanner( $returnMethod = false;
array_slice($this->tokens, $info['tokenStart'], $info['tokenEnd'] - $info['tokenStart'] + 1), $methods = $this->getMethods();
$this->nameInformation foreach ($methods as $method) {
); if ($method->getName() === $methodNameOrInfoIndex) {
$m->setClass($this->name); $returnMethod = $method;
$m->setScannerClass($this); break;
}
}
return $m; return $returnMethod;
} }
/** /**
@ -575,13 +820,7 @@ class ClassScanner implements ScannerInterface
{ {
$this->scan(); $this->scan();
foreach ($this->infos as $info) { return is_object($this->getMethod($name));
if ($info['type'] === 'method' && $info['name'] === $name) {
return true;
}
}
return false;
} }
public static function export() public static function export()
@ -628,7 +867,14 @@ class ClassScanner implements ScannerInterface
/* /*
* MACRO creation * MACRO creation
*/ */
$MACRO_TOKEN_ADVANCE = function () use (&$tokens, &$tokenIndex, &$token, &$tokenType, &$tokenContent, &$tokenLine) { $MACRO_TOKEN_ADVANCE = function () use (
&$tokens,
&$tokenIndex,
&$token,
&$tokenType,
&$tokenContent,
&$tokenLine
) {
static $lastTokenArray = null; static $lastTokenArray = null;
$tokenIndex = ($tokenIndex === null) ? 0 : $tokenIndex + 1; $tokenIndex = ($tokenIndex === null) ? 0 : $tokenIndex + 1;
if (!isset($tokens[$tokenIndex])) { if (!isset($tokens[$tokenIndex])) {
@ -684,6 +930,7 @@ class ClassScanner implements ScannerInterface
case T_ABSTRACT: case T_ABSTRACT:
case T_CLASS: case T_CLASS:
case T_INTERFACE: case T_INTERFACE:
case T_TRAIT:
// CLASS INFORMATION // CLASS INFORMATION
@ -703,12 +950,22 @@ class ClassScanner implements ScannerInterface
case T_FINAL: case T_FINAL:
$this->isFinal = true; $this->isFinal = true;
goto SCANNER_CLASS_INFO_CONTINUE; goto SCANNER_CLASS_INFO_CONTINUE;
//goto no break needed // goto no break needed
case T_ABSTRACT: case T_ABSTRACT:
$this->isAbstract = true; $this->isAbstract = true;
goto SCANNER_CLASS_INFO_CONTINUE; goto SCANNER_CLASS_INFO_CONTINUE;
//goto no break needed // goto no break needed
case T_TRAIT:
$this->isTrait = true;
$this->shortName = $tokens[$tokenIndex + 2][1];
if ($this->nameInformation && $this->nameInformation->hasNamespace()) {
$this->name = $this->nameInformation->getNamespace() . '\\' . $this->shortName;
} else {
$this->name = $this->shortName;
}
goto SCANNER_CLASS_INFO_CONTINUE;
case T_INTERFACE: case T_INTERFACE:
$this->isInterface = true; $this->isInterface = true;
@ -815,7 +1072,121 @@ class ClassScanner implements ScannerInterface
$MACRO_INFO_ADVANCE(); $MACRO_INFO_ADVANCE();
goto SCANNER_CLASS_BODY_CONTINUE; goto SCANNER_CLASS_BODY_CONTINUE;
//goto no break needed // goto no break needed
case T_USE:
// ensure php backwards compatibility
if (! defined('T_INSTEADOF')) {
define('T_INSTEADOF', 24000);
}
$infos[$infoIndex] = array(
'type' => 'use',
'tokenStart' => $tokenIndex,
'tokenEnd' => null,
'lineStart' => $tokens[$tokenIndex][2],
'lineEnd' => null,
'name' => $namespace,
'use_statements' => array(0 => null),
'aliases' => array(0 => null),
);
$isOriginalName = array(T_STRING, T_DOUBLE_COLON);
$isAlias = array(T_STRING);
$isVisibility = array(T_PRIVATE, T_PROTECTED, T_PUBLIC, T_STATIC);
$isAliasType = array(T_AS, T_INSTEADOF);
$isValidAlias = array_merge($isOriginalName, $isAlias, $isVisibility, $isAliasType);
$useStatementIndex = 0;
$aliasStatementIndex = 0;
$useAliasContext = false;
$useAsContext = false;
// start processing with next token
if ($MACRO_TOKEN_ADVANCE() === false) {
goto SCANNER_END;
}
SCANNER_USE_TOP:
if ($tokenType === null) {
if ($tokenContent === "{") {
$useStatementIndex = 0;
$useAliasContext = true;
$infos[$infoIndex]['aliases'][$useStatementIndex] = array(
'original' => null,
'alias' => null,
'visibility' => null,
'type' => 'as'
);
} elseif ($tokenContent === "}") {
$useAliasContext = false;
goto SCANNER_USE_END;
} elseif ($tokenContent === ';') {
if ($useAliasContext === true) {
$useStatementIndex++;
$useAsContext = false;
}
// only end if we aren't inside braces
if (false === $useAliasContext) {
goto SCANNER_USE_END;
}
} elseif ($tokenContent === ',') {
$useStatementIndex++;
$infos[$infoIndex]['use_statements'][$useStatementIndex] = '';
}
}
// ANALYZE
if ($tokenType !== null) {
// use context
if (false === $useAliasContext) {
if ($tokenType == T_NS_SEPARATOR || $tokenType == T_STRING) {
$infos[$infoIndex]['use_statements'][$useStatementIndex] .= $tokenContent;
}
} else {
if (in_array($tokenType, $isValidAlias)
&& empty($infos[$infoIndex]['aliases'][$useStatementIndex])
) {
$infos[$infoIndex]['aliases'][$useStatementIndex] = array(
'original' => null,
'visibility' => null,
'alias' => null,
'type' => null
);
}
if ($tokenType == T_AS || $tokenType == T_INSTEADOF) {
$useAsContext = true;
$infos[$infoIndex]['aliases'][$useStatementIndex]['type'] = ($tokenType == T_INSTEADOF)
? 'insteadof'
: 'as';
goto SCANNER_USE_CONTINUE;
}
// in alias context
if ($useAsContext === true && in_array($tokenType, $isAlias)) {
$infos[$infoIndex]['aliases'][$useStatementIndex]['alias'] = $tokenContent;
} elseif (in_array($tokenType, $isOriginalName)) {
$infos[$infoIndex]['aliases'][$useStatementIndex]['original'] .= $tokenContent;
} elseif (in_array($tokenType, $isVisibility)) {
//add whitespace (will trim later)
$infos[$infoIndex]['aliases'][$useStatementIndex]['visibility'] = $tokenType;
}
}
}
SCANNER_USE_CONTINUE:
if ($MACRO_TOKEN_ADVANCE() === false) {
goto SCANNER_END;
}
goto SCANNER_USE_TOP;
SCANNER_USE_END:
$MACRO_INFO_ADVANCE();
goto SCANNER_CLASS_BODY_CONTINUE;
case T_DOC_COMMENT: case T_DOC_COMMENT:
case T_PUBLIC: case T_PUBLIC:
@ -846,7 +1217,7 @@ class ClassScanner implements ScannerInterface
$methodBodyStarted = true; $methodBodyStarted = true;
$braceCount++; $braceCount++;
goto SCANNER_CLASS_BODY_MEMBER_CONTINUE; goto SCANNER_CLASS_BODY_MEMBER_CONTINUE;
//goto no break needed // goto no break needed
case '}': case '}':
$braceCount--; $braceCount--;
goto SCANNER_CLASS_BODY_MEMBER_CONTINUE; goto SCANNER_CLASS_BODY_MEMBER_CONTINUE;
@ -882,20 +1253,20 @@ class ClassScanner implements ScannerInterface
$infos[$infoIndex]['name'] = ltrim($tokenContent, '$'); $infos[$infoIndex]['name'] = ltrim($tokenContent, '$');
} }
goto SCANNER_CLASS_BODY_MEMBER_CONTINUE; goto SCANNER_CLASS_BODY_MEMBER_CONTINUE;
//goto no break needed // goto no break needed
case T_FUNCTION: case T_FUNCTION:
$memberContext = 'method'; $memberContext = 'method';
$infos[$infoIndex]['type'] = 'method'; $infos[$infoIndex]['type'] = 'method';
goto SCANNER_CLASS_BODY_MEMBER_CONTINUE; goto SCANNER_CLASS_BODY_MEMBER_CONTINUE;
//goto no break needed // goto no break needed
case T_STRING: case T_STRING:
if ($memberContext === 'method' && null === $infos[$infoIndex]['name']) { if ($memberContext === 'method' && null === $infos[$infoIndex]['name']) {
$infos[$infoIndex]['name'] = $tokenContent; $infos[$infoIndex]['name'] = $tokenContent;
} }
goto SCANNER_CLASS_BODY_MEMBER_CONTINUE; goto SCANNER_CLASS_BODY_MEMBER_CONTINUE;
//goto no break needed // goto no break needed
} }
SCANNER_CLASS_BODY_MEMBER_CONTINUE: SCANNER_CLASS_BODY_MEMBER_CONTINUE:
@ -910,7 +1281,7 @@ class ClassScanner implements ScannerInterface
$memberContext = null; $memberContext = null;
$MACRO_INFO_ADVANCE(); $MACRO_INFO_ADVANCE();
goto SCANNER_CLASS_BODY_CONTINUE; goto SCANNER_CLASS_BODY_CONTINUE;
//goto no break needed // goto no break needed
case null: // no type, is a string case null: // no type, is a string
@ -918,7 +1289,8 @@ class ClassScanner implements ScannerInterface
case '{': case '{':
$braceCount++; $braceCount++;
goto SCANNER_CLASS_BODY_CONTINUE; goto SCANNER_CLASS_BODY_CONTINUE;
//fall-through // goto no break needed
case '}': case '}':
$braceCount--; $braceCount--;
goto SCANNER_CLASS_BODY_CONTINUE; goto SCANNER_CLASS_BODY_CONTINUE;

View file

@ -251,6 +251,55 @@ class MethodScanner implements ScannerInterface
return $this->isStatic; return $this->isStatic;
} }
/**
* Override the given name for a method, this is necessary to
* support traits.
*
* @param $name
* @return self
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Visibility must be of T_PUBLIC, T_PRIVATE or T_PROTECTED
* Needed to support traits
*
* @param $visibility T_PUBLIC | T_PRIVATE | T_PROTECTED
* @return self
* @throws \Zend\Code\Exception
*/
public function setVisibility($visibility)
{
switch (strtolower($visibility)) {
case T_PUBLIC:
$this->isPublic = true;
$this->isPrivate = false;
$this->isProtected = false;
break;
case T_PRIVATE:
$this->isPublic = false;
$this->isPrivate = true;
$this->isProtected = false;
break;
case T_PROTECTED:
$this->isPublic = false;
$this->isPrivate = false;
$this->isProtected = true;
break;
default:
throw new Exception("Invalid visibility argument passed to setVisibility.");
}
return $this;
}
/** /**
* @return int * @return int
*/ */
@ -372,7 +421,14 @@ class MethodScanner implements ScannerInterface
/* /*
* MACRO creation * MACRO creation
*/ */
$MACRO_TOKEN_ADVANCE = function () use (&$tokens, &$tokenIndex, &$token, &$tokenType, &$tokenContent, &$tokenLine) { $MACRO_TOKEN_ADVANCE = function () use (
&$tokens,
&$tokenIndex,
&$token,
&$tokenType,
&$tokenContent,
&$tokenLine
) {
static $lastTokenArray = null; static $lastTokenArray = null;
$tokenIndex = ($tokenIndex === null) ? 0 : $tokenIndex + 1; $tokenIndex = ($tokenIndex === null) ? 0 : $tokenIndex + 1;
if (!isset($tokens[$tokenIndex])) { if (!isset($tokens[$tokenIndex])) {
@ -452,14 +508,12 @@ class MethodScanner implements ScannerInterface
//goto (no break needed); //goto (no break needed);
case T_PROTECTED: case T_PROTECTED:
$this->isProtected = true; $this->setVisibility(T_PROTECTED);
$this->isPublic = false;
goto SCANNER_CONTINUE_SIGNATURE; goto SCANNER_CONTINUE_SIGNATURE;
//goto (no break needed); //goto (no break needed);
case T_PRIVATE: case T_PRIVATE:
$this->isPrivate = true; $this->setVisibility(T_PRIVATE);
$this->isPublic = false;
goto SCANNER_CONTINUE_SIGNATURE; goto SCANNER_CONTINUE_SIGNATURE;
//goto (no break needed); //goto (no break needed);

View file

@ -225,7 +225,7 @@ class TokenArrayScanner implements ScannerInterface
} }
if (!isset($info)) { if (!isset($info)) {
return null; return;
} }
return new NameInformation($info['namespace'], $info['uses']); return new NameInformation($info['namespace'], $info['uses']);
@ -669,7 +669,7 @@ class TokenArrayScanner implements ScannerInterface
} elseif (!is_string($namespace)) { } elseif (!is_string($namespace)) {
throw new Exception\InvalidArgumentException('Invalid namespace provided'); throw new Exception\InvalidArgumentException('Invalid namespace provided');
} elseif (!in_array($namespace, $namespaces)) { } elseif (!in_array($namespace, $namespaces)) {
return null; return;
} }
$uses = array(); $uses = array();

View file

@ -8,11 +8,10 @@
], ],
"homepage": "https://github.com/zendframework/zf2", "homepage": "https://github.com/zendframework/zf2",
"autoload": { "autoload": {
"psr-0": { "psr-4": {
"Zend\\Code\\": "" "Zend\\Code\\": ""
} }
}, },
"target-dir": "Zend/Code",
"require": { "require": {
"php": ">=5.3.23", "php": ">=5.3.23",
"zendframework/zend-eventmanager": "self.version" "zendframework/zend-eventmanager": "self.version"

View file

@ -84,7 +84,7 @@ class AbstractConfigFactory implements ServiceManager\AbstractFactoryInterface
$config = $serviceLocator->get('Config'); $config = $serviceLocator->get('Config');
$this->configs[$requestedName] = $this->configs[$key] = $config[$key]; $this->configs[$requestedName] = $this->configs[$key] = $config[$key];
return $config; return $config[$key];
} }
/** /**
@ -167,6 +167,6 @@ class AbstractConfigFactory implements ServiceManager\AbstractFactoryInterface
return $matches[1]; return $matches[1];
} }
} }
return null; return;
} }
} }

View file

@ -30,13 +30,6 @@ class Config implements Countable, Iterator, ArrayAccess
*/ */
protected $allowModifications; protected $allowModifications;
/**
* Number of elements in configuration data.
*
* @var int
*/
protected $count;
/** /**
* Data within the configuration. * Data within the configuration.
* *
@ -71,8 +64,6 @@ class Config implements Countable, Iterator, ArrayAccess
} else { } else {
$this->data[$key] = $value; $this->data[$key] = $value;
} }
$this->count++;
} }
} }
@ -126,8 +117,6 @@ class Config implements Countable, Iterator, ArrayAccess
} else { } else {
$this->data[$name] = $value; $this->data[$name] = $value;
} }
$this->count++;
} else { } else {
throw new Exception\RuntimeException('Config is read only'); throw new Exception\RuntimeException('Config is read only');
} }
@ -200,7 +189,6 @@ class Config implements Countable, Iterator, ArrayAccess
throw new Exception\InvalidArgumentException('Config is read only'); throw new Exception\InvalidArgumentException('Config is read only');
} elseif (isset($this->data[$name])) { } elseif (isset($this->data[$name])) {
unset($this->data[$name]); unset($this->data[$name]);
$this->count--;
$this->skipNextIteration = true; $this->skipNextIteration = true;
} }
} }
@ -213,7 +201,7 @@ class Config implements Countable, Iterator, ArrayAccess
*/ */
public function count() public function count()
{ {
return $this->count; return count($this->data);
} }
/** /**
@ -360,8 +348,6 @@ class Config implements Countable, Iterator, ArrayAccess
} else { } else {
$this->data[$key] = $value; $this->data[$key] = $value;
} }
$this->count++;
} }
} }

View file

@ -259,7 +259,7 @@ class Token implements ProcessorInterface
if (!is_string($value) && (is_bool($value) || is_numeric($value))) { if (!is_string($value) && (is_bool($value) || is_numeric($value))) {
$stringVal = (string) $value; $stringVal = (string) $value;
$changedVal = strtr($value, $this->map); $changedVal = strtr($stringVal, $this->map);
// replace the value only if a string replacement occurred // replace the value only if a string replacement occurred
if ($changedVal !== $stringVal) { if ($changedVal !== $stringVal) {

View file

@ -72,7 +72,7 @@ class Ini implements ReaderInterface
$this->directory = dirname($filename); $this->directory = dirname($filename);
set_error_handler( set_error_handler(
function ($error, $message = '', $file = '', $line = 0) use ($filename) { function ($error, $message = '') use ($filename) {
throw new Exception\RuntimeException( throw new Exception\RuntimeException(
sprintf('Error reading INI file "%s": %s', $filename, $message), sprintf('Error reading INI file "%s": %s', $filename, $message),
$error $error
@ -101,7 +101,7 @@ class Ini implements ReaderInterface
$this->directory = null; $this->directory = null;
set_error_handler( set_error_handler(
function ($error, $message = '', $file = '', $line = 0) { function ($error, $message = '') {
throw new Exception\RuntimeException( throw new Exception\RuntimeException(
sprintf('Error reading INI string: %s', $message), sprintf('Error reading INI string: %s', $message),
$error $error

View file

@ -65,7 +65,7 @@ class Xml implements ReaderInterface
$this->directory = dirname($filename); $this->directory = dirname($filename);
set_error_handler( set_error_handler(
function ($error, $message = '', $file = '', $line = 0) use ($filename) { function ($error, $message = '') use ($filename) {
throw new Exception\RuntimeException( throw new Exception\RuntimeException(
sprintf('Error reading XML file "%s": %s', $filename, $message), sprintf('Error reading XML file "%s": %s', $filename, $message),
$error $error
@ -100,7 +100,7 @@ class Xml implements ReaderInterface
$this->directory = null; $this->directory = null;
set_error_handler( set_error_handler(
function ($error, $message = '', $file = '', $line = 0) { function ($error, $message = '') {
throw new Exception\RuntimeException( throw new Exception\RuntimeException(
sprintf('Error reading XML string: %s', $message), sprintf('Error reading XML string: %s', $message),
$error $error
@ -155,7 +155,7 @@ class Xml implements ReaderInterface
$child = array('_' => $child); $child = array('_' => $child);
} }
if (! is_array($child) ) { if (! is_array($child)) {
$child = array(); $child = array();
} }

View file

@ -38,7 +38,7 @@ abstract class AbstractWriter implements WriterInterface
} }
set_error_handler( set_error_handler(
function ($error, $message = '', $file = '', $line = 0) use ($filename) { function ($error, $message = '') use ($filename) {
throw new Exception\RuntimeException( throw new Exception\RuntimeException(
sprintf('Error writing to "%s": %s', $filename, $message), sprintf('Error writing to "%s": %s', $filename, $message),
$error $error

View file

@ -76,7 +76,7 @@ class PhpArray extends AbstractWriter
} }
set_error_handler( set_error_handler(
function ($error, $message = '', $file = '', $line = 0) use ($filename) { function ($error, $message = '') use ($filename) {
throw new Exception\RuntimeException( throw new Exception\RuntimeException(
sprintf('Error writing to "%s": %s', $filename, $message), sprintf('Error writing to "%s": %s', $filename, $message),
$error $error

0
library/Zend/Config/WriterPluginManager.php Executable file → Normal file
View file

View file

@ -8,11 +8,10 @@
], ],
"homepage": "https://github.com/zendframework/zf2", "homepage": "https://github.com/zendframework/zf2",
"autoload": { "autoload": {
"psr-0": { "psr-4": {
"Zend\\Config\\": "" "Zend\\Config\\": ""
} }
}, },
"target-dir": "Zend/Config",
"require": { "require": {
"php": ">=5.3.23", "php": ">=5.3.23",
"zendframework/zend-stdlib": "self.version" "zendframework/zend-stdlib": "self.version"

View file

@ -159,7 +159,6 @@ abstract class AbstractAdapter implements AdapterInterface
// Determine charset and dimensions // Determine charset and dimensions
$charset = $this->getCharset(); $charset = $this->getCharset();
$width = $x2 - $x1 + 1; $width = $x2 - $x1 + 1;
$height = $y2 - $y1 + 1;
if ($width <= 2) { if ($width <= 2) {
$lineStyle = static::LINE_NONE; $lineStyle = static::LINE_NONE;

View file

@ -402,6 +402,6 @@ class Posix extends AbstractAdapter
return static::$ansiColorMap[$type][$color]; return static::$ansiColorMap[$type][$color];
} }
return null; return;
} }
} }

View file

@ -299,7 +299,7 @@ class Windows extends Virtual
exec( exec(
'powershell -NonInteractive -NoProfile -NoLogo -OutputFormat Text -Command "' 'powershell -NonInteractive -NoProfile -NoLogo -OutputFormat Text -Command "'
. '[int[]] $mask = ' . join(',', $asciiMask) . ';' . '[int[]] $mask = ' . implode(',', $asciiMask) . ';'
. 'do {' . 'do {'
. '$key = $Host.UI.RawUI.ReadKey(\'NoEcho,IncludeKeyDown\').VirtualKeyCode;' . '$key = $Host.UI.RawUI.ReadKey(\'NoEcho,IncludeKeyDown\').VirtualKeyCode;'
. '} while ( !($mask -contains $key) );' . '} while ( !($mask -contains $key) );'

View file

@ -165,7 +165,6 @@ class WindowsAnsicon extends Posix
/** /**
* Get charset currently in use by this adapter. * Get charset currently in use by this adapter.
* *
* @return CharsetInterface $charset * @return CharsetInterface $charset
*/ */
public function getCharset() public function getCharset()
@ -259,7 +258,7 @@ class WindowsAnsicon extends Posix
$result = $return = null; $result = $return = null;
exec( exec(
'powershell -NonInteractive -NoProfile -NoLogo -OutputFormat Text -Command "' 'powershell -NonInteractive -NoProfile -NoLogo -OutputFormat Text -Command "'
. '[int[]] $mask = '.join(',', $asciiMask).';' . '[int[]] $mask = '.implode(',', $asciiMask).';'
. 'do {' . 'do {'
. '$key = $Host.UI.RawUI.ReadKey(\'NoEcho,IncludeKeyDown\').VirtualKeyCode;' . '$key = $Host.UI.RawUI.ReadKey(\'NoEcho,IncludeKeyDown\').VirtualKeyCode;'
. '} while ( !($mask -contains $key) );' . '} while ( !($mask -contains $key) );'

View file

@ -170,7 +170,7 @@ abstract class Console
{ {
// Check if we are in a console environment // Check if we are in a console environment
if (!static::isConsole()) { if (!static::isConsole()) {
return null; return;
} }
// Check if we're on windows // Check if we're on windows

View file

@ -514,7 +514,7 @@ class Getopt
return $this->options[$flag]; return $this->options[$flag];
} }
} }
return null; return;
} }
/** /**

View file

@ -0,0 +1,183 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Console\Prompt;
use Zend\Console\Exception;
use Zend\Stdlib\ArrayUtils;
final class Checkbox extends AbstractPrompt
{
/**
* @var string
*/
private $promptText;
/**
* @var bool
*/
private $ignoreCase;
/**
* @var array|Transversable
*/
private $options;
/**
* Checked options
* @var array
*/
private $checkedOptions = array();
/**
* If the response should be echoed to the console or not
* @var bool
*/
private $echo;
/**
* Ask the user to select any number of pre-defined options
*
* @param string $promptText The prompt text to display in console
* @param array|Transversable $options Allowed options
* @param bool $echo True to display selected option?
*/
public function __construct($promptText = 'Please select one option (Enter to finish) ', $options = array(), $ignoreCase = true, $echo = false)
{
$this->promptText = (string) $promptText;
$this->setOptions($options);
$this->echo = (bool) $echo;
$this->ignoreCase = (bool) $ignoreCase;
}
/**
* Show a list of options and prompt the user to select any number of them.
*
* @return array Checked options
*/
public function show()
{
$this->checkedOptions = array();
$mask = $this->prepareMask();
do {
$this->showAvailableOptions();
$response = $this->readOption($mask);
if ($this->echo) {
$this->showResponse($response);
}
$this->checkOrUncheckOption($response);
} while ($response != "\r" && $response != "\n");
$this->lastResponse = $this->checkedOptions;
return $this->checkedOptions;
}
/**
* Shows the selected option to the screen
* @param string $response
*/
private function showResponse($response)
{
$console = $this->getConsole();
if (isset($this->options[$response])) {
$console->writeLine($this->options[$response]);
} else {
$console->writeLine();
}
}
/**
* Check or uncheck an option
*
* @param string $response
*/
private function checkOrUncheckOption($response)
{
if ($response != "\r" && $response != "\n" && isset($this->options[$response])) {
$pos = array_search($this->options[$response], $this->checkedOptions);
if ($pos === false) {
$this->checkedOptions[] = $this->options[$response];
} else {
array_splice($this->checkedOptions, $pos, 1);
}
}
}
/**
* Generates a mask to to be used by the readChar method.
*
* @return string
*/
private function prepareMask()
{
$mask = implode("", array_keys($this->options)) . "\r\n";
/**
* Normalize the mask if case is irrelevant
*/
if (!$this->ignoreCase) {
return $mask;
}
$mask = implode("", array_unique(str_split(strtolower($mask) . strtoupper($mask))));
return $mask;
}
/**
* Reads a char from console.
*
* @param string $mask
* @return string
*/
private function readOption($mask)
{
/**
* Read char from console
*/
return $this->getConsole()->readChar($mask);
}
/**
* Shows the available options with checked and unchecked states
*/
private function showAvailableOptions()
{
$console = $this->getConsole();
$console->writeLine($this->promptText);
foreach ($this->options as $k => $v) {
$console->writeLine(' ' . $k . ') ' . (in_array($v, $this->checkedOptions) ? '[X] ' : '[ ] ') . $v);
}
}
/**
* Set allowed options
*
* @param array|\Traversable $options
* @throws Exception\InvalidArgumentException
*/
private function setOptions($options)
{
$options = ArrayUtils::iteratorToArray($options);
if (empty($options)) {
throw new Exception\InvalidArgumentException('Please, specify at least one option');
}
$this->options = $options;
}
}

View file

@ -0,0 +1,70 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Console\Prompt;
final class Password extends AbstractPrompt
{
/**
* @var string
*/
private $promptText;
/**
* @var bool
*/
private $echo;
/**
* Ask the user for a password
*
* @param string $promptText The prompt text to display in console
* @param bool $echo Display the selection after user presses key
*/
public function __construct($promptText = 'Password: ', $echo = false)
{
$this->promptText = (string) $promptText;
$this->echo = (bool) $echo;
}
/**
* Show the prompt to user and return a string.
*
* @return string
*/
public function show()
{
$console = $this->getConsole();
$console->writeLine($this->promptText);
$password = '';
/**
* Read characters from console
*/
while (true) {
$char = $console->readChar();
$console->clearLine();
if (PHP_EOL == $char) {
break;
}
$password .= $char;
if ($this->echo) {
$console->write(str_repeat('*', strlen($password)));
}
}
return $password;
}
}

View file

@ -136,7 +136,7 @@ class DefaultRouteMatcher implements RouteMatcherInterface
* Optional literal param, i.e. * Optional literal param, i.e.
* [something] * [something]
*/ */
elseif (preg_match('/\G\[ *?(?P<name>[a-zA-Z][a-zA-Z0-9\_\-]*?) *?\](?: +|$)/s', $def, $m, 0, $pos)) { elseif (preg_match('/\G\[ *?(?P<name>[a-zA-Z][a-zA-Z0-9\_\-\:]*?) *?\](?: +|$)/s', $def, $m, 0, $pos)) {
$item = array( $item = array(
'name' => $m['name'], 'name' => $m['name'],
'literal' => true, 'literal' => true,
@ -175,7 +175,7 @@ class DefaultRouteMatcher implements RouteMatcherInterface
* Mandatory literal param, i.e. * Mandatory literal param, i.e.
* something * something
*/ */
elseif (preg_match('/\G(?P<name>[a-zA-Z][a-zA-Z0-9\_\-]*?)(?: +|$)/s', $def, $m, 0, $pos)) { elseif (preg_match('/\G(?P<name>[a-zA-Z][a-zA-Z0-9\_\-\:]*?)(?: +|$)/s', $def, $m, 0, $pos)) {
$item = array( $item = array(
'name' => $m['name'], 'name' => $m['name'],
'literal' => true, 'literal' => true,
@ -372,7 +372,7 @@ class DefaultRouteMatcher implements RouteMatcherInterface
array_unique($options); array_unique($options);
// remove prefix // remove prefix
array_walk($options, function (&$val, $key) { array_walk($options, function (&$val) {
$val = ltrim($val, '-'); $val = ltrim($val, '-');
}); });
@ -415,7 +415,7 @@ class DefaultRouteMatcher implements RouteMatcherInterface
array_unique($options); array_unique($options);
// remove prefix // remove prefix
array_walk($options, function (&$val, $key) { array_walk($options, function (&$val) {
$val = ltrim($val, '-'); $val = ltrim($val, '-');
}); });
@ -510,7 +510,7 @@ class DefaultRouteMatcher implements RouteMatcherInterface
$alternativeAliases[] = '(?:' . implode('|', $this->getAliases($alternative)) . ')'; $alternativeAliases[] = '(?:' . implode('|', $this->getAliases($alternative)) . ')';
} }
$regex .= join('|', $alternativeAliases); $regex .= implode('|', $alternativeAliases);
if ($part['hasValue']) { if ($part['hasValue']) {
$regex .= ')(?:\=(?P<value>.*?)$)?$/'; $regex .= ')(?:\=(?P<value>.*?)$)?$/';
@ -568,7 +568,7 @@ class DefaultRouteMatcher implements RouteMatcherInterface
* Drop out if that was a mandatory param * Drop out if that was a mandatory param
*/ */
if ($part['required']) { if ($part['required']) {
return null; return;
} }
/* /*
@ -599,7 +599,7 @@ class DefaultRouteMatcher implements RouteMatcherInterface
array_splice($params, $x, 1); array_splice($params, $x, 1);
} else { } else {
// there are no more params available // there are no more params available
return null; return;
} }
} }
@ -611,7 +611,7 @@ class DefaultRouteMatcher implements RouteMatcherInterface
!preg_match($this->constraints[$part['name']], $value) !preg_match($this->constraints[$part['name']], $value)
) { ) {
// constraint failed // constraint failed
return null; return;
} }
} }
@ -653,7 +653,7 @@ class DefaultRouteMatcher implements RouteMatcherInterface
*/ */
foreach ($params as $param) { foreach ($params as $param) {
if (preg_match('#^\-+#', $param)) { if (preg_match('#^\-+#', $param)) {
return null; // there is an unrecognized flag return; // there is an unrecognized flag
} }
} }
@ -668,7 +668,7 @@ class DefaultRouteMatcher implements RouteMatcherInterface
if (!isset($params[$argPos])) { if (!isset($params[$argPos])) {
if ($part['required']) { if ($part['required']) {
// cannot find required positional param // cannot find required positional param
return null; return;
} else { } else {
// stop matching // stop matching
break; break;
@ -685,7 +685,7 @@ class DefaultRouteMatcher implements RouteMatcherInterface
(isset($part['alternatives']) && !in_array($value, $part['alternatives'])) || (isset($part['alternatives']) && !in_array($value, $part['alternatives'])) ||
(!isset($part['alternatives']) && $value != $part['name']) (!isset($part['alternatives']) && $value != $part['name'])
) { ) {
return null; return;
} }
} }
@ -697,7 +697,7 @@ class DefaultRouteMatcher implements RouteMatcherInterface
!preg_match($this->constraints[$part['name']], $value) !preg_match($this->constraints[$part['name']], $value)
) { ) {
// constraint failed // constraint failed
return null; return;
} }
} }
@ -734,7 +734,7 @@ class DefaultRouteMatcher implements RouteMatcherInterface
* Check if we have consumed all positional parameters * Check if we have consumed all positional parameters
*/ */
if ($argPos < count($params)) { if ($argPos < count($params)) {
return null; // there are extraneous params that were not consumed return; // there are extraneous params that were not consumed
} }
/* /*
@ -772,7 +772,7 @@ class DefaultRouteMatcher implements RouteMatcherInterface
} }
if (!$valid) { if (!$valid) {
return null; return;
} }
return array_replace($this->defaults, $matches); return array_replace($this->defaults, $matches);

View file

@ -8,11 +8,10 @@
], ],
"homepage": "https://github.com/zendframework/zf2", "homepage": "https://github.com/zendframework/zf2",
"autoload": { "autoload": {
"psr-0": { "psr-4": {
"Zend\\Console\\": "" "Zend\\Console\\": ""
} }
}, },
"target-dir": "Zend/Console",
"require": { "require": {
"php": ">=5.3.23", "php": ">=5.3.23",
"zendframework/zend-stdlib": "self.version" "zendframework/zend-stdlib": "self.version"

View file

@ -461,7 +461,7 @@ class BlockCipher
} }
$hmacSize = Hmac::getOutputSize($this->hash); $hmacSize = Hmac::getOutputSize($this->hash);
$hmac = substr($data, 0, $hmacSize); $hmac = substr($data, 0, $hmacSize);
$ciphertext = substr($data, $hmacSize); $ciphertext = substr($data, $hmacSize) ?: '';
if (!$this->binaryOutput) { if (!$this->binaryOutput) {
$ciphertext = base64_decode($ciphertext); $ciphertext = base64_decode($ciphertext);
} }

View file

@ -0,0 +1,374 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Crypt;
use Zend\Crypt\Key\Derivation\Pbkdf2;
use Zend\Crypt\Symmetric\Mcrypt;
use Zend\Crypt\Symmetric\SymmetricInterface;
use Zend\Math\Rand;
/**
* Encrypt/decrypt a file using a symmetric cipher in CBC mode
* then authenticate using HMAC
*/
class FileCipher
{
const BUFFER_SIZE = 1048576; // 16 * 65536 bytes = 1 Mb
/**
* Hash algorithm for Pbkdf2
*
* @var string
*/
protected $pbkdf2Hash = 'sha256';
/**
* Hash algorithm for HMAC
*
* @var string
*/
protected $hash = 'sha256';
/**
* Number of iterations for Pbkdf2
*
* @var int
*/
protected $keyIteration = 10000;
/**
* Key
*
* @var string
*/
protected $key;
/**
* Cipher
*
* @var SymmetricInterface
*/
protected $cipher;
/**
* Constructor
*
* @param SymmetricInterface $cipher
*/
public function __construct()
{
$this->cipher = new Mcrypt;
}
/**
* Set the cipher object
*
* @param SymmetricInterface $cipher
*/
public function setCipher(SymmetricInterface $cipher)
{
$this->cipher = $cipher;
}
/**
* Get the cipher object
*
* @return SymmetricInterface
*/
public function getCipher()
{
return $this->cipher;
}
/**
* Set the number of iterations for Pbkdf2
*
* @param int $num
*/
public function setKeyIteration($num)
{
$this->keyIteration = (int) $num;
}
/**
* Get the number of iterations for Pbkdf2
*
* @return int
*/
public function getKeyIteration()
{
return $this->keyIteration;
}
/**
* Set the encryption/decryption key
*
* @param string $key
* @throws Exception\InvalidArgumentException
*/
public function setKey($key)
{
if (empty($key)) {
throw new Exception\InvalidArgumentException('The key cannot be empty');
}
$this->key = (string) $key;
}
/**
* Get the key
*
* @return string|null
*/
public function getKey()
{
return $this->key;
}
/**
* Set algorithm of the symmetric cipher
*
* @param string $algo
*/
public function setCipherAlgorithm($algo)
{
$this->cipher->setAlgorithm($algo);
}
/**
* Get the cipher algorithm
*
* @return string|bool
*/
public function getCipherAlgorithm()
{
return $this->cipher->getAlgorithm();
}
/**
* Get the supported algorithms of the symmetric cipher
*
* @return array
*/
public function getCipherSupportedAlgorithms()
{
return $this->cipher->getSupportedAlgorithms();
}
/**
* Set the hash algorithm for HMAC authentication
*
* @param string $hash
* @throws Exception\InvalidArgumentException
*/
public function setHashAlgorithm($hash)
{
if (!Hash::isSupported($hash)) {
throw new Exception\InvalidArgumentException(
"The specified hash algorithm '{$hash}' is not supported by Zend\Crypt\Hash"
);
}
$this->hash = (string) $hash;
}
/**
* Get the hash algorithm for HMAC authentication
*
* @return string
*/
public function getHashAlgorithm()
{
return $this->hash;
}
/**
* Set the hash algorithm for the Pbkdf2
*
* @param string $hash
* @throws Exception\InvalidArgumentException
*/
public function setPbkdf2HashAlgorithm($hash)
{
if (!Hash::isSupported($hash)) {
throw new Exception\InvalidArgumentException(
"The specified hash algorithm '{$hash}' is not supported by Zend\Crypt\Hash"
);
}
$this->pbkdf2Hash = (string) $hash;
}
/**
* Get the Pbkdf2 hash algorithm
*
* @return string
*/
public function getPbkdf2HashAlgorithm()
{
return $this->pbkdf2Hash;
}
/**
* Encrypt then authenticate a file using HMAC
*
* @param string $fileIn
* @param string $fileOut
* @return bool
* @throws Exception\InvalidArgumentException
*/
public function encrypt($fileIn, $fileOut)
{
$this->checkFileInOut($fileIn, $fileOut);
if (empty($this->key)) {
throw new Exception\InvalidArgumentException('No key specified for encryption');
}
$read = fopen($fileIn, "r");
$write = fopen($fileOut, "w");
$iv = Rand::getBytes($this->cipher->getSaltSize(), true);
$keys = Pbkdf2::calc($this->getPbkdf2HashAlgorithm(),
$this->getKey(),
$iv,
$this->getKeyIteration(),
$this->cipher->getKeySize() * 2);
$hmac = '';
$size = 0;
$tot = filesize($fileIn);
$padding = $this->cipher->getPadding();
$this->cipher->setKey(substr($keys, 0, $this->cipher->getKeySize()));
$this->cipher->setPadding(new Symmetric\Padding\NoPadding);
$this->cipher->setSalt($iv);
$this->cipher->setMode('cbc');
$hashAlgo = $this->getHashAlgorithm();
$saltSize = $this->cipher->getSaltSize();
$algorithm = $this->cipher->getAlgorithm();
$keyHmac = substr($keys, $this->cipher->getKeySize());
while ($data = fread($read, self::BUFFER_SIZE)) {
$size += strlen($data);
// Padding if last block
if ($size == $tot) {
$this->cipher->setPadding($padding);
}
$result = $this->cipher->encrypt($data);
if ($size <= self::BUFFER_SIZE) {
// Write a placeholder for the HMAC and write the IV
fwrite($write, str_repeat(0, Hmac::getOutputSize($hashAlgo)));
} else {
$result = substr($result, $saltSize);
}
$hmac = Hmac::compute($keyHmac,
$hashAlgo,
$algorithm . $hmac . $result);
$this->cipher->setSalt(substr($result, -1 * $saltSize));
if (fwrite($write, $result) !== strlen($result)) {
return false;
}
}
$result = true;
// write the HMAC at the beginning of the file
fseek($write, 0);
if (fwrite($write, $hmac) !== strlen($hmac)) {
$result = false;
}
fclose($write);
fclose($read);
return $result;
}
/**
* Decrypt a file
*
* @param string $fileIn
* @param string $fileOut
* @param bool $compress
* @return bool
* @throws Exception\InvalidArgumentException
*/
public function decrypt($fileIn, $fileOut)
{
$this->checkFileInOut($fileIn, $fileOut);
if (empty($this->key)) {
throw new Exception\InvalidArgumentException('No key specified for decryption');
}
$read = fopen($fileIn, "r");
$write = fopen($fileOut, "w");
$hmacRead = fread($read, Hmac::getOutputSize($this->getHashAlgorithm()));
$iv = fread($read, $this->cipher->getSaltSize());
$tot = filesize($fileIn);
$hmac = $iv;
$size = strlen($iv) + strlen($hmacRead);
$keys = Pbkdf2::calc($this->getPbkdf2HashAlgorithm(),
$this->getKey(),
$iv,
$this->getKeyIteration(),
$this->cipher->getKeySize() * 2);
$padding = $this->cipher->getPadding();
$this->cipher->setPadding(new Symmetric\Padding\NoPadding);
$this->cipher->setKey(substr($keys, 0, $this->cipher->getKeySize()));
$this->cipher->setMode('cbc');
$blockSize = $this->cipher->getBlockSize();
$hashAlgo = $this->getHashAlgorithm();
$algorithm = $this->cipher->getAlgorithm();
$saltSize = $this->cipher->getSaltSize();
$keyHmac = substr($keys, $this->cipher->getKeySize());
while ($data = fread($read, self::BUFFER_SIZE)) {
$size += strlen($data);
// Unpadding if last block
if ($size + $blockSize >= $tot) {
$this->cipher->setPadding($padding);
$data .= fread($read, $blockSize);
}
$result = $this->cipher->decrypt($iv . $data);
$hmac = Hmac::compute($keyHmac,
$hashAlgo,
$algorithm . $hmac . $data);
$iv = substr($data, -1 * $saltSize);
if (fwrite($write, $result) !== strlen($result)) {
return false;
}
}
fclose($write);
fclose($read);
// check for data integrity
if (!Utils::compareStrings($hmac, $hmacRead)) {
unlink($fileOut);
return false;
}
return true;
}
/**
* Check that input file exists and output file dont
*
* @param string $fileIn
* @param string $fileOut
* @throws Exception\InvalidArgumentException
*/
protected function checkFileInOut($fileIn, $fileOut)
{
if (!file_exists($fileIn)) {
throw new Exception\InvalidArgumentException(sprintf(
"I cannot open the %s file", $fileIn
));
}
if (file_exists($fileOut)) {
throw new Exception\InvalidArgumentException(sprintf(
"The file %s already exists", $fileOut
));
}
}
}

View file

@ -14,7 +14,7 @@ namespace Zend\Crypt\Key\Derivation;
*/ */
class SaltedS2k class SaltedS2k
{ {
protected static $supportedMhashAlgos = array ( protected static $supportedMhashAlgos = array(
'adler32' => MHASH_ADLER32, 'adler32' => MHASH_ADLER32,
'md2' => MHASH_MD2, 'md2' => MHASH_MD2,
'md4' => MHASH_MD4, 'md4' => MHASH_MD4,

View file

@ -315,7 +315,7 @@ abstract class Scrypt
if (PHP_INT_SIZE === 8) { if (PHP_INT_SIZE === 8) {
$v = 'V'; $v = 'V';
} }
list(,$n) = unpack($v, substr($b, -64)); list(, $n) = unpack($v, substr($b, -64));
return $n; return $n;
} }

View file

@ -11,6 +11,7 @@ namespace Zend\Crypt\Password;
use Traversable; use Traversable;
use Zend\Math\Rand; use Zend\Math\Rand;
use Zend\Crypt\Utils;
/** /**
* Apache password authentication * Apache password authentication
@ -126,8 +127,9 @@ class Apache implements PasswordInterface
{ {
if (substr($hash, 0, 5) === '{SHA}') { if (substr($hash, 0, 5) === '{SHA}') {
$hash2 = '{SHA}' . base64_encode(sha1($password, true)); $hash2 = '{SHA}' . base64_encode(sha1($password, true));
return ($hash === $hash2); return Utils::compareStrings($hash, $hash2);
} }
if (substr($hash, 0, 6) === '$apr1$') { if (substr($hash, 0, 6) === '$apr1$') {
$token = explode('$', $hash); $token = explode('$', $hash);
if (empty($token[2])) { if (empty($token[2])) {
@ -136,18 +138,22 @@ class Apache implements PasswordInterface
); );
} }
$hash2 = $this->apr1Md5($password, $token[2]); $hash2 = $this->apr1Md5($password, $token[2]);
return ($hash === $hash2); return Utils::compareStrings($hash, $hash2);
} }
if (strlen($hash) > 13) { // digest
$bcryptPattern = '/\$2[ay]?\$[0-9]{2}\$[' . addcslashes(static::BASE64, '+/') . '\.]{53}/';
if (strlen($hash) > 13 && ! preg_match($bcryptPattern, $hash)) { // digest
if (empty($this->userName) || empty($this->authName)) { if (empty($this->userName) || empty($this->authName)) {
throw new Exception\RuntimeException( throw new Exception\RuntimeException(
'You must specify UserName and AuthName (realm) to verify the digest' 'You must specify UserName and AuthName (realm) to verify the digest'
); );
} }
$hash2 = md5($this->userName . ':' . $this->authName . ':' .$password); $hash2 = md5($this->userName . ':' . $this->authName . ':' .$password);
return ($hash === $hash2); return Utils::compareStrings($hash, $hash2);
} }
return (crypt($password, $hash) === $hash);
return Utils::compareStrings($hash, crypt($password, $hash));
} }
/** /**

View file

@ -12,6 +12,7 @@ namespace Zend\Crypt\Password;
use Traversable; use Traversable;
use Zend\Math\Rand; use Zend\Math\Rand;
use Zend\Stdlib\ArrayUtils; use Zend\Stdlib\ArrayUtils;
use Zend\Crypt\Utils;
/** /**
* Bcrypt algorithm using crypt() function of PHP * Bcrypt algorithm using crypt() function of PHP
@ -101,10 +102,7 @@ class Bcrypt implements PasswordInterface
public function verify($password, $hash) public function verify($password, $hash)
{ {
$result = crypt($password, $hash); $result = crypt($password, $hash);
if ($result === $hash) { return Utils::compareStrings($hash, $result);
return true;
}
return false;
} }
/** /**

View file

@ -0,0 +1,45 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Crypt\Password;
use Zend\Crypt\Hash;
/**
* Bcrypt algorithm using crypt() function of PHP with password
* hashed using SHA2 to allow for passwords >72 characters.
*/
class BcryptSha extends Bcrypt
{
/**
* BcryptSha
*
* @param string $password
* @throws Exception\RuntimeException
* @return string
*/
public function create($password)
{
return parent::create(Hash::compute('sha256', $password));
}
/**
* Verify if a password is correct against a hash value
*
* @param string $password
* @param string $hash
* @throws Exception\RuntimeException when the hash is unable to be processed
* @return bool
*/
public function verify($password, $hash)
{
return parent::verify(Hash::compute('sha256', $password), $hash);
}
}

View file

@ -414,14 +414,11 @@ class DiffieHellman
switch ($outputFormat) { switch ($outputFormat) {
case self::FORMAT_BINARY: case self::FORMAT_BINARY:
return $this->math->intToBin($number); return $this->math->intToBin($number);
break;
case self::FORMAT_BTWOC: case self::FORMAT_BTWOC:
return $this->math->intToBin($number, true); return $this->math->intToBin($number, true);
break;
case self::FORMAT_NUMBER: case self::FORMAT_NUMBER:
default: default:
return $number; return $number;
break;
} }
} }

4
library/Zend/Crypt/Symmetric/Mcrypt.php Executable file → Normal file
View file

@ -258,7 +258,7 @@ class Mcrypt implements SymmetricInterface
public function getKey() public function getKey()
{ {
if (empty($this->key)) { if (empty($this->key)) {
return null; return;
} }
return substr($this->key, 0, $this->getKeySize()); return substr($this->key, 0, $this->getKeySize());
} }
@ -433,7 +433,7 @@ class Mcrypt implements SymmetricInterface
public function getSalt() public function getSalt()
{ {
if (empty($this->iv)) { if (empty($this->iv)) {
return null; return;
} }
if (strlen($this->iv) < $this->getSaltSize()) { if (strlen($this->iv) < $this->getSaltSize()) {
throw new Exception\RuntimeException( throw new Exception\RuntimeException(

View file

@ -0,0 +1,39 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Crypt\Symmetric\Padding;
/**
* No Padding
*/
class NoPadding implements PaddingInterface
{
/**
* Pad a string, do nothing and return the string
*
* @param string $string
* @param int $blockSize
* @return string
*/
public function pad($string, $blockSize = 32)
{
return $string;
}
/**
* Unpad a string, do nothing and return the string
*
* @param string $string
* @return string
*/
public function strip($string)
{
return $string;
}
}

View file

@ -21,6 +21,7 @@ class Utils
* is found in the two buffers. That makes possible of leaking * is found in the two buffers. That makes possible of leaking
* timing information useful to an attacker attempting to iteratively guess * timing information useful to an attacker attempting to iteratively guess
* the unknown string (e.g. password). * the unknown string (e.g. password).
* The length will leak.
* *
* @param string $expected * @param string $expected
* @param string $actual * @param string $actual
@ -30,6 +31,11 @@ class Utils
{ {
$expected = (string) $expected; $expected = (string) $expected;
$actual = (string) $actual; $actual = (string) $actual;
if (function_exists('hash_equals')) {
return hash_equals($expected, $actual);
}
$lenExpected = strlen($expected); $lenExpected = strlen($expected);
$lenActual = strlen($actual); $lenActual = strlen($actual);
$len = min($lenExpected, $lenActual); $len = min($lenExpected, $lenActual);

View file

@ -8,11 +8,10 @@
], ],
"homepage": "https://github.com/zendframework/zf2", "homepage": "https://github.com/zendframework/zf2",
"autoload": { "autoload": {
"psr-0": { "psr-4": {
"Zend\\Crypt\\": "" "Zend\\Crypt\\": ""
} }
}, },
"target-dir": "Zend/Crypt",
"require": { "require": {
"php": ">=5.3.23", "php": ">=5.3.23",
"zendframework/zend-math": "self.version", "zendframework/zend-math": "self.version",

View file

@ -9,7 +9,6 @@
namespace Zend\Db\Adapter; namespace Zend\Db\Adapter;
trait AdapterAwareTrait trait AdapterAwareTrait
{ {
/** /**

View file

@ -0,0 +1,135 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Db\Adapter\Driver;
use Zend\Db\Adapter\Profiler\ProfilerAwareInterface;
use Zend\Db\Adapter\Profiler\ProfilerInterface;
abstract class AbstractConnection implements ConnectionInterface, ProfilerAwareInterface
{
/**
* @var array
*/
protected $connectionParameters = array();
/**
* @var string|null
*/
protected $driverName;
/**
* @var boolean
*/
protected $inTransaction = false;
/**
* Nested transactions count.
*
* @var integer
*/
protected $nestedTransactionsCount = 0;
/**
* @var ProfilerInterface|null
*/
protected $profiler;
/**
* @var resource|null
*/
protected $resource;
/**
* {@inheritDoc}
*/
public function disconnect()
{
if ($this->isConnected()) {
$this->resource = null;
}
return $this;
}
/**
* Get connection parameters
*
* @return array
*/
public function getConnectionParameters()
{
return $this->connectionParameters;
}
/**
* Get driver name
*
* @return null|string
*/
public function getDriverName()
{
return $this->driverName;
}
/**
* @return null|ProfilerInterface
*/
public function getProfiler()
{
return $this->profiler;
}
/**
* {@inheritDoc}
*
* @return resource
*/
public function getResource()
{
if (!$this->isConnected()) {
$this->connect();
}
return $this->resource;
}
/**
* Checks whether the connection is in transaction state.
*
* @return boolean
*/
public function inTransaction()
{
return $this->inTransaction;
}
/**
* @param array $connectionParameters
* @return self
*/
public function setConnectionParameters(array $connectionParameters)
{
$this->connectionParameters = $connectionParameters;
return $this;
}
/**
* {@inheritDoc}
*
* @return self
*/
public function setProfiler(ProfilerInterface $profiler)
{
$this->profiler = $profiler;
return $this;
}
}

144
library/Zend/Db/Adapter/Driver/IbmDb2/Connection.php Executable file → Normal file
View file

@ -9,39 +9,16 @@
namespace Zend\Db\Adapter\Driver\IbmDb2; namespace Zend\Db\Adapter\Driver\IbmDb2;
use Zend\Db\Adapter\Driver\ConnectionInterface; use Zend\Db\Adapter\Driver\AbstractConnection;
use Zend\Db\Adapter\Exception; use Zend\Db\Adapter\Exception;
use Zend\Db\Adapter\Profiler;
class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface class Connection extends AbstractConnection
{ {
/** /**
* @var IbmDb2 * @var IbmDb2
*/ */
protected $driver = null; protected $driver = null;
/**
* @var array
*/
protected $connectionParameters = null;
/**
* @var resource
*/
protected $resource = null;
/**
* @var Profiler\ProfilerInterface
*/
protected $profiler = null;
/**
* In transaction
*
* @var bool
*/
protected $inTransaction = false;
/** /**
* i5 OS * i5 OS
* *
@ -78,54 +55,19 @@ class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface
/** /**
* Set driver * Set driver
* *
* @param IbmDb2 $driver * @param IbmDb2 $driver
* @return Connection * @return self
*/ */
public function setDriver(IbmDb2 $driver) public function setDriver(IbmDb2 $driver)
{ {
$this->driver = $driver; $this->driver = $driver;
return $this; return $this;
} }
/** /**
* @param Profiler\ProfilerInterface $profiler * @param resource $resource DB2 resource
* @return Connection * @return self
*/
public function setProfiler(Profiler\ProfilerInterface $profiler)
{
$this->profiler = $profiler;
return $this;
}
/**
* @return null|Profiler\ProfilerInterface
*/
public function getProfiler()
{
return $this->profiler;
}
/**
* @param array $connectionParameters
* @return Connection
*/
public function setConnectionParameters(array $connectionParameters)
{
$this->connectionParameters = $connectionParameters;
return $this;
}
/**
* @return array
*/
public function getConnectionParameters()
{
return $this->connectionParameters;
}
/**
* @param resource $resource DB2 resource
* @return Connection
*/ */
public function setResource($resource) public function setResource($resource)
{ {
@ -133,13 +75,12 @@ class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface
throw new Exception\InvalidArgumentException('The resource provided must be of type "DB2 Connection"'); throw new Exception\InvalidArgumentException('The resource provided must be of type "DB2 Connection"');
} }
$this->resource = $resource; $this->resource = $resource;
return $this; return $this;
} }
/** /**
* Get current schema * {@inheritDoc}
*
* @return string
*/ */
public function getCurrentSchema() public function getCurrentSchema()
{ {
@ -148,23 +89,12 @@ class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface
} }
$info = db2_server_info($this->resource); $info = db2_server_info($this->resource);
return (isset($info->DB_NAME) ? $info->DB_NAME : ''); return (isset($info->DB_NAME) ? $info->DB_NAME : '');
} }
/** /**
* Get resource * {@inheritDoc}
*
* @return mixed
*/
public function getResource()
{
return $this->resource;
}
/**
* Connect
*
* @return self
*/ */
public function connect() public function connect()
{ {
@ -183,7 +113,7 @@ class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface
} }
} }
return null; return;
}; };
$database = $findParameterValue(array('database', 'db')); $database = $findParameterValue(array('database', 'db'));
@ -206,9 +136,7 @@ class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface
} }
/** /**
* Is connected * {@inheritDoc}
*
* @return bool
*/ */
public function isConnected() public function isConnected()
{ {
@ -216,9 +144,7 @@ class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface
} }
/** /**
* Disconnect * {@inheritDoc}
*
* @return ConnectionInterface
*/ */
public function disconnect() public function disconnect()
{ {
@ -231,9 +157,7 @@ class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface
} }
/** /**
* Begin transaction * {@inheritDoc}
*
* @return ConnectionInterface
*/ */
public function beginTransaction() public function beginTransaction()
{ {
@ -250,23 +174,12 @@ class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface
$this->prevAutocommit = db2_autocommit($this->resource); $this->prevAutocommit = db2_autocommit($this->resource);
db2_autocommit($this->resource, DB2_AUTOCOMMIT_OFF); db2_autocommit($this->resource, DB2_AUTOCOMMIT_OFF);
$this->inTransaction = true; $this->inTransaction = true;
return $this; return $this;
} }
/** /**
* In transaction * {@inheritDoc}
*
* @return bool
*/
public function inTransaction()
{
return $this->inTransaction;
}
/**
* Commit
*
* @return ConnectionInterface
*/ */
public function commit() public function commit()
{ {
@ -283,21 +196,22 @@ class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface
} }
$this->inTransaction = false; $this->inTransaction = false;
return $this; return $this;
} }
/** /**
* Rollback * Rollback
* *
* @return ConnectionInterface * @return Connection
*/ */
public function rollback() public function rollback()
{ {
if (!$this->resource) { if (!$this->isConnected()) {
throw new Exception\RuntimeException('Must be connected before you can rollback.'); throw new Exception\RuntimeException('Must be connected before you can rollback.');
} }
if (!$this->inTransaction) { if (!$this->inTransaction()) {
throw new Exception\RuntimeException('Must call beginTransaction() before you can rollback.'); throw new Exception\RuntimeException('Must call beginTransaction() before you can rollback.');
} }
@ -310,14 +224,12 @@ class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface
} }
$this->inTransaction = false; $this->inTransaction = false;
return $this; return $this;
} }
/** /**
* Execute * {@inheritDoc}
*
* @param string $sql
* @return Result
*/ */
public function execute($sql) public function execute($sql)
{ {
@ -346,10 +258,7 @@ class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface
} }
/** /**
* Get last generated id * {@inheritDoc}
*
* @param null $name Ignored
* @return int
*/ */
public function getLastGeneratedValue($name = null) public function getLastGeneratedValue($name = null)
{ {
@ -367,7 +276,8 @@ class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface
return $this->i5; return $this->i5;
} }
$this->i5 = php_uname('s') == 'OS400' ? true : false; $this->i5 = (php_uname('s') == 'OS400');
return $this->i5; return $this->i5;
} }
} }

0
library/Zend/Db/Adapter/Driver/IbmDb2/IbmDb2.php Executable file → Normal file
View file

4
library/Zend/Db/Adapter/Driver/IbmDb2/Result.php Executable file → Normal file
View file

@ -119,7 +119,7 @@ class Result implements ResultInterface
*/ */
public function buffer() public function buffer()
{ {
return null; return;
} }
/** /**
@ -187,6 +187,6 @@ class Result implements ResultInterface
*/ */
public function count() public function count()
{ {
return null; return;
} }
} }

View file

@ -194,7 +194,7 @@ class Statement implements StatementInterface, Profiler\ProfilerAwareInterface
/** /**
* Execute * Execute
* *
* @param null $parameters * @param null|array|ParameterContainer $parameters
* @return Result * @return Result
*/ */
public function execute($parameters = null) public function execute($parameters = null)

View file

@ -9,45 +9,25 @@
namespace Zend\Db\Adapter\Driver\Mysqli; namespace Zend\Db\Adapter\Driver\Mysqli;
use Zend\Db\Adapter\Driver\ConnectionInterface; use Zend\Db\Adapter\Driver\AbstractConnection;
use Zend\Db\Adapter\Exception; use Zend\Db\Adapter\Exception;
use Zend\Db\Adapter\Profiler;
class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface class Connection extends AbstractConnection
{ {
/** /**
* @var Mysqli * @var Mysqli
*/ */
protected $driver = null; protected $driver = null;
/**
* @var Profiler\ProfilerInterface
*/
protected $profiler = null;
/**
* Connection parameters
*
* @var array
*/
protected $connectionParameters = array();
/** /**
* @var \mysqli * @var \mysqli
*/ */
protected $resource = null; protected $resource = null;
/**
* In transaction
*
* @var bool
*/
protected $inTransaction = false;
/** /**
* Constructor * Constructor
* *
* @param array|mysqli|null $connectionInfo * @param array|mysqli|null $connectionInfo
* @throws \Zend\Db\Adapter\Exception\InvalidArgumentException * @throws \Zend\Db\Adapter\Exception\InvalidArgumentException
*/ */
public function __construct($connectionInfo = null) public function __construct($connectionInfo = null)
@ -62,59 +42,18 @@ class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface
} }
/** /**
* @param Mysqli $driver * @param Mysqli $driver
* @return Connection * @return self
*/ */
public function setDriver(Mysqli $driver) public function setDriver(Mysqli $driver)
{ {
$this->driver = $driver; $this->driver = $driver;
return $this; return $this;
} }
/** /**
* @param Profiler\ProfilerInterface $profiler * {@inheritDoc}
* @return Connection
*/
public function setProfiler(Profiler\ProfilerInterface $profiler)
{
$this->profiler = $profiler;
return $this;
}
/**
* @return null|Profiler\ProfilerInterface
*/
public function getProfiler()
{
return $this->profiler;
}
/**
* Set connection parameters
*
* @param array $connectionParameters
* @return Connection
*/
public function setConnectionParameters(array $connectionParameters)
{
$this->connectionParameters = $connectionParameters;
return $this;
}
/**
* Get connection parameters
*
* @return array
*/
public function getConnectionParameters()
{
return $this->connectionParameters;
}
/**
* Get current schema
*
* @return string
*/ */
public function getCurrentSchema() public function getCurrentSchema()
{ {
@ -125,6 +64,7 @@ class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface
/** @var $result \mysqli_result */ /** @var $result \mysqli_result */
$result = $this->resource->query('SELECT DATABASE()'); $result = $this->resource->query('SELECT DATABASE()');
$r = $result->fetch_row(); $r = $result->fetch_row();
return $r[0]; return $r[0];
} }
@ -132,30 +72,17 @@ class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface
* Set resource * Set resource
* *
* @param \mysqli $resource * @param \mysqli $resource
* @return Connection * @return self
*/ */
public function setResource(\mysqli $resource) public function setResource(\mysqli $resource)
{ {
$this->resource = $resource; $this->resource = $resource;
return $this; return $this;
} }
/** /**
* Get resource * {@inheritDoc}
*
* @return \mysqli
*/
public function getResource()
{
$this->connect();
return $this->resource;
}
/**
* Connect
*
* @throws Exception\RuntimeException
* @return Connection
*/ */
public function connect() public function connect()
{ {
@ -173,6 +100,7 @@ class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface
return $p[$name]; return $p[$name];
} }
} }
return; return;
}; };
@ -217,9 +145,7 @@ class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface
} }
/** /**
* Is connected * {@inheritDoc}
*
* @return bool
*/ */
public function isConnected() public function isConnected()
{ {
@ -227,9 +153,7 @@ class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface
} }
/** /**
* Disconnect * {@inheritDoc}
*
* @return void
*/ */
public function disconnect() public function disconnect()
{ {
@ -240,9 +164,7 @@ class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface
} }
/** /**
* Begin transaction * {@inheritDoc}
*
* @return void
*/ */
public function beginTransaction() public function beginTransaction()
{ {
@ -252,43 +174,32 @@ class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface
$this->resource->autocommit(false); $this->resource->autocommit(false);
$this->inTransaction = true; $this->inTransaction = true;
return $this;
} }
/** /**
* In transaction * {@inheritDoc}
*
* @return bool
*/
public function inTransaction()
{
return $this->inTransaction;
}
/**
* Commit
*
* @return void
*/ */
public function commit() public function commit()
{ {
if (!$this->resource) { if (!$this->isConnected()) {
$this->connect(); $this->connect();
} }
$this->resource->commit(); $this->resource->commit();
$this->inTransaction = false; $this->inTransaction = false;
$this->resource->autocommit(true); $this->resource->autocommit(true);
return $this;
} }
/** /**
* Rollback * {@inheritDoc}
*
* @throws Exception\RuntimeException
* @return Connection
*/ */
public function rollback() public function rollback()
{ {
if (!$this->resource) { if (!$this->isConnected()) {
throw new Exception\RuntimeException('Must be connected before you can rollback.'); throw new Exception\RuntimeException('Must be connected before you can rollback.');
} }
@ -298,15 +209,15 @@ class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface
$this->resource->rollback(); $this->resource->rollback();
$this->resource->autocommit(true); $this->resource->autocommit(true);
$this->inTransaction = false;
return $this; return $this;
} }
/** /**
* Execute * {@inheritDoc}
* *
* @param string $sql
* @throws Exception\InvalidQueryException * @throws Exception\InvalidQueryException
* @return Result
*/ */
public function execute($sql) public function execute($sql)
{ {
@ -330,14 +241,12 @@ class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface
} }
$resultPrototype = $this->driver->createResult(($resultResource === true) ? $this->resource : $resultResource); $resultPrototype = $this->driver->createResult(($resultResource === true) ? $this->resource : $resultResource);
return $resultPrototype; return $resultPrototype;
} }
/** /**
* Get last generated id * {@inheritDoc}
*
* @param null $name Ignored
* @return int
*/ */
public function getLastGeneratedValue($name = null) public function getLastGeneratedValue($name = null)
{ {

View file

@ -187,7 +187,6 @@ class Result implements
*/ */
protected function loadDataFromMysqliStatement() protected function loadDataFromMysqliStatement()
{ {
$data = null;
// build the default reference based bind structure, if it does not already exist // build the default reference based bind structure, if it does not already exist
if ($this->statementBindValues['keys'] === null) { if ($this->statementBindValues['keys'] === null) {
$this->statementBindValues['keys'] = array(); $this->statementBindValues['keys'] = array();

View file

@ -219,7 +219,7 @@ class Statement implements StatementInterface, Profiler\ProfilerAwareInterface
/** /**
* Execute * Execute
* *
* @param ParameterContainer|array $parameters * @param null|array|ParameterContainer $parameters
* @throws Exception\RuntimeException * @throws Exception\RuntimeException
* @return mixed * @return mixed
*/ */

155
library/Zend/Db/Adapter/Driver/Oci8/Connection.php Executable file → Normal file
View file

@ -9,45 +9,20 @@
namespace Zend\Db\Adapter\Driver\Oci8; namespace Zend\Db\Adapter\Driver\Oci8;
use Zend\Db\Adapter\Driver\ConnectionInterface; use Zend\Db\Adapter\Driver\AbstractConnection;
use Zend\Db\Adapter\Exception; use Zend\Db\Adapter\Exception;
use Zend\Db\Adapter\Profiler;
class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface class Connection extends AbstractConnection
{ {
/** /**
* @var Oci8 * @var Oci8
*/ */
protected $driver = null; protected $driver = null;
/**
* @var Profiler\ProfilerInterface
*/
protected $profiler = null;
/**
* Connection parameters
*
* @var array
*/
protected $connectionParameters = array();
/**
* @var
*/
protected $resource = null;
/**
* In transaction
*
* @var bool
*/
protected $inTransaction = false;
/** /**
* Constructor * Constructor
* *
* @param array|resource|null $connectionInfo * @param array|resource|null $connectionInfo
* @throws \Zend\Db\Adapter\Exception\InvalidArgumentException * @throws \Zend\Db\Adapter\Exception\InvalidArgumentException
*/ */
public function __construct($connectionInfo = null) public function __construct($connectionInfo = null)
@ -62,59 +37,18 @@ class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface
} }
/** /**
* @param Oci8 $driver * @param Oci8 $driver
* @return Connection * @return self
*/ */
public function setDriver(Oci8 $driver) public function setDriver(Oci8 $driver)
{ {
$this->driver = $driver; $this->driver = $driver;
return $this; return $this;
} }
/** /**
* @param Profiler\ProfilerInterface $profiler * {@inheritDoc}
* @return Connection
*/
public function setProfiler(Profiler\ProfilerInterface $profiler)
{
$this->profiler = $profiler;
return $this;
}
/**
* @return null|Profiler\ProfilerInterface
*/
public function getProfiler()
{
return $this->profiler;
}
/**
* Set connection parameters
*
* @param array $connectionParameters
* @return Connection
*/
public function setConnectionParameters(array $connectionParameters)
{
$this->connectionParameters = $connectionParameters;
return $this;
}
/**
* Get connection parameters
*
* @return array
*/
public function getConnectionParameters()
{
return $this->connectionParameters;
}
/**
* Get current schema
*
* @return string
*/ */
public function getCurrentSchema() public function getCurrentSchema()
{ {
@ -126,6 +60,7 @@ class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface
$stmt = oci_parse($this->resource, $query); $stmt = oci_parse($this->resource, $query);
oci_execute($stmt); oci_execute($stmt);
$dbNameArray = oci_fetch_array($stmt, OCI_ASSOC); $dbNameArray = oci_fetch_array($stmt, OCI_ASSOC);
return $dbNameArray['current_schema']; return $dbNameArray['current_schema'];
} }
@ -133,7 +68,7 @@ class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface
* Set resource * Set resource
* *
* @param resource $resource * @param resource $resource
* @return Connection * @return self
*/ */
public function setResource($resource) public function setResource($resource)
{ {
@ -141,24 +76,12 @@ class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface
throw new Exception\InvalidArgumentException('A resource of type "oci8 connection" was expected'); throw new Exception\InvalidArgumentException('A resource of type "oci8 connection" was expected');
} }
$this->resource = $resource; $this->resource = $resource;
return $this; return $this;
} }
/** /**
* Get resource * {@inheritDoc}
*
* @return \oci8
*/
public function getResource()
{
$this->connect();
return $this->resource;
}
/**
* Connect
*
* @return Connection
*/ */
public function connect() public function connect()
{ {
@ -176,7 +99,8 @@ class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface
return $p[$name]; return $p[$name];
} }
} }
return null;
return;
}; };
// http://www.php.net/manual/en/function.oci-connect.php // http://www.php.net/manual/en/function.oci-connect.php
@ -211,9 +135,7 @@ class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface
} }
/** /**
* Is connected * {@inheritDoc}
*
* @return bool
*/ */
public function isConnected() public function isConnected()
{ {
@ -221,7 +143,7 @@ class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface
} }
/** /**
* Disconnect * {@inheritDoc}
*/ */
public function disconnect() public function disconnect()
{ {
@ -231,7 +153,7 @@ class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface
} }
/** /**
* Begin transaction * {@inheritDoc}
*/ */
public function beginTransaction() public function beginTransaction()
{ {
@ -241,48 +163,42 @@ class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface
// A transaction begins when the first SQL statement that changes data is executed with oci_execute() using the OCI_NO_AUTO_COMMIT flag. // A transaction begins when the first SQL statement that changes data is executed with oci_execute() using the OCI_NO_AUTO_COMMIT flag.
$this->inTransaction = true; $this->inTransaction = true;
return $this;
} }
/** /**
* In transaction * {@inheritDoc}
*
* @return bool
*/
public function inTransaction()
{
return $this->inTransaction;
}
/**
* Commit
*/ */
public function commit() public function commit()
{ {
if (!$this->resource) { if (!$this->isConnected()) {
$this->connect(); $this->connect();
} }
if ($this->inTransaction) { if ($this->inTransaction()) {
$valid = oci_commit($this->resource); $valid = oci_commit($this->resource);
if ($valid === false) { if ($valid === false) {
$e = oci_error($this->resource); $e = oci_error($this->resource);
throw new Exception\InvalidQueryException($e['message'], $e['code']); throw new Exception\InvalidQueryException($e['message'], $e['code']);
} }
$this->inTransaction = false;
} }
return $this;
} }
/** /**
* Rollback * {@inheritDoc}
*
* @return Connection
*/ */
public function rollback() public function rollback()
{ {
if (!$this->resource) { if (!$this->isConnected()) {
throw new Exception\RuntimeException('Must be connected before you can rollback.'); throw new Exception\RuntimeException('Must be connected before you can rollback.');
} }
if (!$this->inTransaction) { if (!$this->inTransaction()) {
throw new Exception\RuntimeException('Must call commit() before you can rollback.'); throw new Exception\RuntimeException('Must call commit() before you can rollback.');
} }
@ -292,14 +208,13 @@ class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface
throw new Exception\InvalidQueryException($e['message'], $e['code']); throw new Exception\InvalidQueryException($e['message'], $e['code']);
} }
$this->inTransaction = false;
return $this; return $this;
} }
/** /**
* Execute * {@inheritDoc}
*
* @param string $sql
* @return Result
*/ */
public function execute($sql) public function execute($sql)
{ {
@ -329,18 +244,16 @@ class Connection implements ConnectionInterface, Profiler\ProfilerAwareInterface
} }
$resultPrototype = $this->driver->createResult($ociStmt); $resultPrototype = $this->driver->createResult($ociStmt);
return $resultPrototype; return $resultPrototype;
} }
/** /**
* Get last generated id * {@inheritDoc}
*
* @param null $name Ignored
* @return int
*/ */
public function getLastGeneratedValue($name = null) public function getLastGeneratedValue($name = null)
{ {
// @todo Get Last Generated Value in Connection (this might not apply) // @todo Get Last Generated Value in Connection (this might not apply)
return null; return;
} }
} }

0
library/Zend/Db/Adapter/Driver/Oci8/Oci8.php Executable file → Normal file
View file

6
library/Zend/Db/Adapter/Driver/Oci8/Result.php Executable file → Normal file
View file

@ -82,7 +82,7 @@ class Result implements Iterator, ResultInterface
*/ */
public function buffer() public function buffer()
{ {
return null; return;
} }
/** /**
@ -202,7 +202,7 @@ class Result implements Iterator, ResultInterface
public function count() public function count()
{ {
// @todo OCI8 row count in Driver Result // @todo OCI8 row count in Driver Result
return null; return;
} }
/** /**
@ -219,6 +219,6 @@ class Result implements Iterator, ResultInterface
public function getGeneratedValue() public function getGeneratedValue()
{ {
// @todo OCI8 generated value in Driver Result // @todo OCI8 generated value in Driver Result
return null; return;
} }
} }

View file

@ -213,7 +213,7 @@ class Statement implements StatementInterface, Profiler\ProfilerAwareInterface
/** /**
* Execute * Execute
* *
* @param ParameterContainer $parameters * @param null|array|ParameterContainer $parameters
* @return mixed * @return mixed
*/ */
public function execute($parameters = null) public function execute($parameters = null)
@ -305,7 +305,12 @@ class Statement implements StatementInterface, Profiler\ProfilerAwareInterface
$type = SQLT_CHR; $type = SQLT_CHR;
} }
oci_bind_by_name($this->resource, $name, $value, -1, $type); $maxLength = -1;
if ($this->parameterContainer->offsetHasMaxLength($name)) {
$maxLength = $this->parameterContainer->offsetGetMaxLength($name);
}
oci_bind_by_name($this->resource, $name, $value, $maxLength, $type);
} }
} }
} }

Some files were not shown because too many files have changed in this diff Show more