Skip to content
This repository was archived by the owner on Oct 28, 2025. It is now read-only.

Commit 2d69331

Browse files
committed
add base path code to model maker
1 parent 977ca21 commit 2d69331

File tree

3 files changed

+145
-13
lines changed

3 files changed

+145
-13
lines changed

src/Maker/MakeModel.php

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
namespace GeekCell\DddBundle\Maker;
66

7-
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
87
use Doctrine\ORM\QueryBuilder;
98
use Doctrine\Persistence\ManagerRegistry;
109
use GeekCell\Ddd\Contracts\Domain\Repository;
@@ -32,6 +31,7 @@
3231
use Symfony\Component\Console\Input\InputOption;
3332
use GeekCell\DddBundle\Infrastructure\Doctrine\Repository as OrmRepository;
3433

34+
use Symfony\Component\Filesystem\Path;
3535
use function Symfony\Component\String\u;
3636

3737
const DOCTRINE_CONFIG_PATH = 'config/packages/doctrine.yaml';
@@ -112,6 +112,13 @@ public function configureCommand(Command $command, InputConfiguration $inputConf
112112
'Adds the suffix "Model" to the model class name',
113113
null
114114
)
115+
->addOption(
116+
'base-path',
117+
null,
118+
InputOption::VALUE_REQUIRED,
119+
'Base path from which to generate model & config.',
120+
null
121+
)
115122
;
116123
}
117124

@@ -199,6 +206,14 @@ public function interact(InputInterface $input, ConsoleStyle $io, Command $comma
199206
);
200207
$input->setOption('entity', $asEntity);
201208
}
209+
210+
if (null === $input->getOption('base-path')) {
211+
$basePath = $io->ask(
212+
'Which base path should be used? Default is "' . PathGenerator::DEFAULT_BASE_PATH . '"',
213+
PathGenerator::DEFAULT_BASE_PATH,
214+
);
215+
$input->setOption('base-path', $basePath);
216+
}
202217
}
203218

204219
/**
@@ -209,19 +224,20 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen
209224
/** @var string $modelName */
210225
$modelName = $input->getArgument('name');
211226
$suffix = $input->getOption('with-suffix') ? 'Model' : '';
227+
$pathGenerator = new PathGenerator($input->getOption('base-path'));
212228

213229
$modelClassNameDetails = $generator->createClassNameDetails(
214230
$modelName,
215-
'Domain\\Model\\',
231+
$pathGenerator->namespacePrefix('Domain\\Model\\'),
216232
$suffix,
217233
);
218234

219235
$this->templateVariables['class_name'] = $modelClassNameDetails->getShortName();
220236

221-
$identityClassNameDetails = $this->generateIdentity($modelName, $input, $io, $generator);
222-
$this->generateEntityMappings($modelClassNameDetails, $input, $io, $generator);
237+
$identityClassNameDetails = $this->generateIdentity($modelName, $input, $io, $generator, $pathGenerator);
238+
$this->generateEntityMappings($modelClassNameDetails, $input, $io, $generator, $pathGenerator);
223239
$this->generateEntity($modelClassNameDetails, $input, $generator);
224-
$this->generateRepository($generator, $input, $modelClassNameDetails, $identityClassNameDetails);
240+
$this->generateRepository($generator, $input, $pathGenerator, $modelClassNameDetails, $identityClassNameDetails);
225241

226242
$this->writeSuccessMessage($io);
227243
}
@@ -239,7 +255,8 @@ private function generateIdentity(
239255
string $modelName,
240256
InputInterface $input,
241257
ConsoleStyle $io,
242-
Generator $generator
258+
Generator $generator,
259+
PathGenerator $pathGenerator
243260
): ?ClassNameDetails {
244261
if (!$this->shouldGenerateIdentity($input)) {
245262
return null;
@@ -251,7 +268,7 @@ private function generateIdentity(
251268
$identityType = $input->getOption('with-identity');
252269
$identityClassNameDetails = $generator->createClassNameDetails(
253270
$modelName,
254-
'Domain\\Model\\ValueObject\\Identity\\',
271+
$pathGenerator->namespacePrefix('Domain\\Model\\ValueObject\\Identity\\'),
255272
ucfirst($identityType),
256273
);
257274

@@ -296,7 +313,7 @@ private function generateIdentity(
296313

297314
$mappingTypeClassNameDetails = $generator->createClassNameDetails(
298315
$modelName.ucfirst($identityType),
299-
'Infrastructure\\Doctrine\\DBAL\\Type\\',
316+
$pathGenerator->namespacePrefix('Infrastructure\\Doctrine\\DBAL\\Type\\'),
300317
'Type',
301318
);
302319

@@ -360,12 +377,14 @@ private function generateIdentity(
360377
* @param InputInterface $input
361378
* @param ConsoleStyle $io
362379
* @param Generator $generator
380+
* @param PathGenerator $pathGenerator
363381
*/
364382
private function generateEntityMappings(
365383
ClassNameDetails $modelClassNameDetails,
366384
InputInterface $input,
367385
ConsoleStyle $io,
368-
Generator $generator
386+
Generator $generator,
387+
PathGenerator $pathGenerator
369388
): void {
370389
if (!$this->shouldGenerateEntity($input)) {
371390
return;
@@ -378,7 +397,7 @@ private function generateEntityMappings(
378397
$newYaml = $this->doctrineUpdater->updateORMDefaultEntityMapping(
379398
$this->fileManager->getFileContents(DOCTRINE_CONFIG_PATH),
380399
'attribute',
381-
'%kernel.project_dir%/src/Domain/Model',
400+
$pathGenerator->path('%kernel.project_dir%/src', 'Domain/Model'),
382401
);
383402
$generator->dumpFile(DOCTRINE_CONFIG_PATH, $newYaml);
384403
$this->classesToImport[] = ['Doctrine\\ORM\\Mapping' => 'ORM'];
@@ -403,7 +422,7 @@ private function generateEntityMappings(
403422
$this->templateVariables['as_entity'] = false;
404423

405424
try {
406-
$mappingsDirectory = '/src/Infrastructure/Doctrine/ORM/Mapping';
425+
$mappingsDirectory = $pathGenerator->path('/src' , 'Infrastructure/Doctrine/ORM/Mapping');
407426
$newYaml = $this->doctrineUpdater->updateORMDefaultEntityMapping(
408427
$this->fileManager->getFileContents(DOCTRINE_CONFIG_PATH),
409428
'xml',
@@ -417,6 +436,7 @@ private function generateEntityMappings(
417436
$mappingsDirectory,
418437
$modelName
419438
);
439+
420440
$generator->generateFile(
421441
$targetPath,
422442
__DIR__.'/../Resources/skeleton/doctrine/Mapping.tpl.xml.php',
@@ -443,6 +463,7 @@ private function generateEntityMappings(
443463
* @param ClassNameDetails $modelClassNameDetails
444464
* @param InputInterface $input
445465
* @param Generator $generator
466+
* @throws \Exception
446467
*/
447468
private function generateEntity(
448469
ClassNameDetails $modelClassNameDetails,
@@ -474,16 +495,18 @@ private function generateEntity(
474495
* @param InputInterface $input
475496
* @param ClassNameDetails $modelClassNameDetails
476497
* @param ?ClassNameDetails $identityClassNameDetails
498+
* @throws \Exception
477499
*/
478500
private function generateRepository(
479501
Generator $generator,
480502
InputInterface $input,
503+
PathGenerator $pathGenerator,
481504
ClassNameDetails $modelClassNameDetails,
482505
?ClassNameDetails $identityClassNameDetails,
483506
): void {
484507
$interfaceNameDetails = $generator->createClassNameDetails(
485508
$input->getArgument('name'),
486-
'Domain\\Repository\\',
509+
$pathGenerator->namespacePrefix('Domain\\Repository\\'),
487510
'Repository',
488511
);
489512

@@ -496,7 +519,7 @@ private function generateRepository(
496519

497520
$implementationNameDetails = $generator->createClassNameDetails(
498521
$input->getArgument('name'),
499-
'Infrastructure\\Doctrine\\ORM\\Repository\\',
522+
$pathGenerator->namespacePrefix('Infrastructure\\Doctrine\\ORM\\Repository\\'),
500523
'Repository',
501524
);
502525

src/Maker/PathGenerator.php

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
namespace GeekCell\DddBundle\Maker;
4+
5+
use function Symfony\Component\String\u;
6+
7+
class PathGenerator
8+
{
9+
private string $basePath;
10+
11+
public const DEFAULT_BASE_PATH = 'src/';
12+
13+
public function __construct(string $basePath)
14+
{
15+
if ($basePath && !u($basePath)->endsWith('/')) {
16+
$basePath .= '/';
17+
}
18+
19+
$this->basePath = u($basePath)->trimPrefix(self::DEFAULT_BASE_PATH);
20+
}
21+
22+
public function namespacePrefix(string $namespacePrefix): string
23+
{
24+
if ($this->basePath) {
25+
return $this->toNamespace($this->basePath) . $namespacePrefix;
26+
}
27+
28+
return $namespacePrefix;
29+
}
30+
31+
public function path(string $prefix, string $suffix): string
32+
{
33+
$prefix = u($prefix)->trimSuffix('/');
34+
$suffix = u($suffix)->trimPrefix('/');
35+
36+
if ($this->basePath) {
37+
return $prefix . '/' . $this->basePath . $suffix;
38+
}
39+
40+
return $prefix . '/' . $suffix;
41+
}
42+
43+
private function toNamespace(string $basePath): string
44+
{
45+
return u($basePath)->replace('/', '\\');
46+
}
47+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php
2+
3+
namespace GeekCell\DddBundle\Tests\Unit\Maker;
4+
5+
use GeekCell\DddBundle\Maker\PathGenerator;
6+
use PHPUnit\Framework\TestCase;
7+
8+
class PathGeneratorTest extends TestCase
9+
{
10+
/**
11+
* @dataProvider provideNamespacePrefixData
12+
*/
13+
public function testNamespacePrefix(string $basePath, string $namespacePrefix, string $expected)
14+
{
15+
$pathGenerator = new PathGenerator($basePath);
16+
17+
$this->assertEquals($expected, $pathGenerator->namespacePrefix($namespacePrefix));
18+
}
19+
20+
/**
21+
* @return array<string, string, string>
22+
*/
23+
public function provideNamespacePrefixData(): array
24+
{
25+
return [
26+
['', 'Domain\\Model\\', 'Domain\\Model\\'],
27+
['src', 'Domain\\Model\\', 'Domain\\Model\\'],
28+
['src/', 'Domain\\Model\\', 'Domain\\Model\\'],
29+
['src/Foo', 'Domain\\Model\\', 'Foo\\Domain\\Model\\'],
30+
['src/Foo/Bar', 'Domain\\Model\\', 'Foo\\Bar\\Domain\\Model\\'],
31+
];
32+
}
33+
34+
/**
35+
* @dataProvider providePathData
36+
*/
37+
public function testPath(string $basePath, string $prefix, string $suffix, string $expected)
38+
{
39+
$pathGenerator = new PathGenerator($basePath);
40+
41+
$this->assertEquals($expected, $pathGenerator->path($prefix, $suffix));
42+
}
43+
44+
/**
45+
* @return array<string, string, string, string>
46+
*/
47+
public function providePathData(): array
48+
{
49+
return [
50+
['', '%kernel.project_dir%/src', 'Domain/Model', '%kernel.project_dir%/src/Domain/Model'],
51+
['', '%kernel.project_dir%/src/', 'Domain/Model', '%kernel.project_dir%/src/Domain/Model'],
52+
['', '%kernel.project_dir%/src/', '/Domain/Model', '%kernel.project_dir%/src/Domain/Model'],
53+
['src', '%kernel.project_dir%/src', 'Domain/Model', '%kernel.project_dir%/src/Domain/Model'],
54+
['src/', '%kernel.project_dir%/src', 'Domain/Model', '%kernel.project_dir%/src/Domain/Model'],
55+
['src/Foo', '%kernel.project_dir%/src', 'Domain/Model', '%kernel.project_dir%/src/Foo/Domain/Model'],
56+
['src/Foo/Bar', '%kernel.project_dir%/src', 'Domain/Model', '%kernel.project_dir%/src/Foo/Bar/Domain/Model'],
57+
['', '/src', 'Infrastructure/Doctrine/ORM/Mapping', '/src/Infrastructure/Doctrine/ORM/Mapping'],
58+
['src/', '/src', 'Infrastructure/Doctrine/ORM/Mapping', '/src/Infrastructure/Doctrine/ORM/Mapping'],
59+
['src/Foo', '/src', 'Infrastructure/Doctrine/ORM/Mapping', '/src/Foo/Infrastructure/Doctrine/ORM/Mapping'],
60+
];
61+
}
62+
}

0 commit comments

Comments
 (0)