From a85c2638e48f9d4d4da83ab57895c9fad456cf30 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Tue, 19 Aug 2014 18:45:42 +0300 Subject: [PATCH] Fix #17: Use Symfony EventDispatcher --- composer.json | 1 + index.php | 2 +- system/src/Grav/Common/Grav.php | 59 ++++++++----------- system/src/Grav/Common/Page/Page.php | 25 ++++---- system/src/Grav/Common/Page/Pages.php | 21 +++---- system/src/Grav/Common/Plugin.php | 55 ++++++++++++++++- system/src/Grav/Common/Plugins.php | 16 ++++- system/src/Grav/Common/Theme.php | 2 +- system/src/Grav/Common/Themes.php | 9 +-- .../Component/ArrayTraits/ArrayAccess.php | 46 +++++++++++++++ .../Component/ArrayTraits/Constructor.php | 21 +++++++ .../Grav/Component/ArrayTraits/Countable.php | 19 ++++++ .../Grav/Component/ArrayTraits/Getters.php | 50 ++++++++++++++++ .../Grav/Component/EventDispatcher/Event.php | 15 +++++ .../EventDispatcher/EventDispatcher.php | 16 +++++ .../EventSubscriberInterface.php | 6 ++ 16 files changed, 297 insertions(+), 66 deletions(-) create mode 100644 system/src/Grav/Component/ArrayTraits/ArrayAccess.php create mode 100644 system/src/Grav/Component/ArrayTraits/Constructor.php create mode 100644 system/src/Grav/Component/ArrayTraits/Countable.php create mode 100644 system/src/Grav/Component/ArrayTraits/Getters.php create mode 100644 system/src/Grav/Component/EventDispatcher/Event.php create mode 100644 system/src/Grav/Component/EventDispatcher/EventDispatcher.php create mode 100644 system/src/Grav/Component/EventDispatcher/EventSubscriberInterface.php diff --git a/composer.json b/composer.json index 3e9f78461..5b2913006 100644 --- a/composer.json +++ b/composer.json @@ -17,6 +17,7 @@ "erusev/parsedown-extra": "dev-master", "symfony/yaml": "2.5.*@dev", "symfony/console": "2.5.*@dev", + "symfony/event-dispatcher": "2.5.*@dev", "doctrine/cache": "1.4.*@dev", "tracy/tracy": "dev-master", "gregwar/image": "dev-master", diff --git a/index.php b/index.php index 3d4857ce3..861749219 100644 --- a/index.php +++ b/index.php @@ -30,7 +30,7 @@ try { $grav->process(); } catch (\Exception $e) { - $grav->fireEvent('onFatalException', $e); + $grav->fireEvent('onFatalException'); throw $e; } diff --git a/system/src/Grav/Common/Grav.php b/system/src/Grav/Common/Grav.php index 2f9c30fe8..6ac395e81 100644 --- a/system/src/Grav/Common/Grav.php +++ b/system/src/Grav/Common/Grav.php @@ -2,6 +2,8 @@ namespace Grav\Common; use Grav\Component\DI\Container; +use Grav\Component\EventDispatcher\Event; +use Grav\Component\EventDispatcher\EventDispatcher; /** * Grav @@ -51,6 +53,9 @@ class Grav extends Container $container['grav'] = $container; + $container['events'] = function ($c) { + return new EventDispatcher; + }; $container['uri'] = function ($c) { return new Uri($c); }; @@ -79,7 +84,18 @@ class Grav extends Container return new Assets(); }; $container['page'] = function ($c) { - return $c['pages']->dispatch($c['uri']->route()); + $page = $c['pages']->dispatch($c['uri']->route()); + + if (!$page || !$page->routable()) { + $event = $c->fireEvent('onPageNotFound'); + + if (isset($event->page)) { + $page = $event->page; + } else { + throw new \RuntimeException('Page Not Found', 404); + } + } + return $page; }; $container['output'] = function ($c) { return $c['twig']->processSite($c['uri']->extension()); @@ -108,11 +124,6 @@ class Grav extends Container $this->fireEvent('onAfterGetPage'); - // If there's no page, throw exception - if (!$this['page']) { - throw new \RuntimeException('Page Not Found', 404); - } - // Process whole page as required $this->output = $this['output']; @@ -172,34 +183,16 @@ class Grav extends Container } /** - * Processes any hooks and runs them. + * Fires an event with optional parameters. + * + * @param string $eventName + * @param Event $event + * @return Event */ - public function fireEvent() + public function fireEvent($eventName, Event $event = null) { - $args = func_get_args(); - $hook_id = array_shift($args); - $no_timing_hooks = array('onAfterPageProcessed','onAfterFolderProcessed', 'onAfterCollectionProcessed'); - - /** @var Plugins $plugins */ - $plugins = $this['plugins']; - - if (!empty($plugins)) { - foreach ($plugins as $plugin) { - if (is_callable(array($plugin, $hook_id))) { - call_user_func_array(array($plugin, $hook_id), $args); - } - } - } - - /** @var Config $config */ - $config = $this['config']; - - if ($config && $config->get('system.debugger.log.timing') && !in_array($hook_id, $no_timing_hooks)) { - /** @var Debugger $debugger */ - $debugger = isset($this['debugger']) ? $this['debugger'] : null; - if ($debugger) { - $debugger->log($hook_id.': %f ms'); - } - } + /** @var EventDispatcher $events */ + $events = $this['events']; + return $events->dispatch($eventName, $event); } } diff --git a/system/src/Grav/Common/Page/Page.php b/system/src/Grav/Common/Page/Page.php index 9685bdd46..dfced9a75 100644 --- a/system/src/Grav/Common/Page/Page.php +++ b/system/src/Grav/Common/Page/Page.php @@ -1,18 +1,19 @@ fireEvent('onAfterCollectionProcessed', $collection); + $grav->fireEvent('onAfterCollectionProcessed', new Event(['collection' => $collection])); $params = $collection->params(); diff --git a/system/src/Grav/Common/Page/Pages.php b/system/src/Grav/Common/Page/Pages.php index a3e29e23f..f853b97ff 100644 --- a/system/src/Grav/Common/Page/Pages.php +++ b/system/src/Grav/Common/Page/Pages.php @@ -1,13 +1,14 @@ initialized) { - $this->grav->fireEvent('onCreateBlueprint', $blueprint); + $this->grav->fireEvent('onCreateBlueprint', new Event(['blueprint' => $blueprint])); $blueprint->initialized = true; } @@ -420,7 +421,7 @@ class Pages $page->init($file); if ($config->get('system.pages.events.page')) { - $this->grav->fireEvent('onAfterPageProcessed', $page); + $this->grav->fireEvent('onAfterPageProcessed', new Event(['page' => $page])); } } elseif ($file->isDir() && !$file->isDot()) { @@ -447,7 +448,7 @@ class Pages $this->lastModified($file->getMTime()); if ($config->get('system.pages.events.page')) { - $this->grav->fireEvent('onAfterFolderProcessed', $page); + $this->grav->fireEvent('onAfterFolderProcessed', new Event(['page' => $page])); } } } diff --git a/system/src/Grav/Common/Plugin.php b/system/src/Grav/Common/Plugin.php index fb25dccdb..0371cd41a 100644 --- a/system/src/Grav/Common/Plugin.php +++ b/system/src/Grav/Common/Plugin.php @@ -1,26 +1,75 @@ grav = $grav; $this->config = $config; } + + /** + * @param array $events + */ + protected function enable(array $events) + { + /** @var EventDispatcher $dispatcher */ + $dispatcher = $this->grav['events']; + + foreach ($events as $eventName => $params) { + if (is_string($params)) { + $dispatcher->addListener($eventName, array($this, $params)); + } elseif (is_string($params[0])) { + $dispatcher->addListener($eventName, array($this, $params[0]), isset($params[1]) ? $params[1] : 0); + } else { + foreach ($params as $listener) { + $dispatcher->addListener($eventName, array($this, $listener[0]), isset($listener[1]) ? $listener[1] : 0); + } + } + } + } } diff --git a/system/src/Grav/Common/Plugins.php b/system/src/Grav/Common/Plugins.php index cf44693b4..11ce58435 100644 --- a/system/src/Grav/Common/Plugins.php +++ b/system/src/Grav/Common/Plugins.php @@ -2,6 +2,8 @@ namespace Grav\Common; use Grav\Common\Filesystem\File; +use Grav\Component\EventDispatcher\EventDispatcher; +use Grav\Component\EventDispatcher\EventSubscriberInterface; /** * The Plugins object holds an array of all the plugin objects that @@ -30,7 +32,9 @@ class Plugins extends Iterator $config = $this->grav['config']; $plugins = (array) $config->get('plugins'); - $instances = ['theme' => $this->grav['themes']->load()]; + /** @var EventDispatcher $events */ + $events = $this->grav['events']; + foreach ($plugins as $plugin => $data) { if (empty($data['enabled'])) { // Only load enabled plugins. @@ -51,7 +55,15 @@ class Plugins extends Iterator throw new \RuntimeException(sprintf("Plugin '%s' class not found!", $plugin)); } - $this->add(new $pluginClass($config)); + $instance = new $pluginClass($this->grav, $config); + if ($instance instanceof EventSubscriberInterface) { + $events->addSubscriber($instance); + } + } + + $instance = $this->grav['themes']->load(); + if ($instance instanceof EventSubscriberInterface) { + $events->addSubscriber($instance); } return $this->items; diff --git a/system/src/Grav/Common/Theme.php b/system/src/Grav/Common/Theme.php index 31e5cf477..0b3e17017 100644 --- a/system/src/Grav/Common/Theme.php +++ b/system/src/Grav/Common/Theme.php @@ -1,6 +1,6 @@ grav['config']; + if (!$name) { - /** @var Config $config */ - $config = $this->grav['config']; $name = $config->get('system.pages.theme'); } @@ -100,13 +101,13 @@ class Themes $className = '\\Grav\\Theme\\' . ucfirst($name); if (class_exists($className)) { - $class = new $className; + $class = new $className($this->grav, $config); } } } if (empty($class)) { - $class = new Theme; + $class = new Theme($this->grav, $config); } return $class; diff --git a/system/src/Grav/Component/ArrayTraits/ArrayAccess.php b/system/src/Grav/Component/ArrayTraits/ArrayAccess.php new file mode 100644 index 000000000..aacd1c01f --- /dev/null +++ b/system/src/Grav/Component/ArrayTraits/ArrayAccess.php @@ -0,0 +1,46 @@ +items[$offset]); + } + + /** + * @param mixed $offset + * @return mixed + */ + public function offsetGet($offset) + { + return isset($this->items[$offset]) ? $this->items[$offset] : null; + } + + /** + * @param mixed $offset + * @param mixed $value + */ + public function offsetSet($offset, $value) + { + $this->items[$offset] = $value; + } + + /** + * @param mixed $offset + */ + public function offsetUnset($offset) + { + unset($this->items[$offset]); + } +} diff --git a/system/src/Grav/Component/ArrayTraits/Constructor.php b/system/src/Grav/Component/ArrayTraits/Constructor.php new file mode 100644 index 000000000..80779c2fc --- /dev/null +++ b/system/src/Grav/Component/ArrayTraits/Constructor.php @@ -0,0 +1,21 @@ +items = $items; + } +} diff --git a/system/src/Grav/Component/ArrayTraits/Countable.php b/system/src/Grav/Component/ArrayTraits/Countable.php new file mode 100644 index 000000000..10e51410c --- /dev/null +++ b/system/src/Grav/Component/ArrayTraits/Countable.php @@ -0,0 +1,19 @@ +items); + } +} diff --git a/system/src/Grav/Component/ArrayTraits/Getters.php b/system/src/Grav/Component/ArrayTraits/Getters.php new file mode 100644 index 000000000..90da77a24 --- /dev/null +++ b/system/src/Grav/Component/ArrayTraits/Getters.php @@ -0,0 +1,50 @@ +offsetSet($offset, $value); + } + + /** + * Magic getter method + * + * @param mixed $offset Asset name value + * @return mixed Asset value + */ + public function __get($offset) + { + return $this->offsetGet($offset); + } + + /** + * Magic method to determine if the attribute is set + * + * @param mixed $offset Asset name value + * @return boolean True if the value is set + */ + public function __isset($offset) + { + return $this->offsetExists($offset); + } + + /** + * Magic method to unset the attribute + * + * @param mixed $offset The name value to unset + */ + public function __unset($offset) + { + $this->offsetUnset($offset); + } +} diff --git a/system/src/Grav/Component/EventDispatcher/Event.php b/system/src/Grav/Component/EventDispatcher/Event.php new file mode 100644 index 000000000..ba2ad9075 --- /dev/null +++ b/system/src/Grav/Component/EventDispatcher/Event.php @@ -0,0 +1,15 @@ +