Change bootstrap to look for metadata directories from modules.

This commit is contained in:
Austen McDonald
2016-07-25 21:31:40 +00:00
parent f5bea45317
commit 0873121151
4 changed files with 79 additions and 70 deletions
+35 -19
View File
@@ -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;
}
}
-34
View File
@@ -1,34 +0,0 @@
<?php
declare(strict_types=1);
namespace LotGD\Core\Tests\AdditionalEntities;
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\Table;
/**
* @Entity
* @Table(name="Users")
*/
class UserEntity
{
/** @Id @Column(type="integer") @GeneratedValue */
private $id;
/** @Column(type="string", length=50); */
private $name;
public function getId(): int
{
return $this->id;
}
public function getName(): string
{
return $this->name;
}
public function setName(string $name)
{
$this->name = $name;
}
}
+34 -17
View File
@@ -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}.");
}
}
+10
View File
@@ -0,0 +1,10 @@
<?php
namespace LotGD\Core\Tests\FakeModule;
use LotGD\Core\Module;
class FakeModule extends Module {
public static function onRegister(Game $g) {}
public static function onUnregister(Game $g) {}
}