Skip to content

Commit

Permalink
Fixes zendframework#6274 added proper support for constants
Browse files Browse the repository at this point in the history
  • Loading branch information
steverhoades authored and dima committed Nov 27, 2014
1 parent 191df68 commit 1ebc5b7
Show file tree
Hide file tree
Showing 2 changed files with 307 additions and 0 deletions.
133 changes: 133 additions & 0 deletions library/Zend/Code/Generator/ClassGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ class ClassGenerator extends AbstractGenerator
*/
protected $properties = array();

/**
* @var PropertyGenerator[] Array of properties
*/
protected $constants = array();

/**
* @var MethodGenerator[] Array of methods
*/
Expand Down Expand Up @@ -116,6 +121,12 @@ public static function fromReflection(ClassReflection $classReflection)
}
$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();
Expand Down Expand Up @@ -421,6 +432,109 @@ 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[]
*/
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
));
} else if (false === $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 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
Expand Down Expand Up @@ -460,6 +574,12 @@ public function addProperty($name, $defaultValue = null, $flags = PropertyGenera
));
}

// 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));
}

Expand All @@ -481,6 +601,12 @@ public function addPropertyFromGenerator(PropertyGenerator $property)
));
}

// backwards compatibility
// @todo remove this on next major version
if($property->isConst()) {
return $this->addConstantFromGenerator($property);
}

$this->properties[$propertyName] = $property;
return $this;
}
Expand Down Expand Up @@ -726,6 +852,13 @@ public function generate()

$output .= self::LINE_FEED . '{' . self::LINE_FEED . self::LINE_FEED;

$constants = $this->getConstants();
if(!empty($constants)) {
foreach ($constants as $constant) {
$output .= $constant->generate() . self::LINE_FEED . self::LINE_FEED;
}
}

$properties = $this->getProperties();
if (!empty($properties)) {
foreach ($properties as $property) {
Expand Down
174 changes: 174 additions & 0 deletions tests/ZendTest/Code/Generator/ClassGeneratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,7 @@ public function methodOne()
}

/**
<<<<<<< Upstream, based on zf2/master
* @group 6253
*/
public function testHereDoc()
Expand Down Expand Up @@ -530,5 +531,178 @@ public function someFunction()
CODE;

$this->assertEquals($contents, $classGenerator->generate());
=======
* @group 6274
*/
public function testCanAddConstant()
{
$classGenerator = new ClassGenerator();
$classGenerator->setName('My\Class');
$classGenerator->addConstant('x', 'value');

$this->assertTrue($classGenerator->hasConstant('x'));
$constant = $classGenerator->getConstant('x');
$this->assertTrue($constant instanceof PropertyGenerator);
$this->assertTrue($constant->isConst());
$this->assertEquals($constant->getDefaultValue()->getValue(), 'value');

}

/**
* @group 6274
*/
public function testCanAddConstantsWithArrayOfGenerators()
{
$constants = array(
new PropertyGenerator('x', 'value1', PropertyGenerator::FLAG_CONSTANT),
new PropertyGenerator('y', 'value2', PropertyGenerator::FLAG_CONSTANT)
);
$classGenerator = new ClassGenerator();
$classGenerator->addConstants($constants);

$this->assertEquals(count($classGenerator->getConstants()), 2);
$constantX = $classGenerator->getConstant('x');
$constantY = $classGenerator->getConstant('y');

$this->assertEquals($constantX->getDefaultValue()->getValue(), 'value1');
$this->assertEquals($constantY->getDefaultValue()->getValue(), 'value2');
}

/**
* @group 6274
*/
public function testCanAddConstantsWithArrayOfKeyValues()
{
$constants = array(
array( 'name'=> 'x', 'value' => 'value1'),
array('name' => 'y', 'value' => 'value2')
);
$classGenerator = new ClassGenerator();
$classGenerator->addConstants($constants);

$this->assertEquals(count($classGenerator->getConstants()), 2);
$constantX = $classGenerator->getConstant('x');
$constantY = $classGenerator->getConstant('y');

$this->assertEquals($constantX->getDefaultValue()->getValue(), 'value1');
$this->assertEquals($constantY->getDefaultValue()->getValue(), 'value2');
}

/**
* @group 6274
*/
public function testAddConstantThrowsExceptionWithInvalidName()
{
$this->setExpectedException('InvalidArgumentException');
$classGenerator = new ClassGenerator();
$classGenerator->addConstant(array(), 'value1');
}

/**
* @group 6274
*/
public function testAddConstantThrowsExceptionWithInvalidValue()
{
$this->setExpectedException('InvalidArgumentException');
$classGenerator = new ClassGenerator();
$classGenerator->addConstant('x', null);
}

/**
* @group 6274
*/
public function testAddConstantThrowsExceptionOnDuplicate()
{
$this->setExpectedException('InvalidArgumentException');
$classGenerator = new ClassGenerator();
$classGenerator->addConstant('x', 'value1');
$classGenerator->addConstant('x', 'value1');
}

/**
* @group 6274
*/
public function testAddPropertyIsBackwardsCompatibleWithConstants()
{
$classGenerator = new ClassGenerator();
$classGenerator->addProperty('x', 'value1', PropertyGenerator::FLAG_CONSTANT);

$constantX = $classGenerator->getConstant('x');

$this->assertEquals($constantX->getDefaultValue()->getValue(), 'value1');
}

/**
* @group 6274
*/
public function testAddPropertiesIsBackwardsCompatibleWithConstants()
{
$constants = array(
new PropertyGenerator('x', 'value1', PropertyGenerator::FLAG_CONSTANT),
new PropertyGenerator('y', 'value2', PropertyGenerator::FLAG_CONSTANT)
);
$classGenerator = new ClassGenerator();
$classGenerator->addProperties($constants);

$this->assertEquals(count($classGenerator->getConstants()), 2);
$constantX = $classGenerator->getConstant('x');
$constantY = $classGenerator->getConstant('y');

$this->assertEquals($constantX->getDefaultValue()->getValue(), 'value1');
$this->assertEquals($constantY->getDefaultValue()->getValue(), 'value2');
}

/**
* @group 6274
*/
public function testConstantsAddedFromReflection()
{
$reflector = new ClassReflection('ZendTest\Code\Generator\TestAsset\TestClassWithManyProperties');
$classGenerator = ClassGenerator::fromReflection($reflector);

$constant = $classGenerator->getConstant('FOO');
$this->assertEquals($constant->getDefaultValue()->getValue(), 'foo');
}

/**
* @group 6274
*/
public function testClassCanBeGeneratedWithConstantAndPropertyWithSameName()
{
$reflector = new ClassReflection('ZendTest\Code\Generator\TestAsset\TestSampleSingleClass');
$classGenerator = ClassGenerator::fromReflection($reflector);
$classGenerator->addProperty('fooProperty', true, PropertyGenerator::FLAG_PUBLIC);
$classGenerator->addConstant('fooProperty', 'duplicate');

$contents = <<<'CODE'
namespace ZendTest\Code\Generator\TestAsset;
/**
* class docblock
*/
class TestSampleSingleClass
{
const fooProperty = 'duplicate';
public $fooProperty = true;
/**
* Enter description here...
*
* @return bool
*/
public function someMethod()
{
/* test test */
}
}

CODE;

$this->assertEquals($classGenerator->generate(), $contents);
>>>>>>> ffeb9c9 Fixes #6274 added proper support for constants
}
}

0 comments on commit 1ebc5b7

Please sign in to comment.