Created
April 11, 2018 17:43
-
-
Save Ocramius/a7f99de6215a1cfa19b2fbd8873d1af9 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Tab; | |
class Baz | |
{ | |
/** | |
* @var string | |
*/ | |
private $a = null; | |
/** | |
* @var int | |
*/ | |
private $b = null; | |
/** | |
* @var \Bar\Foo | |
*/ | |
private $c = null; | |
private $e = null; | |
private $f = null; | |
/** | |
* @var \Bbb\Aaa | |
*/ | |
private $g = null; | |
/** | |
* @var string | |
*/ | |
private $h = null; | |
public function withA(string $a) : \Tab\Baz | |
{ | |
$instance = clone $this; | |
$instance->a = $a; | |
return $instance; | |
} | |
public function withoutA() : \Tab\Baz | |
{ | |
$instance = clone $this; | |
$instance->a = null; | |
return $instance; | |
} | |
public function withB(int $b) : \Tab\Baz | |
{ | |
$instance = clone $this; | |
$instance->b = $b; | |
return $instance; | |
} | |
public function withoutB() : \Tab\Baz | |
{ | |
$instance = clone $this; | |
$instance->b = null; | |
return $instance; | |
} | |
public function withC(\Bar\Foo $c) : \Tab\Baz | |
{ | |
$instance = clone $this; | |
$instance->c = $c; | |
return $instance; | |
} | |
public function withoutC() : \Tab\Baz | |
{ | |
$instance = clone $this; | |
$instance->c = null; | |
return $instance; | |
} | |
public function withE($e) : \Tab\Baz | |
{ | |
$instance = clone $this; | |
$instance->e = $e; | |
return $instance; | |
} | |
public function withoutE() : \Tab\Baz | |
{ | |
$instance = clone $this; | |
$instance->e = null; | |
return $instance; | |
} | |
public function withF($f) : \Tab\Baz | |
{ | |
$instance = clone $this; | |
$instance->f = $f; | |
return $instance; | |
} | |
public function withG(\Bbb\Aaa $g) : \Tab\Baz | |
{ | |
$instance = clone $this; | |
$instance->g = $g; | |
return $instance; | |
} | |
public function withH(string $h) : \Tab\Baz | |
{ | |
$instance = clone $this; | |
$instance->h = $h; | |
return $instance; | |
} | |
public function __construct($f, \Bbb\Aaa $g, string $h) | |
{ | |
$this->f = $f; | |
$this->g = $g; | |
$this->h = $h; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace GoetasWebservices\Xsd\XsdToPhp\Php; | |
use GoetasWebservices\Xsd\XsdToPhp\Php\Structure\PHPClass; | |
use GoetasWebservices\Xsd\XsdToPhp\Php\Structure\PHPProperty; | |
use Zend\Code\Generator\ClassGenerator; | |
use Zend\Code\Generator\DocBlock\Tag\VarTag; | |
use Zend\Code\Generator\DocBlockGenerator; | |
use Zend\Code\Generator\MethodGenerator; | |
use Zend\Code\Generator\ParameterGenerator; | |
use Zend\Code\Generator\PropertyGenerator; | |
final class ImmutableClassGenerator | |
{ | |
public function generate(PHPClass $type) | |
{ | |
$class = new ClassGenerator(); | |
$class->setName($type->getFullName()); | |
foreach ($type->getProperties() as $property) { | |
$propertyType = $property->getType(); | |
$phpType = $propertyType ? $propertyType->getPhpType() : null; | |
$defaultValue = $property->getDefault(); | |
$propertyGenerator = new PropertyGenerator( | |
$property->getName(), | |
$defaultValue, | |
PropertyGenerator::FLAG_PRIVATE | |
); | |
if ($phpType) { | |
// @TODO where do we get nullability from? | |
$propertyGenerator->setDocBlock( | |
(new DocBlockGenerator()) | |
->setTag(new VarTag(null, $phpType)) | |
); | |
} | |
$class->addPropertyFromGenerator($propertyGenerator); | |
$class->addMethodFromGenerator($this->makeWithMethod($type, $property)); | |
$withoutMethod = $this->makeWithoutMethod($type, $property); | |
if ($withoutMethod) { | |
$class->addMethodFromGenerator($withoutMethod); | |
} | |
} | |
$class->addMethodFromGenerator($this->makeConstructor($type)); | |
echo $class->generate(); | |
exit(1); | |
} | |
private function makeWithMethod(PHPClass $class, PHPProperty $property) : MethodGenerator | |
{ | |
$propertyType = $property->getType(); | |
$propertyPhpType = $propertyType ? $propertyType->getPhpType() : null; | |
$propertyName = $property->getName(); | |
$method = new MethodGenerator('with' . ucfirst($propertyName)); | |
$method->setParameter(new ParameterGenerator($propertyName, $propertyPhpType)); | |
$method->setReturnType($class->getFullName()); | |
$method->setBody(\sprintf( | |
<<<'PHP' | |
$instance = clone $this; | |
$instance->%s = $%s; | |
return $instance; | |
PHP | |
, | |
$propertyName, | |
$propertyName | |
)); | |
return $method; | |
} | |
private function makeWithoutMethod(PHPClass $class, PHPProperty $property) : ?MethodGenerator | |
{ | |
if ($property->getRequired()) { | |
return null; | |
} | |
$propertyName = $property->getName(); | |
$method = new MethodGenerator('without' . ucfirst($propertyName)); | |
$method->setReturnType($class->getFullName()); | |
$method->setBody(\sprintf( | |
<<<'PHP' | |
$instance = clone $this; | |
$instance->%s = null; | |
return $instance; | |
PHP | |
, | |
$propertyName | |
)); | |
return $method; | |
} | |
private function makeConstructor(PHPClass $type) | |
{ | |
/** @var $requiredProperties PHPProperty[] */ | |
$requiredProperties = \array_filter( | |
$type->getProperties(), | |
function (PHPProperty $property) : bool { | |
return $property->getRequired(); | |
} | |
); | |
$constructor = new MethodGenerator('__construct'); | |
$body = ''; | |
foreach ($requiredProperties as $requiredProperty) { | |
$propertyType = $requiredProperty->getType(); | |
$propertyName = $requiredProperty->getName(); | |
$propertyPhpType = $propertyType ? $propertyType->getPhpType() : null; | |
$mandatoryParameter = new ParameterGenerator( | |
$requiredProperty->getName(), | |
$propertyPhpType | |
); | |
$body .= '$this->' . $propertyName . ' = $' . $propertyName . ';' . "\n"; | |
$constructor->setParameter($mandatoryParameter); | |
} | |
$constructor->setBody($body); | |
return $constructor; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace GoetasWebservices\Xsd\XsdToPhp\Tests\JmsSerializer\OTA; | |
use GoetasWebservices\Xsd\XsdToPhp\Naming\ShortNamingStrategy; | |
use GoetasWebservices\Xsd\XsdToPhp\Php\ClassGenerator; | |
use GoetasWebservices\Xsd\XsdToPhp\Php\ImmutableClassGenerator; | |
use GoetasWebservices\Xsd\XsdToPhp\Php\PhpConverter; | |
use GoetasWebservices\XML\XSDReader\SchemaReader; | |
use GoetasWebservices\Xsd\XsdToPhp\Php\Structure\PHPClass; | |
use GoetasWebservices\Xsd\XsdToPhp\Php\Structure\PHPProperty; | |
class ImmutableClassGeneratorTest extends \PHPUnit_Framework_TestCase | |
{ | |
public function testFoo() : void | |
{ | |
$class = new PHPClass('Baz', 'Tab'); | |
$a = new PHPProperty('a', new PHPClass('string')); | |
$b = new PHPProperty('b', new PHPClass('int')); | |
$c = new PHPProperty('c', new PHPClass('Foo', 'Bar')); | |
// $d = new PHPProperty('d', new PHPClass('string[]')); | |
$e = new PHPProperty('e'); | |
$f = new PHPProperty('f'); | |
$g = new PHPProperty('g', new PHPClass('Aaa', 'Bbb')); | |
$h = new PHPProperty('h', new PHPClass('string')); | |
// $d->setDefault(['a', 'b', 'c']); | |
$f->setRequired(true); | |
$g->setRequired(true); | |
$h->setRequired(true); | |
$class | |
->addProperty($a) | |
->addProperty($b) | |
->addProperty($c) | |
// ->addProperty($d) | |
->addProperty($e) | |
->addProperty($f) | |
->addProperty($g) | |
->addProperty($h) | |
; | |
(new ImmutableClassGenerator())->generate($class); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment