From 08731211515ff0a24b7da72c336224ee6c91bc39 Mon Sep 17 00:00:00 2001 From: Austen McDonald Date: Mon, 25 Jul 2016 21:31:40 +0000 Subject: [PATCH] Change bootstrap to look for metadata directories from modules. --- src/Bootstrap.php | 54 ++++++++++++++++--------- tests/AdditionalEntities/UserEntity.php | 34 ---------------- tests/BootstrapTest.php | 51 +++++++++++++++-------- tests/FakeModule/Module.php | 10 +++++ 4 files changed, 79 insertions(+), 70 deletions(-) delete mode 100644 tests/AdditionalEntities/UserEntity.php create mode 100644 tests/FakeModule/Module.php diff --git a/src/Bootstrap.php b/src/Bootstrap.php index c1be36b..dfb4576 100644 --- a/src/Bootstrap.php +++ b/src/Bootstrap.php @@ -8,23 +8,14 @@ use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Mapping\AnsiQuoteStrategy; use Doctrine\ORM\Tools\Setup; use Doctrine\ORM\Tools\SchemaTool; +use Monolog\Logger; +use Monolog\Handler\RotatingFileHandler; use LotGD\Core\Exceptions\ArgumentException; use LotGD\Core\Exceptions\InvalidConfigurationException; class Bootstrap { - private static $annotationMetaDataDirectories = []; - - public static function registerAnnotationMetaDataDirectory(string $directory) - { - if (is_dir($directory) === false) { - throw new ArgumentException("{$directory} needs to be a valdid directory"); - } - - self::$annotationMetaDataDirectories[] = $directory; - } - /** * Create a new Game object, with all the necessary configuration. * @throws InvalidConfigurationException @@ -38,21 +29,16 @@ class Bootstrap } $config = new Configuration($configFilePath); - $logger = new \Monolog\Logger('lotgd'); + $logger = new Logger('lotgd'); // Add lotgd as the prefix for the log filenames. - $logger->pushHandler(new \Monolog\Handler\RotatingFileHandler($config->getLogPath() . DIRECTORY_SEPARATOR . 'lotgd', 14)); + $logger->pushHandler(new RotatingFileHandler($config->getLogPath() . DIRECTORY_SEPARATOR . 'lotgd', 14)); $v = Game::getVersion(); $logger->info("Bootstrap constructing game (Daenerys 🐲{$v})."); $pdo = new \PDO($config->getDatabaseDSN(), $config->getDatabaseUser(), $config->getDatabasePassword()); - // Read db annotations from model files - $annotationMetaDataDirectories = array_merge( - [__DIR__ . '/Models'], - self::$annotationMetaDataDirectories - ); - $configuration = Setup::createAnnotationMetadataConfiguration($annotationMetaDataDirectories, true); + $configuration = Setup::createAnnotationMetadataConfiguration(Bootstrap::generateAnnotationDirectories($logger, new ComposerManager($logger)), true); // Set a quote $configuration->setQuoteStrategy(new AnsiQuoteStrategy()); @@ -68,4 +54,34 @@ class Bootstrap return new Game($config, $entityManager, $eventManager, $logger); } + + public static function generateAnnotationDirectories(Logger $logger, ComposerManager $manager): array + { + // Read db annotations from our own model files. + $directories = [__DIR__ . '/Models']; + + // Find other annotation directories from installed modules. + $modulePackages = $manager->getModulePackages(); + foreach ($modulePackages as $p) { + $name = $p->getName(); + $extra = $p->getExtra(); + if (!empty($extra['lotgd-namespace'])) { + $n = $extra['lotgd-namespace']; + + // Find the directory for this namespace by using the autoloader + // to find the required Module class. + $autoloader = require(ComposerManager::findAutoloader()); + $path = $autoloader->findFile($n . 'Module'); + if ($path === false) { + $logger->error("Module {$name} lacks a {$n}Module class."); + continue; + } + + $directories[] = dirname($path); + } else { + $logger->error("Module {$name} lacks a 'lotgd-namespace' entry in its composer 'extra' field. Its database models will not be properly loaded."); + } + } + return $directories; + } } diff --git a/tests/AdditionalEntities/UserEntity.php b/tests/AdditionalEntities/UserEntity.php deleted file mode 100644 index 272cc9b..0000000 --- a/tests/AdditionalEntities/UserEntity.php +++ /dev/null @@ -1,34 +0,0 @@ -id; - } - - public function getName(): string - { - return $this->name; - } - - public function setName(string $name) - { - $this->name = $name; - } -} diff --git a/tests/BootstrapTest.php b/tests/BootstrapTest.php index c8cc1ff..3b0d356 100644 --- a/tests/BootstrapTest.php +++ b/tests/BootstrapTest.php @@ -3,11 +3,25 @@ declare(strict_types=1); namespace LotGD\Core\Tests; +use Composer\Package\PackageInterface; + +use Monolog\Logger; +use Monolog\Handler\NullHandler; + use LotGD\Core\Bootstrap; -use LotGD\Core\Tests\AdditionalEntities\UserEntity; +use LotGD\Core\ComposerManager; +use LotGD\Core\Tests\FakeModule\UserEntity; class BootstrapTest extends \PHPUnit_Framework_TestCase { + private $logger; + + public function setUp() + { + $this->logger = new Logger('test'); + $this->logger->pushHandler(new NullHandler()); + } + public function testGame() { $g = Bootstrap::createGame(); @@ -16,26 +30,29 @@ class BootstrapTest extends \PHPUnit_Framework_TestCase $this->assertNotNull($g->getLogger()); } - public function testDoctrineReadsAnnotationsFromAdditionalMetaDataDirectory() + public function testGenerateAnnotationDirectories() { - Bootstrap::registerAnnotationMetaDataDirectory(__DIR__ . "/AdditionalEntities"); + $composerManager = $this->getMockBuilder(ComposerManager::class) + ->disableOriginalConstructor() + ->getMock(); - $g = Bootstrap::createGame(); + $package = $this->getMockForAbstractClass(PackageInterface::class); + $package->method('getExtra')->willReturn(array( + 'lotgd-namespace' => 'LotGD\\Core\\Tests\\FakeModule\\', + )); - $user = new UserEntity(); - $user->setName("Monthy"); + $composerManager->method('getModulePackages')->willReturn(array($package)); - $g->getEntityManager()->persist($user); - $g->getEntityManager()->flush(); + $result = Bootstrap::generateAnnotationDirectories($this->logger, $composerManager); + $expected = __DIR__ . DIRECTORY_SEPARATOR . 'FakeModule'; - $id = $user->getId(); - $this->assertInternalType("int", $id); - - $g->getEntityManager()->clear(); - $user = $g->getEntityManager()->getRepository(UserEntity::class)->find($id); - - $this->assertInternalType("int", $user->getId()); - $this->assertInternalType("string", $user->getName()); - $this->assertSame("Monthy", $user->getName()); + $string = implode(', ', $result); + $found = false; + foreach ($result as $r) { + if (realpath($r) == $expected) { + $found = true; + } + } + $this->assertTrue($found, "Annotation directories [{$string}] does not contain {$expected}."); } } diff --git a/tests/FakeModule/Module.php b/tests/FakeModule/Module.php new file mode 100644 index 0000000..f08446c --- /dev/null +++ b/tests/FakeModule/Module.php @@ -0,0 +1,10 @@ +