first commit

This commit is contained in:
gauvainboiche
2020-03-03 22:45:25 +01:00
commit 058c2110e9
4420 changed files with 598645 additions and 0 deletions

View File

@@ -0,0 +1,124 @@
<?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 Traversable;
abstract class AbstractGenerator implements GeneratorInterface
{
/**
* Line feed to use in place of EOL
*/
const LINE_FEED = "\n";
/**
* @var bool
*/
protected $isSourceDirty = true;
/**
* @var int|string 4 spaces by default
*/
protected $indentation = ' ';
/**
* @var string
*/
protected $sourceContent = null;
/**
* @param array $options
*/
public function __construct($options = array())
{
if ($options) {
$this->setOptions($options);
}
}
/**
* @param bool $isSourceDirty
* @return AbstractGenerator
*/
public function setSourceDirty($isSourceDirty = true)
{
$this->isSourceDirty = (bool) $isSourceDirty;
return $this;
}
/**
* @return bool
*/
public function isSourceDirty()
{
return $this->isSourceDirty;
}
/**
* @param string $indentation
* @return AbstractGenerator
*/
public function setIndentation($indentation)
{
$this->indentation = (string) $indentation;
return $this;
}
/**
* @return string
*/
public function getIndentation()
{
return $this->indentation;
}
/**
* @param string $sourceContent
* @return AbstractGenerator
*/
public function setSourceContent($sourceContent)
{
$this->sourceContent = (string) $sourceContent;
return $this;
}
/**
* @return string
*/
public function getSourceContent()
{
return $this->sourceContent;
}
/**
* @param array|Traversable $options
* @throws Exception\InvalidArgumentException
* @return AbstractGenerator
*/
public function setOptions($options)
{
if (!is_array($options) && !$options instanceof Traversable) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects an array or Traversable object; received "%s"',
__METHOD__,
(is_object($options) ? get_class($options) : gettype($options))
));
}
foreach ($options as $optionName => $optionValue) {
$methodName = 'set' . $optionName;
if (method_exists($this, $methodName)) {
$this->{$methodName}($optionValue);
}
}
return $this;
}
}

View File

@@ -0,0 +1,224 @@
<?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;
abstract class AbstractMemberGenerator extends AbstractGenerator
{
/**#@+
* @const int Flags for construction usage
*/
const FLAG_ABSTRACT = 0x01;
const FLAG_FINAL = 0x02;
const FLAG_STATIC = 0x04;
const FLAG_PUBLIC = 0x10;
const FLAG_PROTECTED = 0x20;
const FLAG_PRIVATE = 0x40;
/**#@-*/
/**#@+
* @param const string
*/
const VISIBILITY_PUBLIC = 'public';
const VISIBILITY_PROTECTED = 'protected';
const VISIBILITY_PRIVATE = 'private';
/**#@-*/
/**
* @var DocBlockGenerator
*/
protected $docBlock = null;
/**
* @var string
*/
protected $name = null;
/**
* @var int
*/
protected $flags = self::FLAG_PUBLIC;
/**
* @param int|array $flags
* @return AbstractMemberGenerator
*/
public function setFlags($flags)
{
if (is_array($flags)) {
$flagsArray = $flags;
$flags = 0x00;
foreach ($flagsArray as $flag) {
$flags |= $flag;
}
}
// check that visibility is one of three
$this->flags = $flags;
return $this;
}
/**
* @param int $flag
* @return AbstractMemberGenerator
*/
public function addFlag($flag)
{
$this->setFlags($this->flags | $flag);
return $this;
}
/**
* @param int $flag
* @return AbstractMemberGenerator
*/
public function removeFlag($flag)
{
$this->setFlags($this->flags & ~$flag);
return $this;
}
/**
* @param bool $isAbstract
* @return AbstractMemberGenerator
*/
public function setAbstract($isAbstract)
{
return (($isAbstract) ? $this->addFlag(self::FLAG_ABSTRACT) : $this->removeFlag(self::FLAG_ABSTRACT));
}
/**
* @return bool
*/
public function isAbstract()
{
return (bool) ($this->flags & self::FLAG_ABSTRACT);
}
/**
* @param bool $isFinal
* @return AbstractMemberGenerator
*/
public function setFinal($isFinal)
{
return (($isFinal) ? $this->addFlag(self::FLAG_FINAL) : $this->removeFlag(self::FLAG_FINAL));
}
/**
* @return bool
*/
public function isFinal()
{
return (bool) ($this->flags & self::FLAG_FINAL);
}
/**
* @param bool $isStatic
* @return AbstractMemberGenerator
*/
public function setStatic($isStatic)
{
return (($isStatic) ? $this->addFlag(self::FLAG_STATIC) : $this->removeFlag(self::FLAG_STATIC));
}
/**
* @return bool
*/
public function isStatic()
{
return (bool) ($this->flags & self::FLAG_STATIC); // is FLAG_STATIC in flags
}
/**
* @param string $visibility
* @return AbstractMemberGenerator
*/
public function setVisibility($visibility)
{
switch ($visibility) {
case self::VISIBILITY_PUBLIC:
$this->removeFlag(self::FLAG_PRIVATE | self::FLAG_PROTECTED); // remove both
$this->addFlag(self::FLAG_PUBLIC);
break;
case self::VISIBILITY_PROTECTED:
$this->removeFlag(self::FLAG_PUBLIC | self::FLAG_PRIVATE); // remove both
$this->addFlag(self::FLAG_PROTECTED);
break;
case self::VISIBILITY_PRIVATE:
$this->removeFlag(self::FLAG_PUBLIC | self::FLAG_PROTECTED); // remove both
$this->addFlag(self::FLAG_PRIVATE);
break;
}
return $this;
}
/**
* @return string
*/
public function getVisibility()
{
switch (true) {
case ($this->flags & self::FLAG_PROTECTED):
return self::VISIBILITY_PROTECTED;
case ($this->flags & self::FLAG_PRIVATE):
return self::VISIBILITY_PRIVATE;
default:
return self::VISIBILITY_PUBLIC;
}
}
/**
* @param string $name
* @return AbstractMemberGenerator
*/
public function setName($name)
{
$this->name = (string) $name;
return $this;
}
/**
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* @param DocBlockGenerator|string $docBlock
* @throws Exception\InvalidArgumentException
* @return AbstractMemberGenerator
*/
public function setDocBlock($docBlock)
{
if (is_string($docBlock)) {
$docBlock = new DocBlockGenerator($docBlock);
} elseif (!$docBlock instanceof DocBlockGenerator) {
throw new Exception\InvalidArgumentException(sprintf(
'%s is expecting either a string, array or an instance of %s\DocBlockGenerator',
__METHOD__,
__NAMESPACE__
));
}
$this->docBlock = $docBlock;
return $this;
}
/**
* @return DocBlockGenerator
*/
public function getDocBlock()
{
return $this->docBlock;
}
}

View File

@@ -0,0 +1,44 @@
<?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;
class BodyGenerator extends AbstractGenerator
{
/**
* @var string
*/
protected $content = null;
/**
* @param string $content
* @return BodyGenerator
*/
public function setContent($content)
{
$this->content = (string) $content;
return $this;
}
/**
* @return string
*/
public function getContent()
{
return $this->content;
}
/**
* @return string
*/
public function generate()
{
return $this->getContent();
}
}

View File

@@ -0,0 +1,987 @@
<?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 ClassGenerator extends AbstractGenerator
{
const OBJECT_TYPE = "class";
const FLAG_ABSTRACT = 0x01;
const FLAG_FINAL = 0x02;
/**
* @var FileGenerator
*/
protected $containingFileGenerator = null;
/**
* @var string
*/
protected $namespaceName = null;
/**
* @var DocBlockGenerator
*/
protected $docBlock = null;
/**
* @var string
*/
protected $name = null;
/**
* @var bool
*/
protected $flags = 0x00;
/**
* @var string
*/
protected $extendedClass = null;
/**
* @var array Array of string names
*/
protected $implementedInterfaces = array();
/**
* @var PropertyGenerator[] Array of properties
*/
protected $properties = array();
/**
* @var PropertyGenerator[] Array of constants
*/
protected $constants = array();
/**
* @var MethodGenerator[] Array of methods
*/
protected $methods = array();
/**
* @var TraitUsageGenerator Object to encapsulate trait usage logic
*/
protected $traitUsageGenerator;
/**
* Build a Code Generation Php Object from a Class Reflection
*
* @param ClassReflection $classReflection
* @return ClassGenerator
*/
public static function fromReflection(ClassReflection $classReflection)
{
$cg = new static($classReflection->getName());
$cg->setSourceContent($cg->getSourceContent());
$cg->setSourceDirty(false);
if ($classReflection->getDocComment() != '') {
$cg->setDocBlock(DocBlockGenerator::fromReflection($classReflection->getDocBlock()));
}
$cg->setAbstract($classReflection->isAbstract());
// set the namespace
if ($classReflection->inNamespace()) {
$cg->setNamespaceName($classReflection->getNamespaceName());
}
/* @var \Zend\Code\Reflection\ClassReflection $parentClass */
$parentClass = $classReflection->getParentClass();
$interfaces = $classReflection->getInterfaces();
if ($parentClass) {
$cg->setExtendedClass($parentClass->getName());
$interfaces = array_diff($interfaces, $parentClass->getInterfaces());
}
$interfaceNames = array();
foreach ($interfaces as $interface) {
/* @var \Zend\Code\Reflection\ClassReflection $interface */
$interfaceNames[] = $interface->getName();
}
$cg->setImplementedInterfaces($interfaceNames);
$properties = array();
foreach ($classReflection->getProperties() as $reflectionProperty) {
if ($reflectionProperty->getDeclaringClass()->getName() == $classReflection->getName()) {
$properties[] = PropertyGenerator::fromReflection($reflectionProperty);
}
}
$cg->addProperties($properties);
$constants = array();
foreach ($classReflection->getConstants() as $name => $value) {
$constants[] = array(
'name' => $name,
'value' => $value
);
}
$cg->addConstants($constants);
$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 flags int Flags, one of ClassGenerator::FLAG_ABSTRACT ClassGenerator::FLAG_FINAL
* @configkey extendedclass string Class which this class is extending
* @configkey implementedinterfaces
* @configkey properties
* @configkey methods
*
* @throws Exception\InvalidArgumentException
* @param array $array
* @return ClassGenerator
*/
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 'flags':
$cg->setFlags($value);
break;
case 'extendedclass':
$cg->setExtendedClass($value);
break;
case 'implementedinterfaces':
$cg->setImplementedInterfaces($value);
break;
case 'properties':
$cg->addProperties($value);
break;
case 'methods':
$cg->addMethods($value);
break;
}
}
return $cg;
}
/**
* @param string $name
* @param string $namespaceName
* @param array|string $flags
* @param string $extends
* @param array $interfaces
* @param array $properties
* @param array $methods
* @param DocBlockGenerator $docBlock
*/
public function __construct(
$name = null,
$namespaceName = null,
$flags = null,
$extends = null,
$interfaces = array(),
$properties = array(),
$methods = array(),
$docBlock = null
) {
$this->traitUsageGenerator = new TraitUsageGenerator($this);
if ($name !== null) {
$this->setName($name);
}
if ($namespaceName !== null) {
$this->setNamespaceName($namespaceName);
}
if ($flags !== null) {
$this->setFlags($flags);
}
if ($properties !== array()) {
$this->addProperties($properties);
}
if ($extends !== null) {
$this->setExtendedClass($extends);
}
if (is_array($interfaces)) {
$this->setImplementedInterfaces($interfaces);
}
if ($methods !== array()) {
$this->addMethods($methods);
}
if ($docBlock !== null) {
$this->setDocBlock($docBlock);
}
}
/**
* @param string $name
* @return ClassGenerator
*/
public function setName($name)
{
if (strstr($name, '\\')) {
$namespace = substr($name, 0, strrpos($name, '\\'));
$name = substr($name, strrpos($name, '\\') + 1);
$this->setNamespaceName($namespace);
}
$this->name = $name;
return $this;
}
/**
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* @param string $namespaceName
* @return ClassGenerator
*/
public function setNamespaceName($namespaceName)
{
$this->namespaceName = $namespaceName;
return $this;
}
/**
* @return string
*/
public function getNamespaceName()
{
return $this->namespaceName;
}
/**
* @param FileGenerator $fileGenerator
* @return ClassGenerator
*/
public function setContainingFileGenerator(FileGenerator $fileGenerator)
{
$this->containingFileGenerator = $fileGenerator;
return $this;
}
/**
* @return FileGenerator
*/
public function getContainingFileGenerator()
{
return $this->containingFileGenerator;
}
/**
* @param DocBlockGenerator $docBlock
* @return ClassGenerator
*/
public function setDocBlock(DocBlockGenerator $docBlock)
{
$this->docBlock = $docBlock;
return $this;
}
/**
* @return DocBlockGenerator
*/
public function getDocBlock()
{
return $this->docBlock;
}
/**
* @param array|string $flags
* @return ClassGenerator
*/
public function setFlags($flags)
{
if (is_array($flags)) {
$flagsArray = $flags;
$flags = 0x00;
foreach ($flagsArray as $flag) {
$flags |= $flag;
}
}
// check that visibility is one of three
$this->flags = $flags;
return $this;
}
/**
* @param string $flag
* @return ClassGenerator
*/
public function addFlag($flag)
{
$this->setFlags($this->flags | $flag);
return $this;
}
/**
* @param string $flag
* @return ClassGenerator
*/
public function removeFlag($flag)
{
$this->setFlags($this->flags & ~$flag);
return $this;
}
/**
* @param bool $isAbstract
* @return ClassGenerator
*/
public function setAbstract($isAbstract)
{
return (($isAbstract) ? $this->addFlag(self::FLAG_ABSTRACT) : $this->removeFlag(self::FLAG_ABSTRACT));
}
/**
* @return bool
*/
public function isAbstract()
{
return (bool) ($this->flags & self::FLAG_ABSTRACT);
}
/**
* @param bool $isFinal
* @return ClassGenerator
*/
public function setFinal($isFinal)
{
return (($isFinal) ? $this->addFlag(self::FLAG_FINAL) : $this->removeFlag(self::FLAG_FINAL));
}
/**
* @return bool
*/
public function isFinal()
{
return ($this->flags & self::FLAG_FINAL);
}
/**
* @param string $extendedClass
* @return ClassGenerator
*/
public function setExtendedClass($extendedClass)
{
$this->extendedClass = $extendedClass;
return $this;
}
/**
* @return string
*/
public function getExtendedClass()
{
return $this->extendedClass;
}
/**
* @param array $implementedInterfaces
* @return ClassGenerator
*/
public function setImplementedInterfaces(array $implementedInterfaces)
{
$this->implementedInterfaces = $implementedInterfaces;
return $this;
}
/**
* @return array
*/
public function getImplementedInterfaces()
{
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
* @return ClassGenerator
*/
public function addProperties(array $properties)
{
foreach ($properties as $property) {
if ($property instanceof PropertyGenerator) {
$this->addPropertyFromGenerator($property);
} else {
if (is_string($property)) {
$this->addProperty($property);
} elseif (is_array($property)) {
call_user_func_array(array($this, 'addProperty'), $property);
}
}
}
return $this;
}
/**
* Add Property from scalars
*
* @param string $name
* @param string|array $defaultValue
* @param int $flags
* @throws Exception\InvalidArgumentException
* @return ClassGenerator
*/
public function addProperty($name, $defaultValue = null, $flags = PropertyGenerator::FLAG_PUBLIC)
{
if (!is_string($name)) {
throw new Exception\InvalidArgumentException(sprintf(
'%s::%s expects string for name',
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));
}
/**
* Add property from PropertyGenerator
*
* @param PropertyGenerator $property
* @throws Exception\InvalidArgumentException
* @return ClassGenerator
*/
public function addPropertyFromGenerator(PropertyGenerator $property)
{
$propertyName = $property->getName();
if (isset($this->properties[$propertyName])) {
throw new Exception\InvalidArgumentException(sprintf(
'A property by name %s already exists in this class.',
$propertyName
));
}
// backwards compatibility
// @todo remove this on next major version
if ($property->isConst()) {
return $this->addConstantFromGenerator($property);
}
$this->properties[$propertyName] = $property;
return $this;
}
/**
* @return PropertyGenerator[]
*/
public function getProperties()
{
return $this->properties;
}
/**
* @param string $propertyName
* @return PropertyGenerator|false
*/
public function getProperty($propertyName)
{
foreach ($this->getProperties() as $property) {
if ($property->getName() == $propertyName) {
return $property;
}
}
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
*
* @return array
*/
public function getUses()
{
return $this->traitUsageGenerator->getUses();
}
/**
* @param string $propertyName
* @return bool
*/
public function hasProperty($propertyName)
{
return isset($this->properties[$propertyName]);
}
/**
* @param array $methods
* @return ClassGenerator
*/
public function addMethods(array $methods)
{
foreach ($methods as $method) {
if ($method instanceof MethodGenerator) {
$this->addMethodFromGenerator($method);
} else {
if (is_string($method)) {
$this->addMethod($method);
} elseif (is_array($method)) {
call_user_func_array(array($this, 'addMethod'), $method);
}
}
}
return $this;
}
/**
* Add Method from scalars
*
* @param string $name
* @param array $parameters
* @param int $flags
* @param string $body
* @param string $docBlock
* @throws Exception\InvalidArgumentException
* @return ClassGenerator
*/
public function addMethod(
$name = null,
array $parameters = array(),
$flags = MethodGenerator::FLAG_PUBLIC,
$body = null,
$docBlock = null
) {
if (!is_string($name)) {
throw new Exception\InvalidArgumentException(sprintf(
'%s::%s expects string for name',
get_class($this),
__FUNCTION__
));
}
return $this->addMethodFromGenerator(new MethodGenerator($name, $parameters, $flags, $body, $docBlock));
}
/**
* Add Method from MethodGenerator
*
* @param MethodGenerator $method
* @throws Exception\InvalidArgumentException
* @return ClassGenerator
*/
public function addMethodFromGenerator(MethodGenerator $method)
{
$methodName = $method->getName();
if ($this->hasMethod($methodName)) {
throw new Exception\InvalidArgumentException(sprintf(
'A method by name %s already exists in this class.',
$methodName
));
}
$this->methods[strtolower($methodName)] = $method;
return $this;
}
/**
* @return MethodGenerator[]
*/
public function getMethods()
{
return $this->methods;
}
/**
* @param string $methodName
* @return MethodGenerator|false
*/
public function getMethod($methodName)
{
return $this->hasMethod($methodName) ? $this->methods[strtolower($methodName)] : false;
}
/**
* @param string $methodName
* @return ClassGenerator
*/
public function removeMethod($methodName)
{
if ($this->hasMethod($methodName)) {
unset($this->methods[strtolower($methodName)]);
}
return $this;
}
/**
* @param string $methodName
* @return bool
*/
public function hasMethod($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
*/
public function isSourceDirty()
{
if (($docBlock = $this->getDocBlock()) && $docBlock->isSourceDirty()) {
return true;
}
foreach ($this->getProperties() as $property) {
if ($property->isSourceDirty()) {
return true;
}
}
foreach ($this->getMethods() as $method) {
if ($method->isSourceDirty()) {
return true;
}
}
return parent::isSourceDirty();
}
/**
* @inherit Zend\Code\Generator\GeneratorInterface
*/
public function generate()
{
if (!$this->isSourceDirty()) {
$output = $this->getSourceContent();
if (!empty($output)) {
return $output;
}
}
$indent = $this->getIndentation();
$output = '';
if (null !== ($namespace = $this->getNamespaceName())) {
$output .= 'namespace ' . $namespace . ';' . self::LINE_FEED . self::LINE_FEED;
}
$uses = $this->getUses();
if (!empty($uses)) {
foreach ($uses as $use) {
$output .= 'use ' . $use . ';' . self::LINE_FEED;
}
$output .= self::LINE_FEED;
}
if (null !== ($docBlock = $this->getDocBlock())) {
$docBlock->setIndentation('');
$output .= $docBlock->generate();
}
if ($this->isAbstract()) {
$output .= 'abstract ';
} elseif ($this->isFinal()) {
$output .= 'final ';
}
$output .= static::OBJECT_TYPE . ' ' . $this->getName();
if (!empty($this->extendedClass)) {
$output .= ' extends ' . $this->extendedClass;
}
$implemented = $this->getImplementedInterfaces();
if (!empty($implemented)) {
$output .= ' implements ' . implode(', ', $implemented);
}
$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();
foreach ($properties as $property) {
$output .= $property->generate() . self::LINE_FEED . self::LINE_FEED;
}
$methods = $this->getMethods();
foreach ($methods as $method) {
$output .= $method->generate() . self::LINE_FEED;
}
$output .= self::LINE_FEED . '}' . self::LINE_FEED;
return $output;
}
}

View File

@@ -0,0 +1,50 @@
<?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\DocBlock;
use Zend\Code\Generator\DocBlock\Tag\GenericTag;
use Zend\Code\Reflection\DocBlock\Tag\TagInterface as ReflectionTagInterface;
/**
* @deprecated Deprecated in 2.3. Use GenericTag instead
*/
class Tag extends GenericTag
{
/**
* @param ReflectionTagInterface $reflectionTag
* @return Tag
* @deprecated Deprecated in 2.3. Use TagManager::createTagFromReflection() instead
*/
public static function fromReflection(ReflectionTagInterface $reflectionTag)
{
$tagManager = new TagManager();
$tagManager->initializeDefaultTags();
return $tagManager->createTagFromReflection($reflectionTag);
}
/**
* @param string $description
* @return Tag
* @deprecated Deprecated in 2.3. Use GenericTag::setContent() instead
*/
public function setDescription($description)
{
return $this->setContent($description);
}
/**
* @return string
* @deprecated Deprecated in 2.3. Use GenericTag::getContent() instead
*/
public function getDescription()
{
return $this->getContent();
}
}

View File

@@ -0,0 +1,96 @@
<?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\DocBlock\Tag;
use Zend\Code\Generator\AbstractGenerator;
/**
* This abstract class can be used as parent for all tags
* that use a type part in their content.
* @see http://www.phpdoc.org/docs/latest/for-users/phpdoc/types.html
*/
abstract class AbstractTypeableTag extends AbstractGenerator
{
/**
* @var string
*/
protected $description = null;
/**
* @var array
*/
protected $types = array();
/**
* @param array $types
* @param string $description
*/
public function __construct($types = array(), $description = null)
{
if (!empty($types)) {
$this->setTypes($types);
}
if (!empty($description)) {
$this->setDescription($description);
}
}
/**
* @param string $description
* @return ReturnTag
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* @return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Array of types or string with types delimited by pipe (|)
* e.g. array('int', 'null') or "int|null"
*
* @param array|string $types
* @return ReturnTag
*/
public function setTypes($types)
{
if (is_string($types)) {
$types = explode('|', $types);
}
$this->types = $types;
return $this;
}
/**
* @return array
*/
public function getTypes()
{
return $this->types;
}
/**
* @param string $delimiter
* @return string
*/
public function getTypesAsString($delimiter = '|')
{
return implode($delimiter, $this->types);
}
}

View File

@@ -0,0 +1,110 @@
<?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\DocBlock\Tag;
use Zend\Code\Generator\AbstractGenerator;
use Zend\Code\Generator\DocBlock\TagManager;
use Zend\Code\Reflection\DocBlock\Tag\TagInterface as ReflectionTagInterface;
class AuthorTag extends AbstractGenerator implements TagInterface
{
/**
* @var string
*/
protected $authorName = null;
/**
* @var string
*/
protected $authorEmail = null;
/**
* @param string $authorName
* @param string $authorEmail
*/
public function __construct($authorName = null, $authorEmail = null)
{
if (!empty($authorName)) {
$this->setAuthorName($authorName);
}
if (!empty($authorEmail)) {
$this->setAuthorEmail($authorEmail);
}
}
/**
* @param ReflectionTagInterface $reflectionTag
* @return ReturnTag
* @deprecated Deprecated in 2.3. Use TagManager::createTagFromReflection() instead
*/
public static function fromReflection(ReflectionTagInterface $reflectionTag)
{
$tagManager = new TagManager();
$tagManager->initializeDefaultTags();
return $tagManager->createTagFromReflection($reflectionTag);
}
/**
* @return string
*/
public function getName()
{
return 'author';
}
/**
* @param string $authorEmail
* @return AuthorTag
*/
public function setAuthorEmail($authorEmail)
{
$this->authorEmail = $authorEmail;
return $this;
}
/**
* @return string
*/
public function getAuthorEmail()
{
return $this->authorEmail;
}
/**
* @param string $authorName
* @return AuthorTag
*/
public function setAuthorName($authorName)
{
$this->authorName = $authorName;
return $this;
}
/**
* @return string
*/
public function getAuthorName()
{
return $this->authorName;
}
/**
* @return string
*/
public function generate()
{
$output = '@author'
. ((!empty($this->authorName)) ? ' ' . $this->authorName : '')
. ((!empty($this->authorEmail)) ? ' <' . $this->authorEmail . '>' : '');
return $output;
}
}

View File

@@ -0,0 +1,88 @@
<?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\DocBlock\Tag;
use Zend\Code\Generator\AbstractGenerator;
use Zend\Code\Generic\Prototype\PrototypeGenericInterface;
class GenericTag extends AbstractGenerator implements TagInterface, PrototypeGenericInterface
{
/**
* @var string
*/
protected $name = null;
/**
* @var string
*/
protected $content = null;
/**
* @param string $name
* @param string $content
*/
public function __construct($name = null, $content = null)
{
if (!empty($name)) {
$this->setName($name);
}
if (!empty($content)) {
$this->setContent($content);
}
}
/**
* @param string $name
* @return GenericTag
*/
public function setName($name)
{
$this->name = ltrim($name, '@');
return $this;
}
/**
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* @param string $content
* @return GenericTag
*/
public function setContent($content)
{
$this->content = $content;
return $this;
}
/**
* @return string
*/
public function getContent()
{
return $this->content;
}
/**
* @return string
*/
public function generate()
{
$output = '@' . $this->name
. ((!empty($this->content)) ? ' ' . $this->content : '');
return $output;
}
}

View File

@@ -0,0 +1,110 @@
<?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\DocBlock\Tag;
use Zend\Code\Generator\AbstractGenerator;
use Zend\Code\Generator\DocBlock\TagManager;
use Zend\Code\Reflection\DocBlock\Tag\TagInterface as ReflectionTagInterface;
class LicenseTag extends AbstractGenerator implements TagInterface
{
/**
* @var string
*/
protected $url = null;
/**
* @var string
*/
protected $licenseName = null;
/**
* @param string $url
* @param string $licenseName
*/
public function __construct($url = null, $licenseName = null)
{
if (!empty($url)) {
$this->setUrl($url);
}
if (!empty($licenseName)) {
$this->setLicenseName($licenseName);
}
}
/**
* @param ReflectionTagInterface $reflectionTag
* @return ReturnTag
* @deprecated Deprecated in 2.3. Use TagManager::createTagFromReflection() instead
*/
public static function fromReflection(ReflectionTagInterface $reflectionTag)
{
$tagManager = new TagManager();
$tagManager->initializeDefaultTags();
return $tagManager->createTagFromReflection($reflectionTag);
}
/**
* @return string
*/
public function getName()
{
return 'license';
}
/**
* @param string $url
* @return LicenseTag
*/
public function setUrl($url)
{
$this->url = $url;
return $this;
}
/**
* @return string
*/
public function getUrl()
{
return $this->url;
}
/**
* @param string $name
* @return LicenseTag
*/
public function setLicenseName($name)
{
$this->licenseName = $name;
return $this;
}
/**
* @return string
*/
public function getLicenseName()
{
return $this->licenseName;
}
/**
* @return string
*/
public function generate()
{
$output = '@license'
. ((!empty($this->url)) ? ' ' . $this->url : '')
. ((!empty($this->licenseName)) ? ' ' . $this->licenseName : '');
return $output;
}
}

View File

@@ -0,0 +1,98 @@
<?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\DocBlock\Tag;
class MethodTag extends AbstractTypeableTag implements TagInterface
{
/**
* @var string
*/
protected $methodName = null;
/**
* @var bool
*/
protected $isStatic = false;
/**
* @param string $methodName
* @param array $types
* @param string $description
* @param bool $isStatic
*/
public function __construct($methodName = null, $types = array(), $description = null, $isStatic = false)
{
if (!empty($methodName)) {
$this->setMethodName($methodName);
}
$this->setIsStatic((bool) $isStatic);
parent::__construct($types, $description);
}
/**
* @return string
*/
public function getName()
{
return 'method';
}
/**
* @param boolean $isStatic
* @return MethodTag
*/
public function setIsStatic($isStatic)
{
$this->isStatic = $isStatic;
return $this;
}
/**
* @return boolean
*/
public function isStatic()
{
return $this->isStatic;
}
/**
* @param string $methodName
* @return MethodTag
*/
public function setMethodName($methodName)
{
$this->methodName = rtrim($methodName, ')(');
return $this;
}
/**
* @return string
*/
public function getMethodName()
{
return $this->methodName;
}
/**
* @return string
*/
public function generate()
{
$output = '@method'
. (($this->isStatic) ? ' static' : '')
. ((!empty($this->types)) ? ' ' . $this->getTypesAsString() : '')
. ((!empty($this->methodName)) ? ' ' . $this->methodName . '()' : '')
. ((!empty($this->description)) ? ' ' . $this->description : '');
return $output;
}
}

View File

@@ -0,0 +1,124 @@
<?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\DocBlock\Tag;
use Zend\Code\Generator\DocBlock\TagManager;
use Zend\Code\Reflection\DocBlock\Tag\TagInterface as ReflectionTagInterface;
class ParamTag extends AbstractTypeableTag implements TagInterface
{
/**
* @var string
*/
protected $variableName = null;
/**
* @param string $variableName
* @param array $types
* @param string $description
*/
public function __construct($variableName = null, $types = array(), $description = null)
{
if (!empty($variableName)) {
$this->setVariableName($variableName);
}
parent::__construct($types, $description);
}
/**
* @param ReflectionTagInterface $reflectionTag
* @return ReturnTag
* @deprecated Deprecated in 2.3. Use TagManager::createTagFromReflection() instead
*/
public static function fromReflection(ReflectionTagInterface $reflectionTag)
{
$tagManager = new TagManager();
$tagManager->initializeDefaultTags();
return $tagManager->createTagFromReflection($reflectionTag);
}
/**
* @return string
*/
public function getName()
{
return 'param';
}
/**
* @param string $variableName
* @return ParamTag
*/
public function setVariableName($variableName)
{
$this->variableName = ltrim($variableName, '$');
return $this;
}
/**
* @return string
*/
public function getVariableName()
{
return $this->variableName;
}
/**
* @param string $datatype
* @return ReturnTag
* @deprecated Deprecated in 2.3. Use setTypes() instead
*/
public function setDatatype($datatype)
{
return $this->setTypes($datatype);
}
/**
* @return string
* @deprecated Deprecated in 2.3. Use getTypes() or getTypesAsString() instead
*/
public function getDatatype()
{
return $this->getTypesAsString();
}
/**
* @param string $paramName
* @return ParamTag
* @deprecated Deprecated in 2.3. Use setVariableName() instead
*/
public function setParamName($paramName)
{
return $this->setVariableName($paramName);
}
/**
* @return string
* @deprecated Deprecated in 2.3. Use getVariableName() instead
*/
public function getParamName()
{
return $this->getVariableName();
}
/**
* @return string
*/
public function generate()
{
$output = '@param'
. ((!empty($this->types)) ? ' ' . $this->getTypesAsString() : '')
. ((!empty($this->variableName)) ? ' $' . $this->variableName : '')
. ((!empty($this->description)) ? ' ' . $this->description : '');
return $output;
}
}

View File

@@ -0,0 +1,71 @@
<?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\DocBlock\Tag;
class PropertyTag extends AbstractTypeableTag implements TagInterface
{
/**
* @var string
*/
protected $propertyName = null;
/**
* @param string $propertyName
* @param array $types
* @param string $description
*/
public function __construct($propertyName = null, $types = array(), $description = null)
{
if (!empty($propertyName)) {
$this->setPropertyName($propertyName);
}
parent::__construct($types, $description);
}
/**
* @return string
*/
public function getName()
{
return 'property';
}
/**
* @param string $propertyName
* @return self
*/
public function setPropertyName($propertyName)
{
$this->propertyName = ltrim($propertyName, '$');
return $this;
}
/**
* @return string
*/
public function getPropertyName()
{
return $this->propertyName;
}
/**
* @return string
*/
public function generate()
{
$output = '@property'
. ((!empty($this->types)) ? ' ' . $this->getTypesAsString() : '')
. ((!empty($this->propertyName)) ? ' $' . $this->propertyName : '')
. ((!empty($this->description)) ? ' ' . $this->description : '');
return $output;
}
}

View File

@@ -0,0 +1,67 @@
<?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\DocBlock\Tag;
use Zend\Code\Generator\DocBlock\TagManager;
use Zend\Code\Reflection\DocBlock\Tag\TagInterface as ReflectionTagInterface;
class ReturnTag extends AbstractTypeableTag implements TagInterface
{
/**
* @param ReflectionTagInterface $reflectionTag
* @return ReturnTag
* @deprecated Deprecated in 2.3. Use TagManager::createTagFromReflection() instead
*/
public static function fromReflection(ReflectionTagInterface $reflectionTag)
{
$tagManager = new TagManager();
$tagManager->initializeDefaultTags();
return $tagManager->createTagFromReflection($reflectionTag);
}
/**
* @return string
*/
public function getName()
{
return 'return';
}
/**
* @param string $datatype
* @return ReturnTag
* @deprecated Deprecated in 2.3. Use setTypes() instead
*/
public function setDatatype($datatype)
{
return $this->setTypes($datatype);
}
/**
* @return string
* @deprecated Deprecated in 2.3. Use getTypes() or getTypesAsString() instead
*/
public function getDatatype()
{
return $this->getTypesAsString();
}
/**
* @return string
*/
public function generate()
{
$output = '@return '
. $this->getTypesAsString()
. ((!empty($this->description)) ? ' ' . $this->description : '');
return $output;
}
}

View File

@@ -0,0 +1,16 @@
<?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\DocBlock\Tag;
use Zend\Code\Generic\Prototype\PrototypeInterface;
interface TagInterface extends PrototypeInterface
{
}

View File

@@ -0,0 +1,33 @@
<?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\DocBlock\Tag;
class ThrowsTag extends AbstractTypeableTag implements TagInterface
{
/**
* @return string
*/
public function getName()
{
return 'throws';
}
/**
* @return string
*/
public function generate()
{
$output = '@throws'
. ((!empty($this->types)) ? ' ' . $this->getTypesAsString() : '')
. ((!empty($this->description)) ? ' ' . $this->description : '');
return $output;
}
}

View File

@@ -0,0 +1,69 @@
<?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\DocBlock;
use Zend\Code\Generator\DocBlock\Tag\TagInterface;
use Zend\Code\Generic\Prototype\PrototypeClassFactory;
use Zend\Code\Reflection\DocBlock\Tag\TagInterface as ReflectionTagInterface;
/**
* This class is used in DocBlockGenerator and creates the needed
* Tag classes depending on the tag. So for example an @author tag
* will trigger the creation of an AuthorTag class.
*
* If none of the classes is applicable, the GenericTag class will be
* created
*/
class TagManager extends PrototypeClassFactory
{
/**
* @return void
*/
public function initializeDefaultTags()
{
$this->addPrototype(new Tag\ParamTag());
$this->addPrototype(new Tag\ReturnTag());
$this->addPrototype(new Tag\MethodTag());
$this->addPrototype(new Tag\PropertyTag());
$this->addPrototype(new Tag\AuthorTag());
$this->addPrototype(new Tag\LicenseTag());
$this->addPrototype(new Tag\ThrowsTag());
$this->setGenericPrototype(new Tag\GenericTag());
}
/**
* @param ReflectionTagInterface $reflectionTag
* @return TagInterface
*/
public function createTagFromReflection(ReflectionTagInterface $reflectionTag)
{
$tagName = $reflectionTag->getName();
/* @var TagInterface $newTag */
$newTag = $this->getClonedPrototype($tagName);
// transport any properties via accessors and mutators from reflection to codegen object
$reflectionClass = new \ReflectionClass($reflectionTag);
foreach ($reflectionClass->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) {
if (substr($method->getName(), 0, 3) == 'get') {
$propertyName = substr($method->getName(), 3);
if (method_exists($newTag, 'set' . $propertyName)) {
$newTag->{'set' . $propertyName}($reflectionTag->{'get' . $propertyName}());
}
} elseif (substr($method->getName(), 0, 2) == 'is') {
$propertyName = ucfirst($method->getName());
if (method_exists($newTag, 'set' . $propertyName)) {
$newTag->{'set' . $propertyName}($reflectionTag->{$method->getName()}());
}
}
}
return $newTag;
}
}

View File

@@ -0,0 +1,274 @@
<?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\Generator\DocBlock\Tag;
use Zend\Code\Generator\DocBlock\Tag\TagInterface;
use Zend\Code\Generator\DocBlock\TagManager;
use Zend\Code\Reflection\DocBlockReflection;
class DocBlockGenerator extends AbstractGenerator
{
/**
* @var string
*/
protected $shortDescription = null;
/**
* @var string
*/
protected $longDescription = null;
/**
* @var array
*/
protected $tags = array();
/**
* @var string
*/
protected $indentation = '';
/**
* @var bool
*/
protected $wordwrap = true;
protected static $tagManager;
/**
* Build a DocBlock generator object from a reflection object
*
* @param DocBlockReflection $reflectionDocBlock
* @return DocBlockGenerator
*/
public static function fromReflection(DocBlockReflection $reflectionDocBlock)
{
$docBlock = new static();
$docBlock->setSourceContent($reflectionDocBlock->getContents());
$docBlock->setSourceDirty(false);
$docBlock->setShortDescription($reflectionDocBlock->getShortDescription());
$docBlock->setLongDescription($reflectionDocBlock->getLongDescription());
foreach ($reflectionDocBlock->getTags() as $tag) {
$docBlock->setTag(self::getTagManager()->createTagFromReflection($tag));
}
return $docBlock;
}
/**
* Generate from array
*
* @configkey shortdescription string The short description for this doc block
* @configkey longdescription string The long description for this doc block
* @configkey tags array
*
* @throws Exception\InvalidArgumentException
* @param array $array
* @return DocBlockGenerator
*/
public static function fromArray(array $array)
{
$docBlock = new static();
foreach ($array as $name => $value) {
// normalize key
switch (strtolower(str_replace(array('.', '-', '_'), '', $name))) {
case 'shortdescription':
$docBlock->setShortDescription($value);
break;
case 'longdescription':
$docBlock->setLongDescription($value);
break;
case 'tags':
$docBlock->setTags($value);
break;
}
}
return $docBlock;
}
protected static function getTagManager()
{
if (!isset(static::$tagManager)) {
static::$tagManager = new TagManager();
static::$tagManager->initializeDefaultTags();
}
return static::$tagManager;
}
/**
* @param string $shortDescription
* @param string $longDescription
* @param array $tags
*/
public function __construct($shortDescription = null, $longDescription = null, array $tags = array())
{
if ($shortDescription) {
$this->setShortDescription($shortDescription);
}
if ($longDescription) {
$this->setLongDescription($longDescription);
}
if (is_array($tags) && $tags) {
$this->setTags($tags);
}
}
/**
* @param string $shortDescription
* @return DocBlockGenerator
*/
public function setShortDescription($shortDescription)
{
$this->shortDescription = $shortDescription;
return $this;
}
/**
* @return string
*/
public function getShortDescription()
{
return $this->shortDescription;
}
/**
* @param string $longDescription
* @return DocBlockGenerator
*/
public function setLongDescription($longDescription)
{
$this->longDescription = $longDescription;
return $this;
}
/**
* @return string
*/
public function getLongDescription()
{
return $this->longDescription;
}
/**
* @param array $tags
* @return DocBlockGenerator
*/
public function setTags(array $tags)
{
foreach ($tags as $tag) {
$this->setTag($tag);
}
return $this;
}
/**
* @param array|TagInterface $tag
* @throws Exception\InvalidArgumentException
* @return DocBlockGenerator
*/
public function setTag($tag)
{
if (is_array($tag)) {
// use deprecated Tag class for backward compatiblity to old array-keys
$genericTag = new Tag();
$genericTag->setOptions($tag);
$tag = $genericTag;
} elseif (!$tag instanceof TagInterface) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects either an array of method options or an instance of %s\DocBlock\Tag\TagInterface',
__METHOD__,
__NAMESPACE__
));
}
$this->tags[] = $tag;
return $this;
}
/**
* @return TagInterface[]
*/
public function getTags()
{
return $this->tags;
}
/**
* @param bool $value
* @return DocBlockGenerator
*/
public function setWordWrap($value)
{
$this->wordwrap = (bool) $value;
return $this;
}
/**
* @return bool
*/
public function getWordWrap()
{
return $this->wordwrap;
}
/**
* @return string
*/
public function generate()
{
if (!$this->isSourceDirty()) {
return $this->docCommentize(trim($this->getSourceContent()));
}
$output = '';
if (null !== ($sd = $this->getShortDescription())) {
$output .= $sd . self::LINE_FEED . self::LINE_FEED;
}
if (null !== ($ld = $this->getLongDescription())) {
$output .= $ld . self::LINE_FEED . self::LINE_FEED;
}
/* @var $tag GeneratorInterface */
foreach ($this->getTags() as $tag) {
$output .= $tag->generate() . self::LINE_FEED;
}
return $this->docCommentize(trim($output));
}
/**
* @param string $content
* @return string
*/
protected function docCommentize($content)
{
$indent = $this->getIndentation();
$output = $indent . '/**' . self::LINE_FEED;
$content = $this->getWordWrap() == true ? wordwrap($content, 80, self::LINE_FEED) : $content;
$lines = explode(self::LINE_FEED, $content);
foreach ($lines as $line) {
$output .= $indent . ' *';
if ($line) {
$output .= " $line";
}
$output .= self::LINE_FEED;
}
$output .= $indent . ' */' . self::LINE_FEED;
return $output;
}
}

View File

@@ -0,0 +1,16 @@
<?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\Exception;
use Zend\Code\Exception\ExceptionInterface as Exception;
interface ExceptionInterface extends Exception
{
}

View File

@@ -0,0 +1,17 @@
<?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\Exception;
use Zend\Code\Exception;
class InvalidArgumentException extends Exception\InvalidArgumentException implements
ExceptionInterface
{
}

View File

@@ -0,0 +1,17 @@
<?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\Exception;
use Zend\Code\Exception;
class RuntimeException extends Exception\RuntimeException implements
ExceptionInterface
{
}

View File

@@ -0,0 +1,561 @@
<?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\Exception as ReflectionException;
use Zend\Code\Reflection\FileReflection;
class FileGenerator extends AbstractGenerator
{
/**
* @var string
*/
protected $filename = null;
/**
* @var DocBlockGenerator
*/
protected $docBlock = null;
/**
* @var array
*/
protected $requiredFiles = array();
/**
* @var string
*/
protected $namespace = null;
/**
* @var array
*/
protected $uses = array();
/**
* @var array
*/
protected $classes = array();
/**
* @var string
*/
protected $body = null;
/**
* Passes $options to {@link setOptions()}.
*
* @param array|\Traversable $options
*/
public function __construct($options = null)
{
if (null !== $options) {
$this->setOptions($options);
}
}
/**
* Use this if you intend on generating code generation objects based on the same file.
* This will keep previous changes to the file in tact during the same PHP process
*
* @param string $filePath
* @param bool $includeIfNotAlreadyIncluded
* @throws ReflectionException\InvalidArgumentException If file does not exists
* @throws ReflectionException\RuntimeException If file exists but is not included or required
* @return FileGenerator
*/
public static function fromReflectedFileName($filePath, $includeIfNotAlreadyIncluded = true)
{
$fileReflector = new FileReflection($filePath, $includeIfNotAlreadyIncluded);
$codeGenerator = static::fromReflection($fileReflector);
return $codeGenerator;
}
/**
* @param FileReflection $fileReflection
* @return FileGenerator
*/
public static function fromReflection(FileReflection $fileReflection)
{
$file = new static();
$file->setSourceContent($fileReflection->getContents());
$file->setSourceDirty(false);
$uses = $fileReflection->getUses();
foreach ($fileReflection->getClasses() as $class) {
$phpClass = ClassGenerator::fromReflection($class);
$phpClass->setContainingFileGenerator($file);
foreach ($uses as $fileUse) {
$phpClass->addUse($fileUse['use'], $fileUse['as']);
}
$file->setClass($phpClass);
}
$namespace = $fileReflection->getNamespace();
if ($namespace != '') {
$file->setNamespace($namespace);
}
if ($uses) {
$file->setUses($uses);
}
if (($fileReflection->getDocComment() != '')) {
$docBlock = $fileReflection->getDocBlock();
$file->setDocBlock(DocBlockGenerator::fromReflection($docBlock));
}
return $file;
}
/**
* @param array $values
* @return FileGenerator
*/
public static function fromArray(array $values)
{
$fileGenerator = new static;
foreach ($values as $name => $value) {
switch (strtolower(str_replace(array('.', '-', '_'), '', $name))) {
case 'filename':
$fileGenerator->setFilename($value);
continue;
case 'class':
$fileGenerator->setClass(($value instanceof ClassGenerator) ? $value : ClassGenerator::fromArray($value));
continue;
case 'requiredfiles':
$fileGenerator->setRequiredFiles($value);
continue;
default:
if (property_exists($fileGenerator, $name)) {
$fileGenerator->{$name} = $value;
} elseif (method_exists($fileGenerator, 'set' . $name)) {
$fileGenerator->{'set' . $name}($value);
}
}
}
return $fileGenerator;
}
/**
* @param DocBlockGenerator|array|string $docBlock
* @throws Exception\InvalidArgumentException
* @return FileGenerator
*/
public function setDocBlock($docBlock)
{
if (is_string($docBlock)) {
$docBlock = array('shortDescription' => $docBlock);
}
if (is_array($docBlock)) {
$docBlock = new DocBlockGenerator($docBlock);
} elseif (!$docBlock instanceof DocBlockGenerator) {
throw new Exception\InvalidArgumentException(sprintf(
'%s is expecting either a string, array or an instance of %s\DocBlockGenerator',
__METHOD__,
__NAMESPACE__
));
}
$this->docBlock = $docBlock;
return $this;
}
/**
* @return DocBlockGenerator
*/
public function getDocBlock()
{
return $this->docBlock;
}
/**
* @param array $requiredFiles
* @return FileGenerator
*/
public function setRequiredFiles(array $requiredFiles)
{
$this->requiredFiles = $requiredFiles;
return $this;
}
/**
* @return array
*/
public function getRequiredFiles()
{
return $this->requiredFiles;
}
/**
* @return string
*/
public function getNamespace()
{
return $this->namespace;
}
/**
* @param string $namespace
* @return FileGenerator
*/
public function setNamespace($namespace)
{
$this->namespace = (string) $namespace;
return $this;
}
/**
* Returns an array with the first element the use statement, second is the as part.
* If $withResolvedAs is set to true, there will be a third element that is the
* "resolved" as statement, as the second part is not required in use statements
*
* @param bool $withResolvedAs
* @return array
*/
public function getUses($withResolvedAs = false)
{
$uses = $this->uses;
if ($withResolvedAs) {
for ($useIndex = 0, $count = count($uses); $useIndex < $count; $useIndex++) {
if ($uses[$useIndex][1] == '') {
if (($lastSeparator = strrpos($uses[$useIndex][0], '\\')) !== false) {
$uses[$useIndex][2] = substr($uses[$useIndex][0], $lastSeparator + 1);
} else {
$uses[$useIndex][2] = $uses[$useIndex][0];
}
} else {
$uses[$useIndex][2] = $uses[$useIndex][1];
}
}
}
return $uses;
}
/**
* @param array $uses
* @return FileGenerator
*/
public function setUses(array $uses)
{
foreach ($uses as $use) {
$use = (array) $use;
if (array_key_exists('use', $use) && array_key_exists('as', $use)) {
$import = $use['use'];
$alias = $use['as'];
} elseif (count($use) == 2) {
list($import, $alias) = $use;
} else {
$import = current($use);
$alias = null;
}
$this->setUse($import, $alias);
}
return $this;
}
/**
* @param string $use
* @param null|string $as
* @return FileGenerator
*/
public function setUse($use, $as = null)
{
if (!in_array(array($use, $as), $this->uses)) {
$this->uses[] = array($use, $as);
}
return $this;
}
/**
* @param array $classes
* @return FileGenerator
*/
public function setClasses(array $classes)
{
foreach ($classes as $class) {
$this->setClass($class);
}
return $this;
}
/**
* @param string $name
* @return ClassGenerator
*/
public function getClass($name = null)
{
if ($name === null) {
reset($this->classes);
return current($this->classes);
}
return $this->classes[(string) $name];
}
/**
* @param array|string|ClassGenerator $class
* @throws Exception\InvalidArgumentException
* @return FileGenerator
*/
public function setClass($class)
{
if (is_array($class)) {
$class = ClassGenerator::fromArray($class);
} elseif (is_string($class)) {
$class = new ClassGenerator($class);
} elseif (!$class instanceof ClassGenerator) {
throw new Exception\InvalidArgumentException(sprintf(
'%s is expecting either a string, array or an instance of %s\ClassGenerator',
__METHOD__,
__NAMESPACE__
));
}
// @todo check for dup here
$className = $class->getName();
$this->classes[$className] = $class;
return $this;
}
/**
* @param string $filename
* @return FileGenerator
*/
public function setFilename($filename)
{
$this->filename = (string) $filename;
return $this;
}
/**
* @return string
*/
public function getFilename()
{
return $this->filename;
}
/**
* @return ClassGenerator[]
*/
public function getClasses()
{
return $this->classes;
}
/**
* @param string $body
* @return FileGenerator
*/
public function setBody($body)
{
$this->body = (string) $body;
return $this;
}
/**
* @return string
*/
public function getBody()
{
return $this->body;
}
/**
* @return bool
*/
public function isSourceDirty()
{
$docBlock = $this->getDocBlock();
if ($docBlock && $docBlock->isSourceDirty()) {
return true;
}
foreach ($this->classes as $class) {
if ($class->isSourceDirty()) {
return true;
}
}
return parent::isSourceDirty();
}
/**
* @return string
*/
public function generate()
{
if ($this->isSourceDirty() === false) {
return $this->sourceContent;
}
$output = '';
// @note body gets populated when FileGenerator created
// from a file. @see fromReflection and may also be set
// via FileGenerator::setBody
$body = $this->getBody();
// start with the body (if there), or open tag
if (preg_match('#(?:\s*)<\?php#', $body) == false) {
$output = '<?php' . self::LINE_FEED;
}
// if there are markers, put the body into the output
if (preg_match('#/\* Zend_Code_Generator_Php_File-(.*?)Marker:#m', $body)) {
$tokens = token_get_all($body);
foreach ($tokens as $token) {
if (is_array($token) && in_array($token[0], array(T_OPEN_TAG, T_COMMENT, T_DOC_COMMENT, T_WHITESPACE))
) {
$output .= $token[1];
}
}
$body = '';
}
// Add file DocBlock, if any
if (null !== ($docBlock = $this->getDocBlock())) {
$docBlock->setIndentation('');
if (preg_match('#/\* Zend_Code_Generator_FileGenerator-DocBlockMarker \*/#m', $output)) {
$output = preg_replace('#/\* Zend_Code_Generator_FileGenerator-DocBlockMarker \*/#m', $docBlock->generate(), $output, 1);
} else {
$output .= $docBlock->generate() . self::LINE_FEED;
}
}
// newline
$output .= self::LINE_FEED;
// namespace, if any
$namespace = $this->getNamespace();
if ($namespace) {
$namespace = sprintf('namespace %s;%s', $namespace, str_repeat(self::LINE_FEED, 2));
if (preg_match('#/\* Zend_Code_Generator_FileGenerator-NamespaceMarker \*/#m', $output)) {
$output = preg_replace(
'#/\* Zend_Code_Generator_FileGenerator-NamespaceMarker \*/#m',
$namespace,
$output,
1
);
} else {
$output .= $namespace;
}
}
// process required files
// @todo marker replacement for required files
$requiredFiles = $this->getRequiredFiles();
if (!empty($requiredFiles)) {
foreach ($requiredFiles as $requiredFile) {
$output .= 'require_once \'' . $requiredFile . '\';' . self::LINE_FEED;
}
$output .= self::LINE_FEED;
}
$classes = $this->getClasses();
$classUses = array();
//build uses array
foreach ($classes as $class) {
//check for duplicate use statements
$uses = $class->getUses();
if (!empty($uses) && is_array($uses)) {
$classUses = array_merge($classUses, $uses);
}
}
// process import statements
$uses = $this->getUses();
if (!empty($uses)) {
$useOutput = '';
foreach ($uses as $use) {
list($import, $alias) = $use;
if (null === $alias) {
$tempOutput = sprintf('%s', $import);
} else {
$tempOutput = sprintf('%s as %s', $import, $alias);
}
//don't duplicate use statements
if (!in_array($tempOutput, $classUses)) {
$useOutput .= "use ". $tempOutput .";";
$useOutput .= self::LINE_FEED;
}
}
$useOutput .= self::LINE_FEED;
if (preg_match('#/\* Zend_Code_Generator_FileGenerator-UseMarker \*/#m', $output)) {
$output = preg_replace(
'#/\* Zend_Code_Generator_FileGenerator-UseMarker \*/#m',
$useOutput,
$output,
1
);
} else {
$output .= $useOutput;
}
}
// process classes
if (!empty($classes)) {
foreach ($classes as $class) {
$regex = str_replace('&', $class->getName(), '/\* Zend_Code_Generator_Php_File-ClassMarker: \{[A-Za-z0-9\\\]+?&\} \*/');
if (preg_match('#' . $regex . '#m', $output)) {
$output = preg_replace('#' . $regex . '#', $class->generate(), $output, 1);
} else {
if ($namespace) {
$class->setNamespaceName(null);
}
$output .= $class->generate() . self::LINE_FEED;
}
}
}
if (!empty($body)) {
// add an extra space between classes and
if (!empty($classes)) {
$output .= self::LINE_FEED;
}
$output .= $body;
}
return $output;
}
/**
* @return FileGenerator
* @throws Exception\RuntimeException
*/
public function write()
{
if ($this->filename == '' || !is_writable(dirname($this->filename))) {
throw new Exception\RuntimeException('This code generator object is not writable.');
}
file_put_contents($this->filename, $this->generate());
return $this;
}
}

View File

@@ -0,0 +1,44 @@
<?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\Generator\Exception\RuntimeException;
class FileGeneratorRegistry
{
/**
* @var array $fileCodeGenerators
*/
private static $fileCodeGenerators = array();
/**
* Registry for the Zend\Code package.
*
* @param FileGenerator $fileCodeGenerator
* @param string $fileName
* @throws RuntimeException
*/
public static function registerFileCodeGenerator(FileGenerator $fileCodeGenerator, $fileName = null)
{
if ($fileName === null) {
$fileName = $fileCodeGenerator->getFilename();
}
if ($fileName == '') {
throw new RuntimeException('FileName does not exist.');
}
// cannot use realpath since the file might not exist, but we do need to have the index
// in the same DIRECTORY_SEPARATOR that realpath would use:
$fileName = str_replace(array('\\', '/'), DIRECTORY_SEPARATOR, $fileName);
static::$fileCodeGenerators[$fileName] = $fileCodeGenerator;
}
}

View File

@@ -0,0 +1,15 @@
<?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 GeneratorInterface
{
public function generate();
}

View File

@@ -0,0 +1,313 @@
<?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\MethodReflection;
class MethodGenerator extends AbstractMemberGenerator
{
/**
* @var DocBlockGenerator
*/
protected $docBlock = null;
/**
* @var ParameterGenerator[]
*/
protected $parameters = array();
/**
* @var string
*/
protected $body = null;
/**
* @param MethodReflection $reflectionMethod
* @return MethodGenerator
*/
public static function fromReflection(MethodReflection $reflectionMethod)
{
$method = new static();
$method->setSourceContent($reflectionMethod->getContents(false));
$method->setSourceDirty(false);
if ($reflectionMethod->getDocComment() != '') {
$method->setDocBlock(DocBlockGenerator::fromReflection($reflectionMethod->getDocBlock()));
}
$method->setFinal($reflectionMethod->isFinal());
if ($reflectionMethod->isPrivate()) {
$method->setVisibility(self::VISIBILITY_PRIVATE);
} elseif ($reflectionMethod->isProtected()) {
$method->setVisibility(self::VISIBILITY_PROTECTED);
} else {
$method->setVisibility(self::VISIBILITY_PUBLIC);
}
$method->setStatic($reflectionMethod->isStatic());
$method->setName($reflectionMethod->getName());
foreach ($reflectionMethod->getParameters() as $reflectionParameter) {
$method->setParameter(ParameterGenerator::fromReflection($reflectionParameter));
}
$method->setBody(static::clearBodyIndention($reflectionMethod->getBody()));
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
*
* @configkey name string [required] Class Name
* @configkey docblock string The docblock information
* @configkey flags int Flags, one of MethodGenerator::FLAG_ABSTRACT MethodGenerator::FLAG_FINAL
* @configkey parameters string Class which this class is extending
* @configkey body string
* @configkey abstract bool
* @configkey final bool
* @configkey static bool
* @configkey visibility string
*
* @throws Exception\InvalidArgumentException
* @param array $array
* @return MethodGenerator
*/
public static function fromArray(array $array)
{
if (!isset($array['name'])) {
throw new Exception\InvalidArgumentException(
'Method generator requires that a name is provided for this object'
);
}
$method = new static($array['name']);
foreach ($array as $name => $value) {
// normalize key
switch (strtolower(str_replace(array('.', '-', '_'), '', $name))) {
case 'docblock':
$docBlock = ($value instanceof DocBlockGenerator) ? $value : DocBlockGenerator::fromArray($value);
$method->setDocBlock($docBlock);
break;
case 'flags':
$method->setFlags($value);
break;
case 'parameters':
$method->setParameters($value);
break;
case 'body':
$method->setBody($value);
break;
case 'abstract':
$method->setAbstract($value);
break;
case 'final':
$method->setFinal($value);
break;
case 'static':
$method->setStatic($value);
break;
case 'visibility':
$method->setVisibility($value);
break;
}
}
return $method;
}
/**
* @param string $name
* @param array $parameters
* @param int $flags
* @param string $body
* @param DocBlockGenerator|string $docBlock
*/
public function __construct(
$name = null,
array $parameters = array(),
$flags = self::FLAG_PUBLIC,
$body = null,
$docBlock = null
) {
if ($name) {
$this->setName($name);
}
if ($parameters) {
$this->setParameters($parameters);
}
if ($flags !== self::FLAG_PUBLIC) {
$this->setFlags($flags);
}
if ($body) {
$this->setBody($body);
}
if ($docBlock) {
$this->setDocBlock($docBlock);
}
}
/**
* @param array $parameters
* @return MethodGenerator
*/
public function setParameters(array $parameters)
{
foreach ($parameters as $parameter) {
$this->setParameter($parameter);
}
return $this;
}
/**
* @param ParameterGenerator|array|string $parameter
* @throws Exception\InvalidArgumentException
* @return MethodGenerator
*/
public function setParameter($parameter)
{
if (is_string($parameter)) {
$parameter = new ParameterGenerator($parameter);
}
if (is_array($parameter)) {
$parameter = ParameterGenerator::fromArray($parameter);
}
if (!$parameter instanceof ParameterGenerator) {
throw new Exception\InvalidArgumentException(sprintf(
'%s is expecting either a string, array or an instance of %s\ParameterGenerator',
__METHOD__,
__NAMESPACE__
));
}
$this->parameters[$parameter->getName()] = $parameter;
return $this;
}
/**
* @return ParameterGenerator[]
*/
public function getParameters()
{
return $this->parameters;
}
/**
* @param string $body
* @return MethodGenerator
*/
public function setBody($body)
{
$this->body = $body;
return $this;
}
/**
* @return string
*/
public function getBody()
{
return $this->body;
}
/**
* @return string
*/
public function generate()
{
$output = '';
$indent = $this->getIndentation();
if (($docBlock = $this->getDocBlock()) !== null) {
$docBlock->setIndentation($indent);
$output .= $docBlock->generate();
}
$output .= $indent;
if ($this->isAbstract()) {
$output .= 'abstract ';
} else {
$output .= (($this->isFinal()) ? 'final ' : '');
}
$output .= $this->getVisibility()
. (($this->isStatic()) ? ' static' : '')
. ' function ' . $this->getName() . '(';
$parameters = $this->getParameters();
if (!empty($parameters)) {
foreach ($parameters as $parameter) {
$parameterOutput[] = $parameter->generate();
}
$output .= implode(', ', $parameterOutput);
}
$output .= ')';
if ($this->isAbstract()) {
return $output . ';';
}
$output .= self::LINE_FEED . $indent . '{' . self::LINE_FEED;
if ($this->body) {
$output .= preg_replace('#^((?![a-zA-Z0-9_-]+;).+?)$#m', $indent . $indent . '$1', trim($this->body))
. self::LINE_FEED;
}
$output .= $indent . '}' . self::LINE_FEED;
return $output;
}
public function __toString()
{
return $this->generate();
}
}

View File

@@ -0,0 +1,300 @@
<?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\ParameterReflection;
class ParameterGenerator extends AbstractGenerator
{
/**
* @var string
*/
protected $name = null;
/**
* @var string
*/
protected $type = null;
/**
* @var string|ValueGenerator
*/
protected $defaultValue = null;
/**
* @var int
*/
protected $position = null;
/**
* @var bool
*/
protected $passedByReference = false;
/**
* @var array
*/
protected static $simple = array('int', 'bool', 'string', 'float', 'resource', 'mixed', 'object');
/**
* @param ParameterReflection $reflectionParameter
* @return ParameterGenerator
*/
public static function fromReflection(ParameterReflection $reflectionParameter)
{
$param = new ParameterGenerator();
$param->setName($reflectionParameter->getName());
if ($reflectionParameter->isArray()) {
$param->setType('array');
} elseif (method_exists($reflectionParameter, 'isCallable') && $reflectionParameter->isCallable()) {
$param->setType('callable');
} else {
$typeClass = $reflectionParameter->getClass();
if ($typeClass) {
$parameterType = $typeClass->getName();
$currentNamespace = $reflectionParameter->getDeclaringClass()->getNamespaceName();
if (!empty($currentNamespace) && substr($parameterType, 0, strlen($currentNamespace)) == $currentNamespace) {
$parameterType = substr($parameterType, strlen($currentNamespace) + 1);
} else {
$parameterType = '\\' . trim($parameterType, '\\');
}
$param->setType($parameterType);
}
}
$param->setPosition($reflectionParameter->getPosition());
if ($reflectionParameter->isOptional()) {
$param->setDefaultValue($reflectionParameter->getDefaultValue());
}
$param->setPassedByReference($reflectionParameter->isPassedByReference());
return $param;
}
/**
* Generate from array
*
* @configkey name string [required] Class Name
* @configkey type string
* @configkey defaultvalue null|bool|string|int|float|array|ValueGenerator
* @configkey passedbyreference bool
* @configkey position int
* @configkey sourcedirty bool
* @configkey indentation string
* @configkey sourcecontent string
*
* @throws Exception\InvalidArgumentException
* @param array $array
* @return ParameterGenerator
*/
public static function fromArray(array $array)
{
if (!isset($array['name'])) {
throw new Exception\InvalidArgumentException(
'Paramerer generator requires that a name is provided for this object'
);
}
$param = new static($array['name']);
foreach ($array as $name => $value) {
// normalize key
switch (strtolower(str_replace(array('.', '-', '_'), '', $name))) {
case 'type':
$param->setType($value);
break;
case 'defaultvalue':
$param->setDefaultValue($value);
break;
case 'passedbyreference':
$param->setPassedByReference($value);
break;
case 'position':
$param->setPosition($value);
break;
case 'sourcedirty':
$param->setSourceDirty($value);
break;
case 'indentation':
$param->setIndentation($value);
break;
case 'sourcecontent':
$param->setSourceContent($value);
break;
}
}
return $param;
}
/**
* @param string $name
* @param string $type
* @param mixed $defaultValue
* @param int $position
* @param bool $passByReference
*/
public function __construct(
$name = null,
$type = null,
$defaultValue = null,
$position = null,
$passByReference = false
) {
if (null !== $name) {
$this->setName($name);
}
if (null !== $type) {
$this->setType($type);
}
if (null !== $defaultValue) {
$this->setDefaultValue($defaultValue);
}
if (null !== $position) {
$this->setPosition($position);
}
if (false !== $passByReference) {
$this->setPassedByReference(true);
}
}
/**
* @param string $type
* @return ParameterGenerator
*/
public function setType($type)
{
$this->type = (string) $type;
return $this;
}
/**
* @return string
*/
public function getType()
{
return $this->type;
}
/**
* @param string $name
* @return ParameterGenerator
*/
public function setName($name)
{
$this->name = (string) $name;
return $this;
}
/**
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set the default value of the parameter.
*
* Certain variables are difficult to express
*
* @param null|bool|string|int|float|array|ValueGenerator $defaultValue
* @return ParameterGenerator
*/
public function setDefaultValue($defaultValue)
{
if (!($defaultValue instanceof ValueGenerator)) {
$defaultValue = new ValueGenerator($defaultValue);
}
$this->defaultValue = $defaultValue;
return $this;
}
/**
* @return string
*/
public function getDefaultValue()
{
return $this->defaultValue;
}
/**
* @param int $position
* @return ParameterGenerator
*/
public function setPosition($position)
{
$this->position = (int) $position;
return $this;
}
/**
* @return int
*/
public function getPosition()
{
return $this->position;
}
/**
* @return bool
*/
public function getPassedByReference()
{
return $this->passedByReference;
}
/**
* @param bool $passedByReference
* @return ParameterGenerator
*/
public function setPassedByReference($passedByReference)
{
$this->passedByReference = (bool) $passedByReference;
return $this;
}
/**
* @return string
*/
public function generate()
{
$output = '';
if ($this->type && !in_array($this->type, static::$simple)) {
$output .= $this->type . ' ';
}
if (true === $this->passedByReference) {
$output .= '&';
}
$output .= '$' . $this->name;
if ($this->defaultValue !== null) {
$output .= ' = ';
if (is_string($this->defaultValue)) {
$output .= ValueGenerator::escape($this->defaultValue);
} elseif ($this->defaultValue instanceof ValueGenerator) {
$this->defaultValue->setOutputMode(ValueGenerator::OUTPUT_SINGLE_LINE);
$output .= $this->defaultValue;
} else {
$output .= $this->defaultValue;
}
}
return $output;
}
}

View File

@@ -0,0 +1,226 @@
<?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\PropertyReflection;
class PropertyGenerator extends AbstractMemberGenerator
{
const FLAG_CONSTANT = 0x08;
/**
* @var bool
*/
protected $isConst = null;
/**
* @var PropertyValueGenerator
*/
protected $defaultValue = null;
/**
* @param PropertyReflection $reflectionProperty
* @return PropertyGenerator
*/
public static function fromReflection(PropertyReflection $reflectionProperty)
{
$property = new static();
$property->setName($reflectionProperty->getName());
$allDefaultProperties = $reflectionProperty->getDeclaringClass()->getDefaultProperties();
$property->setDefaultValue($allDefaultProperties[$reflectionProperty->getName()]);
if ($reflectionProperty->getDocComment() != '') {
$property->setDocBlock(DocBlockGenerator::fromReflection($reflectionProperty->getDocBlock()));
}
if ($reflectionProperty->isStatic()) {
$property->setStatic(true);
}
if ($reflectionProperty->isPrivate()) {
$property->setVisibility(self::VISIBILITY_PRIVATE);
} elseif ($reflectionProperty->isProtected()) {
$property->setVisibility(self::VISIBILITY_PROTECTED);
} else {
$property->setVisibility(self::VISIBILITY_PUBLIC);
}
$property->setSourceDirty(false);
return $property;
}
/**
* Generate from array
*
* @configkey name string [required] Class Name
* @configkey const bool
* @configkey defaultvalue null|bool|string|int|float|array|ValueGenerator
* @configkey flags int
* @configkey abstract bool
* @configkey final bool
* @configkey static bool
* @configkey visibility string
*
* @throws Exception\InvalidArgumentException
* @param array $array
* @return PropertyGenerator
*/
public static function fromArray(array $array)
{
if (!isset($array['name'])) {
throw new Exception\InvalidArgumentException(
'Property generator requires that a name is provided for this object'
);
}
$property = new static($array['name']);
foreach ($array as $name => $value) {
// normalize key
switch (strtolower(str_replace(array('.', '-', '_'), '', $name))) {
case 'const':
$property->setConst($value);
break;
case 'defaultvalue':
$property->setDefaultValue($value);
break;
case 'docblock':
$docBlock = ($value instanceof DocBlockGenerator) ? $value : DocBlockGenerator::fromArray($value);
$property->setDocBlock($docBlock);
break;
case 'flags':
$property->setFlags($value);
break;
case 'abstract':
$property->setAbstract($value);
break;
case 'final':
$property->setFinal($value);
break;
case 'static':
$property->setStatic($value);
break;
case 'visibility':
$property->setVisibility($value);
break;
}
}
return $property;
}
/**
* @param string $name
* @param PropertyValueGenerator|string|array $defaultValue
* @param int $flags
*/
public function __construct($name = null, $defaultValue = null, $flags = self::FLAG_PUBLIC)
{
if (null !== $name) {
$this->setName($name);
}
if (null !== $defaultValue) {
$this->setDefaultValue($defaultValue);
}
if ($flags !== self::FLAG_PUBLIC) {
$this->setFlags($flags);
}
}
/**
* @param bool $const
* @return PropertyGenerator
*/
public function setConst($const)
{
if ($const) {
$this->removeFlag(self::FLAG_PUBLIC | self::FLAG_PRIVATE | self::FLAG_PROTECTED);
$this->setFlags(self::FLAG_CONSTANT);
} else {
$this->removeFlag(self::FLAG_CONSTANT);
}
return $this;
}
/**
* @return bool
*/
public function isConst()
{
return (bool) ($this->flags & self::FLAG_CONSTANT);
}
/**
* @param PropertyValueGenerator|mixed $defaultValue
* @param string $defaultValueType
* @param string $defaultValueOutputMode
*
* @return PropertyGenerator
*/
public function setDefaultValue($defaultValue, $defaultValueType = PropertyValueGenerator::TYPE_AUTO, $defaultValueOutputMode = PropertyValueGenerator::OUTPUT_MULTIPLE_LINE)
{
if (!($defaultValue instanceof PropertyValueGenerator)) {
$defaultValue = new PropertyValueGenerator($defaultValue, $defaultValueType, $defaultValueOutputMode);
}
$this->defaultValue = $defaultValue;
return $this;
}
/**
* @return PropertyValueGenerator
*/
public function getDefaultValue()
{
return $this->defaultValue;
}
/**
* @throws Exception\RuntimeException
* @return string
*/
public function generate()
{
$name = $this->getName();
$defaultValue = $this->getDefaultValue();
$output = '';
if (($docBlock = $this->getDocBlock()) !== null) {
$docBlock->setIndentation(' ');
$output .= $docBlock->generate();
}
if ($this->isConst()) {
if ($defaultValue !== null && !$defaultValue->isValidConstantType()) {
throw new Exception\RuntimeException(sprintf(
'The property %s is said to be '
. 'constant but does not have a valid constant value.',
$this->name
));
}
$output .= $this->indentation . 'const ' . $name . ' = '
. (($defaultValue !== null) ? $defaultValue->generate() : 'null;');
} else {
$output .= $this->indentation
. $this->getVisibility()
. (($this->isStatic()) ? ' static' : '')
. ' $' . $name . ' = '
. (($defaultValue !== null) ? $defaultValue->generate() : 'null;');
}
return $output;
}
}

View File

@@ -0,0 +1,23 @@
<?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;
class PropertyValueGenerator extends ValueGenerator
{
protected $arrayDepth = 1;
/**
* @return string
*/
public function generate()
{
return parent::generate() . ';';
}
}

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

@@ -0,0 +1,435 @@
<?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\Stdlib\ArrayObject;
class ValueGenerator extends AbstractGenerator
{
/**#@+
* Constant values
*/
const TYPE_AUTO = 'auto';
const TYPE_BOOLEAN = 'boolean';
const TYPE_BOOL = 'bool';
const TYPE_NUMBER = 'number';
const TYPE_INTEGER = 'integer';
const TYPE_INT = 'int';
const TYPE_FLOAT = 'float';
const TYPE_DOUBLE = 'double';
const TYPE_STRING = 'string';
const TYPE_ARRAY = 'array';
const TYPE_CONSTANT = 'constant';
const TYPE_NULL = 'null';
const TYPE_OBJECT = 'object';
const TYPE_OTHER = 'other';
/**#@-*/
const OUTPUT_MULTIPLE_LINE = 'multipleLine';
const OUTPUT_SINGLE_LINE = 'singleLine';
/**
* @var mixed
*/
protected $value = null;
/**
* @var string
*/
protected $type = self::TYPE_AUTO;
/**
* @var int
*/
protected $arrayDepth = 0;
/**
* @var string
*/
protected $outputMode = self::OUTPUT_MULTIPLE_LINE;
/**
* @var array
*/
protected $allowedTypes = null;
/**
* Autodetectable constants
* @var ArrayObject
*/
protected $constants = null;
/**
* @param mixed $value
* @param string $type
* @param string $outputMode
* @param ArrayObject $constants
*/
public function __construct($value = null, $type = self::TYPE_AUTO, $outputMode = self::OUTPUT_MULTIPLE_LINE, ArrayObject $constants = null)
{
// strict check is important here if $type = AUTO
if ($value !== null) {
$this->setValue($value);
}
if ($type !== self::TYPE_AUTO) {
$this->setType($type);
}
if ($outputMode !== self::OUTPUT_MULTIPLE_LINE) {
$this->setOutputMode($outputMode);
}
if ($constants !== null) {
$this->constants = $constants;
} else {
$this->constants = new ArrayObject();
}
}
/**
* Init constant list by defined and magic constants
*/
public function initEnvironmentConstants()
{
$constants = array(
'__DIR__',
'__FILE__',
'__LINE__',
'__CLASS__',
'__TRAIT__',
'__METHOD__',
'__FUNCTION__',
'__NAMESPACE__',
'::'
);
$constants = array_merge($constants, array_keys(get_defined_constants()), $this->constants->getArrayCopy());
$this->constants->exchangeArray($constants);
}
/**
* Add constant to list
*
* @param string $constant
*
* @return $this
*/
public function addConstant($constant)
{
$this->constants->append($constant);
return $this;
}
/**
* Delete constant from constant list
*
* @param string $constant
*
* @return bool
*/
public function deleteConstant($constant)
{
if (($index = array_search($constant, $this->constants->getArrayCopy())) !== false) {
$this->constants->offsetUnset($index);
}
return $index !== false;
}
/**
* Return constant list
*
* @return ArrayObject
*/
public function getConstants()
{
return $this->constants;
}
/**
* @return bool
*/
public function isValidConstantType()
{
if ($this->type == self::TYPE_AUTO) {
$type = $this->getAutoDeterminedType($this->value);
} else {
$type = $this->type;
}
// valid types for constants
$scalarTypes = array(
self::TYPE_BOOLEAN,
self::TYPE_BOOL,
self::TYPE_NUMBER,
self::TYPE_INTEGER,
self::TYPE_INT,
self::TYPE_FLOAT,
self::TYPE_DOUBLE,
self::TYPE_STRING,
self::TYPE_CONSTANT,
self::TYPE_NULL
);
return in_array($type, $scalarTypes);
}
/**
* @param mixed $value
* @return ValueGenerator
*/
public function setValue($value)
{
$this->value = $value;
return $this;
}
/**
* @return mixed
*/
public function getValue()
{
return $this->value;
}
/**
* @param string $type
* @return ValueGenerator
*/
public function setType($type)
{
$this->type = (string) $type;
return $this;
}
/**
* @return string
*/
public function getType()
{
return $this->type;
}
/**
* @param int $arrayDepth
* @return ValueGenerator
*/
public function setArrayDepth($arrayDepth)
{
$this->arrayDepth = (int) $arrayDepth;
return $this;
}
/**
* @return int
*/
public function getArrayDepth()
{
return $this->arrayDepth;
}
/**
* @param string $type
* @return string
*/
protected function getValidatedType($type)
{
$types = array(
self::TYPE_AUTO,
self::TYPE_BOOLEAN,
self::TYPE_BOOL,
self::TYPE_NUMBER,
self::TYPE_INTEGER,
self::TYPE_INT,
self::TYPE_FLOAT,
self::TYPE_DOUBLE,
self::TYPE_STRING,
self::TYPE_ARRAY,
self::TYPE_CONSTANT,
self::TYPE_NULL,
self::TYPE_OBJECT,
self::TYPE_OTHER
);
if (in_array($type, $types)) {
return $type;
}
return self::TYPE_AUTO;
}
/**
* @param mixed $value
* @return string
*/
public function getAutoDeterminedType($value)
{
switch (gettype($value)) {
case 'boolean':
return self::TYPE_BOOLEAN;
case 'string':
foreach ($this->constants as $constant) {
if (strpos($value, $constant) !== false) {
return self::TYPE_CONSTANT;
}
}
return self::TYPE_STRING;
case 'double':
case 'float':
case 'integer':
return self::TYPE_NUMBER;
case 'array':
return self::TYPE_ARRAY;
case 'NULL':
return self::TYPE_NULL;
case 'object':
case 'resource':
case 'unknown type':
default:
return self::TYPE_OTHER;
}
}
/**
* @throws Exception\RuntimeException
* @return string
*/
public function generate()
{
$type = $this->type;
if ($type != self::TYPE_AUTO) {
$type = $this->getValidatedType($type);
}
$value = $this->value;
if ($type == self::TYPE_AUTO) {
$type = $this->getAutoDeterminedType($value);
}
if ($type == self::TYPE_ARRAY) {
foreach ($value as &$curValue) {
if ($curValue instanceof self) {
continue;
}
$curValue = new self($curValue, self::TYPE_AUTO, self::OUTPUT_MULTIPLE_LINE, $this->getConstants());
}
}
$output = '';
switch ($type) {
case self::TYPE_BOOLEAN:
case self::TYPE_BOOL:
$output .= ($value ? 'true' : 'false');
break;
case self::TYPE_STRING:
$output .= self::escape($value);
break;
case self::TYPE_NULL:
$output .= 'null';
break;
case self::TYPE_NUMBER:
case self::TYPE_INTEGER:
case self::TYPE_INT:
case self::TYPE_FLOAT:
case self::TYPE_DOUBLE:
case self::TYPE_CONSTANT:
$output .= $value;
break;
case self::TYPE_ARRAY:
$output .= 'array(';
if ($this->outputMode == self::OUTPUT_MULTIPLE_LINE) {
$output .= self::LINE_FEED . str_repeat($this->indentation, $this->arrayDepth + 1);
}
$outputParts = array();
$noKeyIndex = 0;
foreach ($value as $n => $v) {
/* @var $v ValueGenerator */
$v->setArrayDepth($this->arrayDepth + 1);
$partV = $v->generate();
$short = false;
if (is_int($n)) {
if ($n === $noKeyIndex) {
$short = true;
$noKeyIndex++;
} else {
$noKeyIndex = max($n + 1, $noKeyIndex);
}
}
if ($short) {
$outputParts[] = $partV;
} else {
$outputParts[] = (is_int($n) ? $n : self::escape($n)) . ' => ' . $partV;
}
}
$padding = ($this->outputMode == self::OUTPUT_MULTIPLE_LINE)
? self::LINE_FEED . str_repeat($this->indentation, $this->arrayDepth + 1)
: ' ';
$output .= implode(',' . $padding, $outputParts);
if ($this->outputMode == self::OUTPUT_MULTIPLE_LINE) {
if (count($outputParts) > 0) {
$output .= ',';
}
$output .= self::LINE_FEED . str_repeat($this->indentation, $this->arrayDepth);
}
$output .= ')';
break;
case self::TYPE_OTHER:
default:
throw new Exception\RuntimeException(
sprintf('Type "%s" is unknown or cannot be used as property default value.', get_class($value))
);
}
return $output;
}
/**
* Quotes value for PHP code.
*
* @param string $input Raw string.
* @param bool $quote Whether add surrounding quotes or not.
* @return string PHP-ready code.
*/
public static function escape($input, $quote = true)
{
$output = addcslashes($input, "\\'");
// adds quoting strings
if ($quote) {
$output = "'" . $output . "'";
}
return $output;
}
/**
* @param string $outputMode
* @return ValueGenerator
*/
public function setOutputMode($outputMode)
{
$this->outputMode = (string) $outputMode;
return $this;
}
/**
* @return string
*/
public function getOutputMode()
{
return $this->outputMode;
}
public function __toString()
{
return $this->generate();
}
}