Skip to content

Commit 5621827

Browse files
authored
Merge pull request #157 from moufmouf/dao_factory_zend_code
Generating DaoFactory with ZendCode
2 parents 18f4b45 + b22b40b commit 5621827

File tree

6 files changed

+247
-75
lines changed

6 files changed

+247
-75
lines changed

src/Utils/BaseCodeGeneratorListener.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,4 +135,30 @@ public function onBaseDaoFindByIndexGenerated(MethodGenerator $methodGenerator,
135135
{
136136
return $methodGenerator;
137137
}
138+
139+
/**
140+
* @param BeanDescriptor[] $beanDescriptors
141+
*/
142+
public function onDaoFactoryGenerated(FileGenerator $fileGenerator, array $beanDescriptors, ConfigurationInterface $configuration): ?FileGenerator
143+
{
144+
return $fileGenerator;
145+
}
146+
147+
/**
148+
* @param BeanDescriptor[] $beanDescriptors
149+
*/
150+
public function onDaoFactoryConstructorGenerated(MethodGenerator $methodGenerator, array $beanDescriptors, ConfigurationInterface $configuration, ClassGenerator $classGenerator): ?MethodGenerator
151+
{
152+
return $methodGenerator;
153+
}
154+
155+
public function onDaoFactoryGetterGenerated(MethodGenerator $methodGenerator, BeanDescriptor $beanDescriptor, ConfigurationInterface $configuration, ClassGenerator $classGenerator): ?MethodGenerator
156+
{
157+
return $methodGenerator;
158+
}
159+
160+
public function onDaoFactorySetterGenerated(MethodGenerator $methodGenerator, BeanDescriptor $beanDescriptor, ConfigurationInterface $configuration, ClassGenerator $classGenerator): ?MethodGenerator
161+
{
162+
return $methodGenerator;
163+
}
138164
}

src/Utils/CodeGeneratorEventDispatcher.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,4 +263,54 @@ public function onBaseDaoFindByIndexGenerated(MethodGenerator $methodGenerator,
263263
}
264264
return $methodGenerator;
265265
}
266+
267+
/**
268+
* @param BeanDescriptor[] $beanDescriptors
269+
*/
270+
public function onDaoFactoryGenerated(FileGenerator $fileGenerator, array $beanDescriptors, ConfigurationInterface $configuration): ?FileGenerator
271+
{
272+
foreach ($this->listeners as $listener) {
273+
$fileGenerator = $listener->onDaoFactoryGenerated($fileGenerator, $beanDescriptors, $configuration);
274+
if ($fileGenerator === null) {
275+
break;
276+
}
277+
}
278+
return $fileGenerator;
279+
}
280+
281+
/**
282+
* @param BeanDescriptor[] $beanDescriptors
283+
*/
284+
public function onDaoFactoryConstructorGenerated(MethodGenerator $methodGenerator, array $beanDescriptors, ConfigurationInterface $configuration, ClassGenerator $classGenerator): ?MethodGenerator
285+
{
286+
foreach ($this->listeners as $listener) {
287+
$methodGenerator = $listener->onDaoFactoryConstructorGenerated($methodGenerator, $beanDescriptors, $configuration, $classGenerator);
288+
if ($methodGenerator === null) {
289+
break;
290+
}
291+
}
292+
return $methodGenerator;
293+
}
294+
295+
public function onDaoFactoryGetterGenerated(MethodGenerator $methodGenerator, BeanDescriptor $beanDescriptor, ConfigurationInterface $configuration, ClassGenerator $classGenerator): ?MethodGenerator
296+
{
297+
foreach ($this->listeners as $listener) {
298+
$methodGenerator = $listener->onDaoFactoryGetterGenerated($methodGenerator, $beanDescriptor, $configuration, $classGenerator);
299+
if ($methodGenerator === null) {
300+
break;
301+
}
302+
}
303+
return $methodGenerator;
304+
}
305+
306+
public function onDaoFactorySetterGenerated(MethodGenerator $methodGenerator, BeanDescriptor $beanDescriptor, ConfigurationInterface $configuration, ClassGenerator $classGenerator): ?MethodGenerator
307+
{
308+
foreach ($this->listeners as $listener) {
309+
$methodGenerator = $listener->onDaoFactorySetterGenerated($methodGenerator, $beanDescriptor, $configuration, $classGenerator);
310+
if ($methodGenerator === null) {
311+
break;
312+
}
313+
}
314+
return $methodGenerator;
315+
}
266316
}

src/Utils/CodeGeneratorListenerInterface.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,18 @@ public function onBaseDaoFindOneFromSqlGenerated(MethodGenerator $methodGenerato
7979
public function onBaseDaoSetDefaultSortGenerated(MethodGenerator $methodGenerator, BeanDescriptor $beanDescriptor, ConfigurationInterface $configuration, ClassGenerator $classGenerator): ?MethodGenerator;
8080

8181
public function onBaseDaoFindByIndexGenerated(MethodGenerator $methodGenerator, Index $index, BeanDescriptor $beanDescriptor, ConfigurationInterface $configuration, ClassGenerator $classGenerator): ?MethodGenerator;
82+
83+
/**
84+
* @param BeanDescriptor[] $beanDescriptors
85+
*/
86+
public function onDaoFactoryGenerated(FileGenerator $fileGenerator, array $beanDescriptors, ConfigurationInterface $configuration): ?FileGenerator;
87+
88+
/**
89+
* @param BeanDescriptor[] $beanDescriptors
90+
*/
91+
public function onDaoFactoryConstructorGenerated(MethodGenerator $methodGenerator, array $beanDescriptors, ConfigurationInterface $configuration, ClassGenerator $classGenerator): ?MethodGenerator;
92+
93+
public function onDaoFactoryGetterGenerated(MethodGenerator $methodGenerator, BeanDescriptor $beanDescriptor, ConfigurationInterface $configuration, ClassGenerator $classGenerator): ?MethodGenerator;
94+
95+
public function onDaoFactorySetterGenerated(MethodGenerator $methodGenerator, BeanDescriptor $beanDescriptor, ConfigurationInterface $configuration, ClassGenerator $classGenerator): ?MethodGenerator;
8296
}

src/Utils/TDBMDaoGenerator.php

Lines changed: 96 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,26 @@
77
use Doctrine\DBAL\Schema\Schema;
88
use Doctrine\DBAL\Schema\Table;
99
use Doctrine\DBAL\Types\Type;
10+
use Psr\Container\ContainerInterface;
11+
use TheCodingMachine\TDBM\Schema\ForeignKeys;
12+
use TheCodingMachine\TDBM\TDBMService;
13+
use Zend\Code\Generator\AbstractMemberGenerator;
14+
use Zend\Code\Generator\ClassGenerator;
15+
use Zend\Code\Generator\DocBlock\Tag\VarTag;
16+
use Zend\Code\Generator\DocBlockGenerator;
17+
use Zend\Code\Generator\FileGenerator;
18+
use Zend\Code\Generator\MethodGenerator;
19+
use Zend\Code\Generator\ParameterGenerator;
20+
use Zend\Code\Generator\PropertyGenerator;
1021
use function str_replace;
1122
use TheCodingMachine\TDBM\ConfigurationInterface;
1223
use TheCodingMachine\TDBM\TDBMException;
1324
use TheCodingMachine\TDBM\TDBMSchemaAnalyzer;
1425
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
1526
use Symfony\Component\Filesystem\Filesystem;
27+
use function strpos;
28+
use function substr;
29+
use function var_export;
1630

1731
/**
1832
* This class generates automatically DAOs and Beans for TDBM.
@@ -88,7 +102,7 @@ public function generateAllDaosAndBeans(): void
88102
}
89103

90104

91-
$this->generateFactory($tableList);
105+
$this->generateFactory($beanDescriptors);
92106

93107
// Let's call the list of listeners
94108
$this->eventDispatcher->onGenerate($this->configuration, $beanDescriptors);
@@ -279,93 +293,105 @@ private function psr2Fix(string $content): string
279293
/**
280294
* Generates the factory bean.
281295
*
282-
* @param Table[] $tableList
296+
* @param BeanDescriptor[] $beanDescriptors
283297
* @throws TDBMException
284298
*/
285-
private function generateFactory(array $tableList) : void
299+
private function generateFactory(array $beanDescriptors) : void
286300
{
287301
$daoNamespace = $this->configuration->getDaoNamespace();
288302
$daoFactoryClassName = $this->namingStrategy->getDaoFactoryClassName();
289303

304+
$file = new FileGenerator();
305+
$file->setDocBlock(
306+
new DocBlockGenerator(
307+
<<<DOC
308+
This file has been automatically generated by TDBM.
309+
DO NOT edit this file, as it might be overwritten.
310+
DOC
311+
)
312+
);
313+
$class = new ClassGenerator();
314+
$file->setClass($class);
315+
$class->setName($daoFactoryClassName);
316+
$file->setNamespace($daoNamespace.'\\Generated');
317+
318+
$class->setDocBlock(new DocBlockGenerator("The $daoFactoryClassName provides an easy access to all DAOs generated by TDBM."));
319+
320+
$containerProperty = new PropertyGenerator('container');
321+
$containerProperty->setVisibility(AbstractMemberGenerator::VISIBILITY_PRIVATE);
322+
$containerProperty->setDocBlock(new DocBlockGenerator(null, null, [new VarTag(null, ['\\'.ContainerInterface::class])]));
323+
$class->addPropertyFromGenerator($containerProperty);
324+
325+
$constructorMethod = new MethodGenerator(
326+
'__construct',
327+
[ new ParameterGenerator('container', ContainerInterface::class) ],
328+
MethodGenerator::FLAG_PUBLIC,
329+
'$this->container = $container;'
330+
);
331+
$constructorMethod = $this->configuration->getCodeGeneratorListener()->onDaoFactoryConstructorGenerated($constructorMethod, $beanDescriptors, $this->configuration, $class);
332+
if ($constructorMethod !== null) {
333+
$class->addMethodFromGenerator($constructorMethod);
334+
}
335+
290336
// For each table, let's write a property.
337+
foreach ($beanDescriptors as $beanDescriptor) {
338+
$daoClassName = $beanDescriptor->getDaoClassName();
339+
$daoInstanceName = self::toVariableName($daoClassName);
291340

292-
$str = "<?php
293-
declare(strict_types=1);
341+
$daoInstanceProperty = new PropertyGenerator($daoInstanceName);
342+
$daoInstanceProperty->setVisibility(AbstractMemberGenerator::VISIBILITY_PRIVATE);
343+
$daoInstanceProperty->setDocBlock(new DocBlockGenerator(null, null, [new VarTag(null, ['\\' . $daoNamespace . '\\' . $daoClassName, 'null'])]));
344+
$class->addPropertyFromGenerator($daoInstanceProperty);
294345

295-
/*
296-
* This file has been automatically generated by TDBM.
297-
* DO NOT edit this file, as it might be overwritten.
298-
*/
346+
$fullClassNameVarExport = var_export($daoNamespace.'\\'.$daoClassName, true);
347+
$getterBody = <<<BODY
348+
if (!\$this->$daoInstanceName) {
349+
\$this->$daoInstanceName = \$this->container->get($fullClassNameVarExport);
350+
}
299351
300-
namespace {$daoNamespace}\\Generated;
352+
return \$this->$daoInstanceName;
353+
BODY;
354+
355+
$getterMethod = new MethodGenerator(
356+
'get' . $daoClassName,
357+
[],
358+
MethodGenerator::FLAG_PUBLIC,
359+
$getterBody
360+
);
361+
$getterMethod->setReturnType($daoNamespace.'\\'.$daoClassName);
362+
$getterMethod = $this->configuration->getCodeGeneratorListener()->onDaoFactoryGetterGenerated($getterMethod, $beanDescriptor, $this->configuration, $class);
363+
if ($getterMethod !== null) {
364+
$class->addMethodFromGenerator($getterMethod);
365+
}
301366

302-
use Psr\Container\ContainerInterface;
303-
";
304-
foreach ($tableList as $table) {
305-
$tableName = $table->getName();
306-
$daoClassName = $this->namingStrategy->getDaoClassName($tableName);
307-
$str .= "use {$daoNamespace}\\".$daoClassName.";\n";
367+
$setterMethod = new MethodGenerator(
368+
'set' . $daoClassName,
369+
[new ParameterGenerator($daoInstanceName, '\\' . $daoNamespace . '\\' . $daoClassName)],
370+
MethodGenerator::FLAG_PUBLIC,
371+
'$this->' . $daoInstanceName . ' = $' . $daoInstanceName . ';'
372+
);
373+
$setterMethod->setReturnType('void');
374+
$setterMethod = $this->configuration->getCodeGeneratorListener()->onDaoFactorySetterGenerated($setterMethod, $beanDescriptor, $this->configuration, $class);
375+
if ($setterMethod !== null) {
376+
$class->addMethodFromGenerator($setterMethod);
377+
}
308378
}
309379

310-
$str .= "
311-
/**
312-
* The $daoFactoryClassName provides an easy access to all DAOs generated by TDBM.
313-
*
314-
*/
315-
class $daoFactoryClassName
316-
{
317-
private \$container;
318-
319-
public function __construct(ContainerInterface \$container)
320-
{
321-
\$this->container = \$container;
322-
}
323-
380+
$file = $this->configuration->getCodeGeneratorListener()->onDaoFactoryGenerated($file, $beanDescriptors, $this->configuration);
324381

325-
";
382+
if ($file !== null) {
383+
$possibleFileName = $this->configuration->getPathFinder()->getPath($daoNamespace.'\\Generated\\'.$daoFactoryClassName)->getPathname();
326384

327-
foreach ($tableList as $table) {
328-
$tableName = $table->getName();
329-
$daoClassName = $this->namingStrategy->getDaoClassName($tableName);
330-
$daoInstanceName = self::toVariableName($daoClassName);
385+
$fileContent = $file->generate();
331386

332-
$str .= ' /**
333-
* @var '.$daoClassName.'|null
334-
*/
335-
private $'.$daoInstanceName.';
336-
337-
/**
338-
* Returns an instance of the '.$daoClassName.' class.
339-
*
340-
* @return '.$daoClassName.'
341-
*/
342-
public function get'.$daoClassName.'() : '.$daoClassName.'
343-
{
344-
if (!$this->'.$daoInstanceName.') {
345-
$this->'.$daoInstanceName.' = $this->container->get('.$daoClassName.'::class);
346-
}
347-
348-
return $this->'.$daoInstanceName.';
349-
}
387+
// Hard code PSR-2 fix
388+
$fileContent = $this->psr2Fix($fileContent);
389+
// Add the declare strict-types directive
390+
$commentEnd = strpos($fileContent, ' */') + 3;
391+
$fileContent = substr($fileContent, 0, $commentEnd) . "\n\ndeclare(strict_types=1);" . substr($fileContent, $commentEnd + 1);
350392

351-
/**
352-
* Override the instance of the '.$daoClassName.' class that will be returned by the factory getter.
353-
*
354-
* @param '.$daoClassName.' $'.$daoInstanceName.'
355-
*/
356-
public function set'.$daoClassName.'('.$daoClassName.' $'.$daoInstanceName.') : void
357-
{
358-
$this->'.$daoInstanceName.' = $'.$daoInstanceName.';
359-
}';
393+
$this->dumpFile($possibleFileName, $fileContent);
360394
}
361-
362-
$str .= '
363-
}
364-
';
365-
366-
$possibleFileName = $this->configuration->getPathFinder()->getPath($daoNamespace.'\\Generated\\'.$daoFactoryClassName)->getPathname();
367-
368-
$this->dumpFile($possibleFileName, $str);
369395
}
370396

371397
/**

tests/Utils/CodeGeneratorEventDispatcherTest.php

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,38 @@ public function onBaseDaoFindByIndexGenerated(MethodGenerator $methodGenerator,
131131
{
132132
return null;
133133
}
134+
135+
/**
136+
* @param BeanDescriptor[] $beanDescriptors
137+
*/
138+
public function onDaoFactoryGenerated(FileGenerator $fileGenerator, array $beanDescriptors, ConfigurationInterface $configuration): ?FileGenerator
139+
{
140+
return null;
141+
}
142+
143+
/**
144+
* @param BeanDescriptor[] $beanDescriptors
145+
*/
146+
public function onDaoFactoryConstructorGenerated(MethodGenerator $methodGenerator, array $beanDescriptors, ConfigurationInterface $configuration, ClassGenerator $classGenerator): ?MethodGenerator
147+
{
148+
return null;
149+
}
150+
151+
/**
152+
* @param BeanDescriptor[] $beanDescriptor
153+
*/
154+
public function onDaoFactoryGetterGenerated(MethodGenerator $methodGenerator, BeanDescriptor $beanDescriptor, ConfigurationInterface $configuration, ClassGenerator $classGenerator): ?MethodGenerator
155+
{
156+
return null;
157+
}
158+
159+
/**
160+
* @param BeanDescriptor[] $beanDescriptor
161+
*/
162+
public function onDaoFactorySetterGenerated(MethodGenerator $methodGenerator, BeanDescriptor $beanDescriptor, ConfigurationInterface $configuration, ClassGenerator $classGenerator): ?MethodGenerator
163+
{
164+
return null;
165+
}
134166
}]);
135167
$this->method1 = new MethodGenerator();
136168
$this->method2 = new MethodGenerator();
@@ -266,4 +298,28 @@ public function testOnBaseDaoFindByIndexGenerated(): void
266298
$this->assertSame($this->method1, $this->dispatcher->onBaseDaoFindByIndexGenerated($this->method1, $index, $this->beanDescriptor, $this->configuration, $this->class));
267299
$this->assertSame(null, $this->nullDispatcher->onBaseDaoFindByIndexGenerated($this->method1, $index, $this->beanDescriptor, $this->configuration, $this->class));
268300
}
301+
302+
public function testOnDaoFactoryGenerated(): void
303+
{
304+
$this->assertSame($this->file, $this->dispatcher->onDaoFactoryGenerated($this->file, [], $this->configuration));
305+
$this->assertSame(null, $this->nullDispatcher->onDaoFactoryGenerated($this->file, [], $this->configuration));
306+
}
307+
308+
public function testOnDaoFactoryConstructorGenerated(): void
309+
{
310+
$this->assertSame($this->method1, $this->dispatcher->onDaoFactoryConstructorGenerated($this->method1, [], $this->configuration, $this->class));
311+
$this->assertSame(null, $this->nullDispatcher->onDaoFactoryConstructorGenerated($this->method1, [], $this->configuration, $this->class));
312+
}
313+
314+
public function testOnDaoFactoryGetterGenerated(): void
315+
{
316+
$this->assertSame($this->method1, $this->dispatcher->onDaoFactoryGetterGenerated($this->method1, $this->beanDescriptor, $this->configuration, $this->class));
317+
$this->assertSame(null, $this->nullDispatcher->onDaoFactoryGetterGenerated($this->method1, $this->beanDescriptor, $this->configuration, $this->class));
318+
}
319+
320+
public function testOnDaoFactorySetterGenerated(): void
321+
{
322+
$this->assertSame($this->method1, $this->dispatcher->onDaoFactorySetterGenerated($this->method1, $this->beanDescriptor, $this->configuration, $this->class));
323+
$this->assertSame(null, $this->nullDispatcher->onDaoFactorySetterGenerated($this->method1, $this->beanDescriptor, $this->configuration, $this->class));
324+
}
269325
}

0 commit comments

Comments
 (0)