mirror of
https://github.com/OpenXE-org/OpenXE.git
synced 2024-12-27 07:00:29 +01:00
237 lines
6.1 KiB
PHP
237 lines
6.1 KiB
PHP
|
<?php
|
||
|
|
||
|
namespace Xentral\Core\Installer;
|
||
|
|
||
|
use RecursiveDirectoryIterator;
|
||
|
use RecursiveIteratorIterator;
|
||
|
use RegexIterator;
|
||
|
use RuntimeException;
|
||
|
use Xentral\Components\SchemaCreator\Collection\SchemaCollection;
|
||
|
|
||
|
final class Installer
|
||
|
{
|
||
|
/** @var ClassMapGenerator $classMapGenerator */
|
||
|
private $classMapGenerator;
|
||
|
|
||
|
/** @var Psr4ClassNameResolver $classNameResolver */
|
||
|
private $classNameResolver;
|
||
|
|
||
|
/** @var array $classMap */
|
||
|
private $classMap = [];
|
||
|
|
||
|
/** @var array $bootstrapClasses */
|
||
|
private $bootstrapClasses = [];
|
||
|
|
||
|
/** @var array */
|
||
|
private $services = [];
|
||
|
|
||
|
/** @var array $javascript */
|
||
|
private $javascript = [];
|
||
|
|
||
|
/** @var string $classDir */
|
||
|
private $classDir;
|
||
|
|
||
|
/**
|
||
|
* @param ClassMapGenerator $generator
|
||
|
*/
|
||
|
public function __construct(ClassMapGenerator $generator, Psr4ClassNameResolver $resolver)
|
||
|
{
|
||
|
$this->classMapGenerator = $generator;
|
||
|
$this->classNameResolver = $resolver;
|
||
|
$this->classDir = dirname(dirname(__DIR__));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return array
|
||
|
*/
|
||
|
public function getClassMap()
|
||
|
{
|
||
|
if (!empty($this->classMap)) {
|
||
|
return $this->classMap;
|
||
|
}
|
||
|
|
||
|
$this->classMap = $this->classMapGenerator->generate($this->classDir);
|
||
|
|
||
|
return $this->classMap;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return array
|
||
|
*/
|
||
|
public function getServices()
|
||
|
{
|
||
|
if (!empty($this->services)) {
|
||
|
return $this->services;
|
||
|
}
|
||
|
|
||
|
$classNames = $this->getBootstrapClassNames();
|
||
|
|
||
|
foreach ($classNames as $className) {
|
||
|
if (empty($className)) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (!class_exists($className, true)) {
|
||
|
$this->loadClass($className);
|
||
|
}
|
||
|
if (!method_exists($className, 'registerServices')) {
|
||
|
continue;
|
||
|
}
|
||
|
$services = forward_static_call([$className, 'registerServices']);
|
||
|
foreach ($services as $serviceName => $factoryMethod) {
|
||
|
$this->addServiceDefinition($serviceName, $className, $factoryMethod);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $this->services;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @throws RuntimeException
|
||
|
*
|
||
|
* @return SchemaCollection
|
||
|
*/
|
||
|
public function getTableSchemas(): SchemaCollection
|
||
|
{
|
||
|
$schemaCollection = new SchemaCollection();
|
||
|
$classNames = $this->getBootstrapClassNames();
|
||
|
|
||
|
foreach ($classNames as $className) {
|
||
|
if (empty($className)) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (!class_exists($className, true)) {
|
||
|
$this->loadClass($className);
|
||
|
}
|
||
|
if (!method_exists($className, 'registerTableSchemas')) {
|
||
|
continue;
|
||
|
}
|
||
|
forward_static_call([$className, 'registerTableSchemas'], $schemaCollection);
|
||
|
}
|
||
|
|
||
|
return $schemaCollection;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return array
|
||
|
*/
|
||
|
public function getJavascriptFiles()
|
||
|
{
|
||
|
$classNames = $this->getBootstrapClassNames();
|
||
|
|
||
|
foreach ($classNames as $className) {
|
||
|
if (!class_exists($className, true)) {
|
||
|
continue;
|
||
|
}
|
||
|
if (!method_exists($className, 'registerJavascript')) {
|
||
|
continue;
|
||
|
}
|
||
|
$javascript = forward_static_call([$className, 'registerJavascript']);
|
||
|
foreach ($javascript as $cacheName => $jsFiles) {
|
||
|
$this->addJavascriptDefinition($cacheName, $jsFiles);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $this->javascript;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return array Absolute paths to all bootstrap files
|
||
|
*/
|
||
|
private function getBootstrapFiles()
|
||
|
{
|
||
|
$directory = new RecursiveDirectoryIterator($this->classDir);
|
||
|
$iterator = new RecursiveIteratorIterator($directory);
|
||
|
$bootstraps = new RegexIterator($iterator, '/^.+Bootstrap\.php$/', RegexIterator::MATCH);
|
||
|
|
||
|
$files = [];
|
||
|
|
||
|
/** @var \SplFileInfo $bootstrap */
|
||
|
foreach ($bootstraps as $bootstrap) {
|
||
|
$files[] = $bootstrap->getRealPath();
|
||
|
}
|
||
|
|
||
|
return $files;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return array FQCN of all bootstrap classes
|
||
|
*/
|
||
|
private function getBootstrapClassNames()
|
||
|
{
|
||
|
if (!empty($this->bootstrapClasses)) {
|
||
|
return $this->bootstrapClasses;
|
||
|
}
|
||
|
|
||
|
$files = $this->getBootstrapFiles();
|
||
|
foreach ($files as $file) {
|
||
|
$className = $this->classNameResolver->resolveClassName($file);
|
||
|
if ($className === null) {
|
||
|
continue;
|
||
|
}
|
||
|
$this->bootstrapClasses[] = $className;
|
||
|
}
|
||
|
|
||
|
return $this->bootstrapClasses;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param string $serviceName
|
||
|
* @param string $bootstrapClass
|
||
|
* @param string $factoryMethod
|
||
|
*
|
||
|
* @return void
|
||
|
*/
|
||
|
private function addServiceDefinition($serviceName, $bootstrapClass, $factoryMethod)
|
||
|
{
|
||
|
if (isset($this->services[$serviceName])) {
|
||
|
$registeredCallString = $this->services[$serviceName][0] . '::' . $this->services[$serviceName][1];
|
||
|
$failedCallString = $bootstrapClass . '::' . $factoryMethod;
|
||
|
throw new RuntimeException(sprintf(
|
||
|
'Service "%s" can not be registered. Name is already taken. Registered "%s" - Failed "%s"',
|
||
|
$serviceName, $registeredCallString, $failedCallString
|
||
|
));
|
||
|
}
|
||
|
|
||
|
$this->services[$serviceName] = [$bootstrapClass, $factoryMethod];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param $cacheName
|
||
|
* @param $files
|
||
|
*
|
||
|
* @return void
|
||
|
*/
|
||
|
private function addJavascriptDefinition($cacheName, $files)
|
||
|
{
|
||
|
$this->javascript[$cacheName] = $files;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param string $className
|
||
|
*
|
||
|
* @throws RuntimeException
|
||
|
*
|
||
|
* @return void
|
||
|
*/
|
||
|
private function loadClass($className)
|
||
|
{
|
||
|
if (empty($className)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (empty($this->classMap)) {
|
||
|
$this->getClassMap();
|
||
|
}
|
||
|
|
||
|
if (!isset($this->classMap[$className])) {
|
||
|
throw new RuntimeException(sprintf(
|
||
|
'Could not load class "%s"', $className
|
||
|
));
|
||
|
}
|
||
|
|
||
|
include $this->classMap[$className];
|
||
|
}
|
||
|
}
|