From dbd9f31ff6e1913d92a23b0b3174b649ef3ba48c Mon Sep 17 00:00:00 2001 From: eater Date: Wed, 17 Jan 2018 12:51:33 +0100 Subject: [PATCH] Initial commit --- .gitignore | 2 + composer.json | 21 ++++ composer.lock | 241 +++++++++++++++++++++++++++++++++++++++++++++ config/default.php | 8 ++ src/Instance.php | 209 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 481 insertions(+) create mode 100644 .gitignore create mode 100644 composer.json create mode 100644 composer.lock create mode 100644 config/default.php create mode 100644 src/Instance.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0dca145 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/vendor/ +.idea diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..838d1fb --- /dev/null +++ b/composer.json @@ -0,0 +1,21 @@ +{ + "name": "bitcommunism/marx", + "description": "The engine", + "version": "1.0.2", + "type": "library", + "require": { + "php-di/php-di": "^5.4" + }, + "autoload": { + "psr-4": { + "BitCommunism\\Marx\\": "src/" + } + }, + "license": "Propietary", + "authors": [ + { + "name": "eater", + "email": "eater@bitcommunism.net" + } + ] +} \ No newline at end of file diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..7facaa2 --- /dev/null +++ b/composer.lock @@ -0,0 +1,241 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "content-hash": "e94413d031d3c517aa5122f0946cf2d3", + "packages": [ + { + "name": "container-interop/container-interop", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/container-interop/container-interop.git", + "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8", + "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8", + "shasum": "" + }, + "require": { + "psr/container": "^1.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Interop\\Container\\": "src/Interop/Container/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Promoting the interoperability of container objects (DIC, SL, etc.)", + "homepage": "https://github.com/container-interop/container-interop", + "time": "2017-02-14T19:40:03+00:00" + }, + { + "name": "php-di/invoker", + "version": "1.3.3", + "source": { + "type": "git", + "url": "https://github.com/PHP-DI/Invoker.git", + "reference": "1f4ca63b9abc66109e53b255e465d0ddb5c2e3f7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHP-DI/Invoker/zipball/1f4ca63b9abc66109e53b255e465d0ddb5c2e3f7", + "reference": "1f4ca63b9abc66109e53b255e465d0ddb5c2e3f7", + "shasum": "" + }, + "require": { + "container-interop/container-interop": "~1.1" + }, + "require-dev": { + "athletic/athletic": "~0.1.8", + "phpunit/phpunit": "~4.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Invoker\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Generic and extensible callable invoker", + "homepage": "https://github.com/PHP-DI/Invoker", + "keywords": [ + "callable", + "dependency", + "dependency-injection", + "injection", + "invoke", + "invoker" + ], + "time": "2016-07-14T13:09:58+00:00" + }, + { + "name": "php-di/php-di", + "version": "5.4.6", + "source": { + "type": "git", + "url": "https://github.com/PHP-DI/PHP-DI.git", + "reference": "3f9255659595f3e289f473778bb6c51aa72abbbd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHP-DI/PHP-DI/zipball/3f9255659595f3e289f473778bb6c51aa72abbbd", + "reference": "3f9255659595f3e289f473778bb6c51aa72abbbd", + "shasum": "" + }, + "require": { + "container-interop/container-interop": "~1.2", + "php": ">=5.5.0", + "php-di/invoker": "^1.3.2", + "php-di/phpdoc-reader": "^2.0.1", + "psr/container": "~1.0" + }, + "provide": { + "container-interop/container-interop-implementation": "^1.0", + "psr/container-implementation": "^1.0" + }, + "replace": { + "mnapoli/php-di": "*" + }, + "require-dev": { + "doctrine/annotations": "~1.2", + "doctrine/cache": "~1.4", + "mnapoli/phpunit-easymock": "~0.2.0", + "ocramius/proxy-manager": "~1.0|~2.0", + "phpbench/phpbench": "@dev", + "phpunit/phpunit": "~4.5" + }, + "suggest": { + "doctrine/annotations": "Install it if you want to use annotations (version ~1.2)", + "doctrine/cache": "Install it if you want to use the cache (version ~1.4)", + "ocramius/proxy-manager": "Install it if you want to use lazy injection (version ~1.0 or ~2.0)" + }, + "type": "library", + "autoload": { + "psr-4": { + "DI\\": "src/DI/" + }, + "files": [ + "src/DI/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "The dependency injection container for humans", + "homepage": "http://php-di.org/", + "keywords": [ + "container", + "dependency injection", + "di" + ], + "time": "2017-12-03T08:20:27+00:00" + }, + { + "name": "php-di/phpdoc-reader", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/PHP-DI/PhpDocReader.git", + "reference": "83f5ead159defccfa8e7092e5b6c1c533b326d68" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHP-DI/PhpDocReader/zipball/83f5ead159defccfa8e7092e5b6c1c533b326d68", + "reference": "83f5ead159defccfa8e7092e5b6c1c533b326d68", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.6" + }, + "type": "library", + "autoload": { + "psr-4": { + "PhpDocReader\\": "src/PhpDocReader" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PhpDocReader parses @var and @param values in PHP docblocks (supports namespaced class names with the same resolution rules as PHP)", + "keywords": [ + "phpdoc", + "reflection" + ], + "time": "2015-11-29T10:34:25+00:00" + }, + { + "name": "psr/container", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "time": "2017-02-14T16:28:37+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [] +} diff --git a/config/default.php b/config/default.php new file mode 100644 index 0000000..5eb8282 --- /dev/null +++ b/config/default.php @@ -0,0 +1,8 @@ + [], + 'marx.loadsers' => [], +]; \ No newline at end of file diff --git a/src/Instance.php b/src/Instance.php new file mode 100644 index 0000000..55bb99b --- /dev/null +++ b/src/Instance.php @@ -0,0 +1,209 @@ + 'doctrine', + 'cli' => 'cli', + 'http' => 'http', + ]; + + public static function create($directory, $environment = 'development'): Instance + { + $instance = new Instance(realpath($directory), $environment); + $instance->load(); + + return $instance; + } + + public function __construct($directory, $environment = 'development') + { + $this->directory = $directory; + $this->environment = $environment; + } + + public function load() + { + $container = $this->buildTemporaryContainer(); + $this->buildContainer($container->get('modules')); + + $this->registerCalls(); + $this->runLoaders(); + } + + protected function registerCalls() { + $calls = $this->container->get('marx.calls'); + + foreach ($calls as $name => $call) { + $this->register($name, function (...$arguments) use ($call) { + return $this->container->call($call, [ + 'arguments' => $arguments + ]); + }); + } + } + + protected function runLoaders() { + $loaders = $this->container->get('marx.loaders'); + + foreach ($loaders as $loader) { + $this->container->call($loader); + } + } + + protected function loadModules($modules, ContainerBuilder $builder) { + $directories = []; + + $loadedModules = []; + + foreach ($modules as $module) { + if (strpos($module, '/') === false) { + $module = 'bitcommunism/' . $module; + } + + $directory = $this->directory; + $modulePath = $directory . '/vendor/' . $module; + + if (!is_dir($modulePath)) { + $stderr = fopen('php://stderr', 'w+'); + fwrite($stderr, "Warning: Module '{$module}' doesn't exist, did you install it? e.g.:\n\n\tcomposer require {$module}\n\n"); + // fclose($stderr); + } + + $directories[] = $modulePath; + $loadedModules[$module] = true; + } + + $builder->addDefinitions($loadedModules); + + $this->loadDefinitions($builder, $directories); + } + + public function register($name, $callback) { + $this->calls[$name] = $callback; + } + + public function __call($name, $arguments) + { + if (!isset($this->calls[$name])) { + if (isset($this->knownCalls[$name])) { + throw new \Exception("No call {$name} found, did you install and enable the {$this->knownCalls[$name]} module?"); + } + + throw new \Exception("No call {$name} found. are you missing a module?"); + } + + return $this->calls[$name](...$arguments); + } + + + private function buildTemporaryContainer() { + $builder = new ContainerBuilder(); + + $builder->addDefinitions([ + 'basedir' => $this->directory, + ]); + + $this->loadDefinitions($builder, [__DIR__ . '/..', $this->directory]); + + return $builder->build(); + } + + private function loadDefinitions(ContainerBuilder $builder, $directories = []) { + $configTypes = ['default', 'routes', $this->environment]; + + foreach ($directories as $directory) { + foreach ($configTypes as $configType) { + $configPath = sprintf(self::CONFIG_PATH, $directory, $configType); + if (!file_exists($configPath)) { + continue; + } + try { + $config = include($configPath); + } catch (\Throwable $e) { + // Failed loading config + + continue; + } + + if ($configType === 'routes') { + // Routes needs to be put in 'routes' + $config = [ + 'routes' => $config, + ]; + } + + if (!is_array($config)) { + continue; + } + + $builder->addDefinitions($config); + } + } + } + + private function buildContainer($modules) + { + $builder = new ContainerBuilder(); + + $builder->addDefinitions([ + 'basedir' => $this->directory, + 'marx.instance' => value($this), + self::class => $this, + ]); + + $this->loadDefinitions($builder, [__DIR__ . '/..']); + $this->loadModules($modules, $builder); + $this->loadDefinitions($builder, [$this->directory]); + + $this->container = $builder->build(); + } +} \ No newline at end of file