Skip to content

Commit 6d4cc3c

Browse files
Merge pull request #12 from dayspring-tech/fix/symfony4_structure
add support for S4+ directory structure
2 parents ff12c8e + 85f90fc commit 6d4cc3c

File tree

10 files changed

+358
-155
lines changed

10 files changed

+358
-155
lines changed

AppBundle.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
namespace Propel\Bundle\PropelBundle;
3+
4+
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
5+
use Symfony\Component\DependencyInjection\ContainerInterface;
6+
use Symfony\Component\HttpKernel\Bundle\Bundle;
7+
8+
/**
9+
* this class is made to simulate bundle containing base structure so we can work with no bundle architecture used from s4+
10+
* Class AppBundle
11+
* @package App
12+
*/
13+
class AppBundle extends Bundle {
14+
const NAME = 'AppBundle';
15+
16+
public function __construct(ContainerInterface $container)
17+
{
18+
$this->setContainer($container);
19+
20+
$this->path = $this->container->get('kernel')->getProjectDir();
21+
}
22+
}

Command/AbstractCommand.php

Lines changed: 71 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use Symfony\Component\HttpKernel\Bundle\Bundle;
2020
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
2121
use Symfony\Component\HttpKernel\KernelInterface;
22+
use Propel\Bundle\PropelBundle\Service\SchemaLocator;
2223

2324
/**
2425
* Wrapper for Propel commands.
@@ -67,6 +68,12 @@ abstract class AbstractCommand extends Command
6768
*/
6869
protected $input;
6970

71+
/**
72+
*
73+
* @var OutputInterface
74+
*/
75+
protected $output;
76+
7077
private ContainerInterface $container;
7178

7279
public function __construct(ContainerInterface $container, $name = null)
@@ -140,6 +147,7 @@ protected function initialize(InputInterface $input, OutputInterface $output)
140147
}
141148

142149
$this->input = $input;
150+
$this->output = $output;
143151

144152
$this->checkConfiguration();
145153

@@ -241,24 +249,19 @@ protected function copySchemas(KernelInterface $kernel, $cacheDir)
241249
{
242250
$filesystem = new Filesystem();
243251

244-
if (!is_dir($cacheDir)) {
245-
$filesystem->mkdir($cacheDir);
246-
}
247-
248252
$base = ltrim(realpath($kernel->getProjectDir()), DIRECTORY_SEPARATOR);
249253

254+
/** @var array<string, array{?BundleInterface, \SplFileInfo}> $finalSchemas */
250255
$finalSchemas = $this->getFinalSchemas($kernel, $this->bundle);
251256
foreach ($finalSchemas as $schema) {
252257
list($bundle, $finalSchema) = $schema;
253258

254-
$tempSchema = $bundle->getName().'-'.$finalSchema->getBaseName();
255-
$this->tempSchemas[$tempSchema] = array(
256-
'bundle' => $bundle->getName(),
257-
'basename' => $finalSchema->getBaseName(),
258-
'path' => $finalSchema->getPathname(),
259-
);
259+
if ($bundle) {
260+
$file = $cacheDir.DIRECTORY_SEPARATOR.'bundle-'.$bundle->getName().'-'.$finalSchema->getBaseName();
261+
} else {
262+
$file = $cacheDir.DIRECTORY_SEPARATOR.'app-'.$finalSchema->getBaseName();
263+
}
260264

261-
$file = $cacheDir.DIRECTORY_SEPARATOR.$tempSchema;
262265
$filesystem->copy((string) $finalSchema, $file, true);
263266

264267
// the package needs to be set absolute
@@ -269,31 +272,47 @@ protected function copySchemas(KernelInterface $kernel, $cacheDir)
269272
if (isset($database['package'])) {
270273
// Do not use the prefix!
271274
// This is used to override the package resulting from namespace conversion.
272-
$package = $database['package'];
275+
$database['package'] = $database['package'];
273276
} elseif (isset($database['namespace'])) {
274-
$package = $this->getPackage($bundle, $database['namespace'], $base);
277+
if ($bundle) {
278+
$database['package'] = $this->getPackage($bundle, (string)$database['namespace'], $base);
279+
} else {
280+
$database['package'] = $this->getPackageFromApp((string)$database['namespace']);
281+
}
275282
} else {
276283
throw new \RuntimeException(
277-
sprintf('%s : Please define a `package` attribute or a `namespace` attribute for schema `%s`',
278-
$bundle->getName(), $finalSchema->getBaseName())
284+
sprintf(
285+
'%s : Please define a `package` attribute or a `namespace` attribute for schema `%s`',
286+
$bundle ? $bundle->getName() : 'App',
287+
$finalSchema->getBaseName()
288+
)
279289
);
280290
}
281291

282-
$database['package'] = $package;
283-
284292
if ($this->input && $this->input->hasOption('connection') && $this->input->getOption('connection')
285293
&& $database['name'] != $this->input->getOption('connection')) {
286-
//we skip this schema because the connection name doesn't match the input value
287-
unset($this->tempSchemas[$tempSchema]);
294+
// we skip this schema because the connection name doesn't match the input values
288295
$filesystem->remove($file);
296+
$this->output->writeln(sprintf(
297+
'<info>Skipped schema %s due to database name missmatch (%s not in [%s]).</info>',
298+
$finalSchema->getPathname(),
299+
$database['name'],
300+
$this->input->getOption('connection')
301+
));
289302
continue;
290303
}
291304

292305
foreach ($database->table as $table) {
293306
if (isset($table['package'])) {
294307
$table['package'] = $table['package'];
295-
} else {
296-
$table['package'] = $package;
308+
} elseif (isset($table['namespace'])) {
309+
if ($bundle) {
310+
$table['package'] = $this->getPackage($bundle, (string)$table['namespace']);
311+
} else {
312+
$table['package'] = $this->getPackageFromApp((string)$table['namespace']);
313+
}
314+
} elseif (isset($database['package'])) {
315+
$table['package'] = $database['package'];
297316
}
298317
}
299318

@@ -311,41 +330,10 @@ protected function copySchemas(KernelInterface $kernel, $cacheDir)
311330
protected function getFinalSchemas(KernelInterface $kernel, BundleInterface $bundle = null)
312331
{
313332
if (null !== $bundle) {
314-
return $this->getSchemasFromBundle($bundle);
315-
}
316-
317-
$finalSchemas = array();
318-
foreach ($kernel->getBundles() as $bundle) {
319-
$finalSchemas = array_merge($finalSchemas, $this->getSchemasFromBundle($bundle));
320-
}
321-
322-
return $finalSchemas;
323-
}
324-
325-
/**
326-
* @param \Symfony\Component\HttpKernel\Bundle\BundleInterface $bundle
327-
*
328-
* @return array
329-
*/
330-
protected function getSchemasFromBundle(BundleInterface $bundle)
331-
{
332-
$finalSchemas = array();
333-
334-
if (is_dir($dir = $bundle->getPath().'/Resources/config')) {
335-
$finder = new Finder();
336-
$schemas = $finder->files()->name('*schema.xml')->followLinks()->in($dir);
337-
338-
if (iterator_count($schemas)) {
339-
foreach ($schemas as $schema) {
340-
$logicalName = $this->transformToLogicalName($schema, $bundle);
341-
$finalSchema = new \SplFileInfo($this->getFileLocator()->locate($logicalName));
342-
343-
$finalSchemas[(string) $finalSchema] = array($bundle, $finalSchema);
344-
}
345-
}
333+
return $this->getSchemaLocator()->locateFromBundle($bundle);
346334
}
347335

348-
return $finalSchemas;
336+
return $this->getSchemaLocator()->locateFromBundlesAndConfiguration($kernel->getBundles());
349337
}
350338

351339
/**
@@ -471,6 +459,24 @@ protected function getProperties($file)
471459
return $properties;
472460
}
473461

462+
/**
463+
* @param string $namespace
464+
*
465+
* @return string
466+
*/
467+
protected function getPackageFromApp(string $namespace): string
468+
{
469+
if ('\\' === $namespace[0]) {
470+
$namespace = substr($namespace, 1);
471+
}
472+
473+
if (0 === stripos($namespace, 'App\\')) {
474+
$namespace = substr($namespace, 4);
475+
}
476+
477+
return 'src.'.str_replace('\\', '.', $namespace);
478+
}
479+
474480
/**
475481
* Return the current Propel cache directory.
476482
* @return string The current Propel cache directory.
@@ -488,6 +494,17 @@ protected function getFileLocator()
488494
return $this->getContainer()->get('propel.file_locator');
489495
}
490496

497+
/**
498+
* @return SchemaLocator
499+
*/
500+
protected function getSchemaLocator(): SchemaLocator
501+
{
502+
/** @var SchemaLocator $obj */
503+
$obj = $this->getContainer()->get('propel.schema_locator');
504+
505+
return $obj;
506+
}
507+
491508
/**
492509
* Get connection by checking the input option named 'connection'.
493510
* Returns the default connection if no option specified or an exception

Command/FormGenerateCommand.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@ protected function configure()
5353
*/
5454
protected function execute(InputInterface $input, OutputInterface $output)
5555
{
56-
if ($schemas = $this->getSchemasFromBundle($this->bundle)) {
57-
$schemas = $this->getFinalSchemas($this->getContainer()->get('kernel'));
56+
$schemas = $this->getFinalSchemas($this->getContainer()->get('kernel'), $this->bundle);
5857

58+
if (0 < count($schemas)) {
5959
$transformer = new \XmlToAppData(null, null, 'UTF-8');
6060
foreach ($schemas as $fileName => $array) {
6161
foreach ($this->getDatabasesFromSchema($array[1], $transformer) as $database) {

Resources/config/propel.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
<parameters>
88
<parameter key="propel.dbal.default_connection">default</parameter>
99
<parameter key="propel.configuration.class">PropelConfiguration</parameter>
10+
<parameter key="propel.schema_locator.class">Propel\Bundle\PropelBundle\Service\SchemaLocator</parameter>
1011
<parameter key="propel.logger.class">Propel\Bundle\PropelBundle\Logger\PropelLogger</parameter>
1112
<parameter key="propel.data_collector.class">Propel\Bundle\PropelBundle\DataCollector\PropelDataCollector</parameter>
1213
<parameter key="propel.build_properties.class">Propel\Bundle\PropelBundle\DependencyInjection\Properties</parameter>
@@ -21,6 +22,11 @@
2122

2223
<service id="propel.build_properties" class="%propel.build_properties.class%" public="true" />
2324

25+
<service id="propel.schema_locator" class="%propel.schema_locator.class%" public="true">
26+
<argument type="service" id="service_container" />
27+
<argument type="service" id="file_locator" />
28+
</service>
29+
2430
<service id="propel.logger" class="%propel.logger.class%" public="true">
2531
<tag name="monolog.logger" channel="propel" />
2632
<argument type="service" id="logger" on-invalid="null" />

Service/SchemaLocator.php

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
<?php
2+
3+
/**
4+
* This file is part of the PropelBundle package.
5+
* For the full copyright and license information, please view the LICENSE
6+
* file that was distributed with this source code.
7+
*
8+
* @license MIT License
9+
*/
10+
11+
namespace Propel\Bundle\PropelBundle\Service;
12+
13+
use Propel\Bundle\PropelBundle\AppBundle;
14+
use Symfony\Component\Config\FileLocatorInterface;
15+
use Symfony\Component\DependencyInjection\ContainerInterface;
16+
use Symfony\Component\Finder\Finder;
17+
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
18+
19+
class SchemaLocator
20+
{
21+
protected ContainerInterface $container;
22+
protected FileLocatorInterface $fileLocator;
23+
24+
/**
25+
* @param ContainerInterface $container
26+
* @param FileLocatorInterface $fileLocator
27+
*/
28+
public function __construct(ContainerInterface $container, FileLocatorInterface $fileLocator)
29+
{
30+
$this->container = $container;
31+
$this->fileLocator = $fileLocator;
32+
}
33+
34+
/**
35+
* @param array<string, BundleInterface> $bundles
36+
*
37+
* @return array<string, array{?BundleInterface, \SplFileInfo}>
38+
*/
39+
public function locateFromBundlesAndConfiguration(array $bundles): array
40+
{
41+
$finalSchemas = $this->locateFromBundles($bundles);
42+
43+
// search project config directory per symfony 4.0+ directory structure
44+
$finder = new Finder();
45+
$dir = $this->container->get('kernel')->getProjectDir().'/config';
46+
$schemas = $finder->files()->name('*schema.xml')->followLinks()->in($dir);
47+
if (iterator_count($schemas)) {
48+
foreach ($schemas as $schema) {
49+
$finalSchemas[(string) $schema] = array(null, $schema);
50+
}
51+
}
52+
53+
return $finalSchemas;
54+
}
55+
56+
/**
57+
* @param array<string, BundleInterface> $bundles
58+
*
59+
* @return array<string, array{BundleInterface, \SplFileInfo}>
60+
*/
61+
public function locateFromBundles(array $bundles): array
62+
{
63+
$schemas = array();
64+
foreach ($bundles as $bundle) {
65+
$schemas = array_merge($schemas, $this->locateFromBundle($bundle));
66+
}
67+
68+
return $schemas;
69+
}
70+
71+
/**
72+
* @param BundleInterface $bundle
73+
*
74+
* @return array<string, array{BundleInterface, \SplFileInfo}>
75+
*/
76+
public function locateFromBundle(BundleInterface $bundle): array
77+
{
78+
// no bundle/bundle
79+
$dir = ($bundle->getName() === AppBundle::NAME)? $bundle->getPath().'/config' : $bundle->getPath().'/Resources/config';
80+
81+
$finalSchemas = array();
82+
83+
if (is_dir($dir)) {
84+
$finder = new Finder();
85+
$schemas = $finder->files()->name('*schema.xml')->followLinks()->in($dir);
86+
87+
if (iterator_count($schemas)) {
88+
foreach ($schemas as $schema) {
89+
$logicalName = $this->transformToLogicalName($schema, $bundle);
90+
91+
$finalSchema = new \SplFileInfo($this->fileLocator->locate($logicalName));
92+
93+
$finalSchemas[(string) $finalSchema] = array($bundle, $finalSchema);
94+
}
95+
}
96+
}
97+
98+
return $finalSchemas;
99+
}
100+
101+
/**
102+
* @param \SplFileInfo $schema
103+
* @param BundleInterface $bundle
104+
* @return string
105+
*/
106+
protected function transformToLogicalName(\SplFileInfo $schema, BundleInterface $bundle)
107+
{
108+
// NOTE: for future research - i dont see why this function exists call of ->getRealPath() should do the job
109+
110+
$schemaPath = str_replace(
111+
// no bundle/bundle
112+
$bundle->getPath(). DIRECTORY_SEPARATOR . ($bundle->getName() == AppBundle::NAME ? '' : 'Resources' . DIRECTORY_SEPARATOR) . 'config' . DIRECTORY_SEPARATOR,
113+
'',
114+
$schema->getRealPath()
115+
);
116+
117+
//
118+
if ($bundle->getName() == AppBundle::NAME) {
119+
return sprintf('%s/config/%s', $bundle->getPath(), $schemaPath);
120+
}
121+
122+
return sprintf('@%s/Resources/config/%s', $bundle->getName(), $schemaPath);
123+
}
124+
}

0 commit comments

Comments
 (0)