• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tito10047 / type-safe-id-bundle / 23182491396

17 Mar 2026 07:03AM UTC coverage: 86.0% (+7.4%) from 78.621%
23182491396

push

github

tito10047
change multiple servises to one global

115 of 120 new or added lines in 3 files covered. (95.83%)

1 existing line in 1 file now uncovered.

172 of 200 relevant lines covered (86.0%)

27.75 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.06
/src/Maker/MakeTypeSafeEntity.php
1
<?php
2

3
namespace Tito10047\TypeSafeIdBundle\Maker;
4

5
use Symfony\Bundle\MakerBundle\ConsoleStyle;
6
use Symfony\Bundle\MakerBundle\DependencyBuilder;
7
use Symfony\Bundle\MakerBundle\Generator;
8
use Symfony\Bundle\MakerBundle\InputConfiguration;
9
use Symfony\Bundle\MakerBundle\Maker\AbstractMaker;
10
use Symfony\Bundle\MakerBundle\Maker\Common\EntityIdTypeEnum;
11
use Symfony\Bundle\MakerBundle\Util\UseStatementGenerator;
12
use Symfony\Component\Console\Command\Command;
13
use Symfony\Component\Console\Input\InputArgument;
14
use Symfony\Component\Console\Input\InputInterface;
15
use Symfony\Component\Console\Input\InputOption;
16
use Symfony\Component\Uid\Ulid;
17
use Symfony\Component\Uid\UuidV7;
18
use Symfony\Bridge\Doctrine\Types\AbstractUidType;
19
use Tito10047\TypeSafeIdBundle\AbstractIntIdType;
20

21
class MakeTypeSafeEntity extends AbstractMaker
22
{
23
    public function __construct(
24
        private readonly string $entityPath,
25
        private readonly string $typeIdPath,
26
        private readonly string $repositoryPath,
27
    ) {
28
    }
36✔
29

30
    public static function getCommandName(): string
31
    {
32
        return 'make:entity:typesafe';
36✔
33
    }
34

35
    public static function getCommandDescription(): string
36
    {
37
        return 'Creates a new Doctrine entity class with type-safe ID';
36✔
38
    }
39

40
    public function configureCommand(Command $command, InputConfiguration $inputConfig)
41
    {
42
        $command
36✔
43
            ->addArgument('name', InputArgument::OPTIONAL, 'The name of the entity class (e.g. <alternate>Foo</alternate>)')
36✔
44
            ->addOption('with-ulid', null, InputOption::VALUE_NONE, 'Use ULID as ID')
36✔
45
            ->addOption('with-uuid', null, InputOption::VALUE_NONE, 'Use UUID as ID')
36✔
46
            ->setHelp(file_get_contents(__DIR__ . '/../../docs/make_entity_typesafe.txt') ?: 'Creates a new Doctrine entity class with type-safe ID')
36✔
47
        ;
36✔
48
    }
49

50
    public function configureDependencies(DependencyBuilder $dependencies)
51
    {
52
        // No extra dependencies needed beyond MakerBundle and Doctrine
53
    }
36✔
54

55
    public function interact(InputInterface $input, ConsoleStyle $io, Command $command)
56
    {
NEW
57
        if (null === $input->getArgument('name')) {
×
NEW
58
            $argument = $command->getDefinition()->getArgument('name');
×
NEW
59
            $input->setArgument('name', $io->ask($argument->getDescription()));
×
60
        }
61
    }
62

63
    public function generate(InputInterface $input, ConsoleStyle $io, Generator $generator)
64
    {
65
        $className = $input->getArgument('name');
36✔
66
        
67
        $idType = EntityIdTypeEnum::INT;
36✔
68
        if ($input->getOption('with-ulid')) {
36✔
69
            $idType = EntityIdTypeEnum::ULID;
12✔
70
        } elseif ($input->getOption('with-uuid')) {
24✔
71
            $idType = EntityIdTypeEnum::UUID;
12✔
72
        }
73

74
        $entityNamespace = $this->pathToNamespace($this->entityPath);
36✔
75
        $typeIdNamespace = $this->pathToNamespace($this->typeIdPath);
36✔
76
        $repositoryNamespace = $this->pathToNamespace($this->repositoryPath);
36✔
77

78
        $entityClassDetails = $generator->createClassNameDetails($className, $entityNamespace);
36✔
79
        $idClassDetails = $generator->createClassNameDetails($className . 'Id', $typeIdNamespace);
36✔
80
        $idTypeClassDetails = $generator->createClassNameDetails($className . 'IdType', $typeIdNamespace);
36✔
81
        $repositoryClassDetails = $generator->createClassNameDetails($className, $repositoryNamespace, 'Repository');
36✔
82

83
        // 1. Generate ID class
84
        $useStatements = new UseStatementGenerator([]);
36✔
85
        if ($idType === EntityIdTypeEnum::UUID) {
36✔
86
            $useStatements->addUseStatement(UuidV7::class);
12✔
87
        } elseif ($idType === EntityIdTypeEnum::ULID) {
24✔
88
            $useStatements->addUseStatement(Ulid::class);
12✔
89
        }
90
        
91
        $generator->generateClass(
36✔
92
            $idClassDetails->getFullName(),
36✔
93
            __DIR__ . '/../../templates/extension/maker/TypeId.tpl.php',
36✔
94
            [
36✔
95
                'id_type' => $idType,
36✔
96
                'use_statements' => $useStatements,
36✔
97
            ]
36✔
98
        );
36✔
99

100
        // 2. Generate ID Type class
101
        $useStatements = new UseStatementGenerator([]);
36✔
102
        $useStatements->addUseStatement($idClassDetails->getFullName());
36✔
103
        if ($idType === EntityIdTypeEnum::UUID || $idType === EntityIdTypeEnum::ULID) {
36✔
104
            $useStatements->addUseStatement(AbstractUidType::class);
24✔
105
        } else {
106
            $useStatements->addUseStatement(AbstractIntIdType::class);
12✔
107
        }
108
        
109
        $generator->generateClass(
36✔
110
            $idTypeClassDetails->getFullName(),
36✔
111
            __DIR__ . '/../../templates/extension/maker/TypeIdType.tpl.php',
36✔
112
            [
36✔
113
                'id_type' => $idType,
36✔
114
                'id_class' => $idClassDetails->getShortName(),
36✔
115
                'use_statements' => $useStatements,
36✔
116
            ]
36✔
117
        );
36✔
118

119
        // 3. Generate Repository
120
        $useStatements = new UseStatementGenerator([]);
36✔
121
        $useStatements->addUseStatement(\Doctrine\ORM\EntityRepository::class); // Fallback or use ServiceEntityRepository
36✔
122
        $useStatements->addUseStatement(\Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository::class);
36✔
123
        $useStatements->addUseStatement(\Doctrine\Persistence\ManagerRegistry::class);
36✔
124
        $useStatements->addUseStatement($entityClassDetails->getFullName());
36✔
125
        $useStatements->addUseStatement($idClassDetails->getFullName());
36✔
126
        $useStatements->addUseStatement(\Doctrine\ORM\QueryBuilder::class);
36✔
127

128
        $generator->generateClass(
36✔
129
            $repositoryClassDetails->getFullName(),
36✔
130
            __DIR__ . '/../../templates/extension/maker/Repository.tpl.php',
36✔
131
            [
36✔
132
                'entity_full_class_name' => $entityClassDetails->getFullName(),
36✔
133
                'entity_class_name' => $entityClassDetails->getShortName(),
36✔
134
                'id_class' => $idClassDetails->getShortName(),
36✔
135
                'id_type' => $idType,
36✔
136
                'use_statements' => $useStatements,
36✔
137
                'include_example_comments' => false,
36✔
138
                'with_password_upgrade' => false,
36✔
139
                'entity_alias' => strtolower($entityClassDetails->getShortName()[0]),
36✔
140
            ]
36✔
141
        );
36✔
142

143
        // 4. Generate Entity
144
        $useStatements = new UseStatementGenerator([]);
36✔
145
        $useStatements->addUseStatement([[\Doctrine\ORM\Mapping::class => 'ORM']]);
36✔
146
        $useStatements->addUseStatement($idClassDetails->getFullName());
36✔
147
        $useStatements->addUseStatement($idTypeClassDetails->getFullName());
36✔
148

149
        $generator->generateClass(
36✔
150
            $entityClassDetails->getFullName(),
36✔
151
            __DIR__ . '/../../templates/extension/maker/Entity.tpl.php',
36✔
152
            [
36✔
153
                'repository_class_name' => $repositoryClassDetails->getShortName(),
36✔
154
                'id_type' => $idType,
36✔
155
                'id_generator_service' => 'doctrine.id_generator.universal',
36✔
156
                'use_statements' => $useStatements,
36✔
157
                'should_escape_table_name' => false,
36✔
158
                'api_resource' => false,
36✔
159
                'broadcast' => false,
36✔
160
                'table_name' => null, // Will be handled by Doctrine naming strategy
36✔
161
            ]
36✔
162
        );
36✔
163

164
        $generator->writeChanges();
36✔
165

166
        $this->writeSuccessMessage($io);
36✔
167
        
168
        $io->text([
36✔
169
            'Next: You can now add fields to your entity using the official make:entity command:',
36✔
170
            sprintf(' <fg=yellow>php bin/console make:entity %s</>', $className),
36✔
171
            '',
36✔
172
        ]);
36✔
173
    }
174

175
    private function pathToNamespace(string $path): string
176
    {
177
        // Simple heuristic: assume src/ is at the root and skip it
178
        $namespace = preg_replace('/^src\//', '', $path);
36✔
179
        $namespace = str_replace('/', '\\', $namespace);
36✔
180
        return trim($namespace, '\\');
36✔
181
    }
182
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc