Skip to content

Commit

Permalink
Merge branch '3.next' into 3.next-plugins
Browse files Browse the repository at this point in the history
  • Loading branch information
markstory committed Feb 19, 2018
2 parents d4a4887 + 131255a commit 1e59a8d
Show file tree
Hide file tree
Showing 9 changed files with 354 additions and 90 deletions.
44 changes: 39 additions & 5 deletions src/Console/CommandRunner.php
Expand Up @@ -23,6 +23,7 @@
use Cake\Console\Shell;
use Cake\Core\ConsoleApplicationInterface;
use Cake\Core\PluginApplicationInterface;
use Cake\Event\EventApplicationInterface;
use Cake\Event\EventDispatcherInterface;
use Cake\Event\EventDispatcherTrait;
use Cake\Utility\Inflector;
Expand Down Expand Up @@ -64,7 +65,7 @@ class CommandRunner implements EventDispatcherInterface
*/
public function __construct(ConsoleApplicationInterface $app, $root = 'cake')
{
$this->app = $app;
$this->setApp($app);
$this->root = $root;
$this->aliases = [
'--version' => 'version',
Expand Down Expand Up @@ -96,6 +97,23 @@ public function setAliases(array $aliases)
return $this;
}

/**
* Set the application.
*
* @param \Cake\Core\ConsoleApplicationInterface $app The application to run CLI commands for.
* @return $this
*/
public function setApp(ConsoleApplicationInterface $app)
{
$this->app = $app;

if ($app instanceof EventDispatcherInterface) {
$this->setEventManager($app->getEventManager());
}

return $this;
}

/**
* Run the command contained in $argv.
*
Expand All @@ -113,10 +131,7 @@ public function setAliases(array $aliases)
*/
public function run(array $argv, ConsoleIo $io = null)
{
$this->app->bootstrap();
if ($this->app instanceof PluginApplicationInterface) {
$this->app->pluginBootstrap();
}
$this->bootstrap();

$commands = new CommandCollection([
'version' => VersionCommand::class,
Expand Down Expand Up @@ -164,6 +179,25 @@ public function run(array $argv, ConsoleIo $io = null)
return Shell::CODE_ERROR;
}

/**
* Application bootstrap wrapper.
*
* Calls `bootstrap()` and `events()` if application implements `EventApplicationInterface`.
*
* @return void
*/
protected function bootstrap()
{
$this->app->bootstrap();
if ($this->app instanceof EventApplicationInterface) {
$eventManager = $this->app->events($this->getEventManager());
$this->setEventManager($eventManager);
}
if ($this->app instanceof PluginApplicationInterface) {
$this->app->pluginBootstrap();
}
}

/**
* Get the shell instance for a given command name
*
Expand Down
26 changes: 26 additions & 0 deletions src/Event/EventApplicationInterface.php
@@ -0,0 +1,26 @@
<?php
/**
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since 3.6.0
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\Event;

interface EventApplicationInterface
{

/**
* Application hook for attaching events to the Application event manager instance.
*
* @param \Cake\Event\EventManagerInterface $eventManager Event manager instance.
* @return \Cake\Event\EventManagerInterface
*/
public function events(EventManagerInterface $eventManager);
}
81 changes: 5 additions & 76 deletions src/Event/EventManager.php
Expand Up @@ -22,7 +22,7 @@
* can create multiple instances of this object to manage local events or keep a single instance
* and pass it around to manage all events in your app.
*/
class EventManager
class EventManager implements EventManagerInterface
{

/**
Expand Down Expand Up @@ -129,42 +129,7 @@ public function attach($callable, $eventKey = null, array $options = [])
}

/**
* Adds a new listener to an event.
*
* A variadic interface to add listeners that emulates jQuery.on().
*
* Binding an EventListenerInterface:
*
* ```
* $eventManager->on($listener);
* ```
*
* Binding with no options:
*
* ```
* $eventManager->on('Model.beforeSave', $callable);
* ```
*
* Binding with options:
*
* ```
* $eventManager->on('Model.beforeSave', ['priority' => 90], $callable);
* ```
*
* @param string|\Cake\Event\EventListenerInterface|null $eventKey The event unique identifier name
* with which the callback will be associated. If $eventKey is an instance of
* Cake\Event\EventListenerInterface its events will be bound using the `implementedEvents` methods.
*
* @param array|callable $options Either an array of options or the callable you wish to
* bind to $eventKey. If an array of options, the `priority` key can be used to define the order.
* Priorities are treated as queues. Lower values are called before higher ones, and multiple attachments
* added to the same priority queue will be treated in the order of insertion.
*
* @param callable|null $callable The callable function you want invoked.
*
* @return $this
* @throws \InvalidArgumentException When event key is missing or callable is not an
* instance of Cake\Event\EventListenerInterface.
* {@inheritDoc}
*/
public function on($eventKey = null, $options = [], $callable = null)
{
Expand Down Expand Up @@ -263,36 +228,7 @@ public function detach($callable, $eventKey = null)
}

/**
* Remove a listener from the active listeners.
*
* Remove a EventListenerInterface entirely:
*
* ```
* $manager->off($listener);
* ```
*
* Remove all listeners for a given event:
*
* ```
* $manager->off('My.event');
* ```
*
* Remove a specific listener:
*
* ```
* $manager->off('My.event', $callback);
* ```
*
* Remove a callback from all events:
*
* ```
* $manager->off($callback);
* ```
*
* @param string|\Cake\Event\EventListenerInterface $eventKey The event unique identifier name
* with which the callback has been associated, or the $listener you want to remove.
* @param callable|null $callable The callback you want to detach.
* @return $this
* {@inheritDoc}
*/
public function off($eventKey, $callable = null)
{
Expand Down Expand Up @@ -365,11 +301,7 @@ protected function _detachSubscriber(EventListenerInterface $subscriber, $eventK
}

/**
* Dispatches a new event to all configured listeners
*
* @param string|\Cake\Event\Event $event the event key name or instance of Event
* @return \Cake\Event\Event
* @triggers $event
* {@inheritDoc}
*/
public function dispatch($event)
{
Expand Down Expand Up @@ -422,10 +354,7 @@ protected function _callListener(callable $listener, Event $event)
}

/**
* Returns a list of all listeners for an eventKey in the order they should be called
*
* @param string $eventKey Event key.
* @return array
* {@inheritDoc}
*/
public function listeners($eventKey)
{
Expand Down
109 changes: 109 additions & 0 deletions src/Event/EventManagerInterface.php
@@ -0,0 +1,109 @@
<?php
/**
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since 3.6.0
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\Event;

interface EventManagerInterface
{

/**
* Adds a new listener to an event.
*
* A variadic interface to add listeners that emulates jQuery.on().
*
* Binding an EventListenerInterface:
*
* ```
* $eventManager->on($listener);
* ```
*
* Binding with no options:
*
* ```
* $eventManager->on('Model.beforeSave', $callable);
* ```
*
* Binding with options:
*
* ```
* $eventManager->on('Model.beforeSave', ['priority' => 90], $callable);
* ```
*
* @param string|\Cake\Event\EventListenerInterface|null $eventKey The event unique identifier name
* with which the callback will be associated. If $eventKey is an instance of
* Cake\Event\EventListenerInterface its events will be bound using the `implementedEvents` methods.
*
* @param array|callable $options Either an array of options or the callable you wish to
* bind to $eventKey. If an array of options, the `priority` key can be used to define the order.
* Priorities are treated as queues. Lower values are called before higher ones, and multiple attachments
* added to the same priority queue will be treated in the order of insertion.
*
* @param callable|null $callable The callable function you want invoked.
*
* @return $this
* @throws \InvalidArgumentException When event key is missing or callable is not an
* instance of Cake\Event\EventListenerInterface.
*/
public function on($eventKey = null, $options = [], $callable = null);

/**
* Remove a listener from the active listeners.
*
* Remove a EventListenerInterface entirely:
*
* ```
* $manager->off($listener);
* ```
*
* Remove all listeners for a given event:
*
* ```
* $manager->off('My.event');
* ```
*
* Remove a specific listener:
*
* ```
* $manager->off('My.event', $callback);
* ```
*
* Remove a callback from all events:
*
* ```
* $manager->off($callback);
* ```
*
* @param string|\Cake\Event\EventListenerInterface $eventKey The event unique identifier name
* with which the callback has been associated, or the $listener you want to remove.
* @param callable|null $callable The callback you want to detach.
* @return $this
*/
public function off($eventKey, $callable = null);

/**
* Dispatches a new event to all configured listeners
*
* @param string|\Cake\Event\EventInterface $event The event key name or instance of EventInterface.
* @return \Cake\Event\EventInterface
* @triggers $event
*/
public function dispatch($event);

/**
* Returns a list of all listeners for an eventKey in the order they should be called
*
* @param string $eventKey Event key.
* @return array
*/
public function listeners($eventKey);
}
23 changes: 21 additions & 2 deletions src/Http/BaseApplication.php
Expand Up @@ -19,6 +19,11 @@
use Cake\Core\Plugin;
use Cake\Core\PluginApplicationInterface;
use Cake\Core\PluginInterface;
use Cake\Event\EventApplicationInterface;
use Cake\Event\EventDispatcherInterface;
use Cake\Event\EventDispatcherTrait;
use Cake\Event\EventManager;
use Cake\Event\EventManagerInterface;
use Cake\Routing\DispatcherFactory;
use Cake\Routing\Router;
use InvalidArgumentException;
Expand All @@ -34,10 +39,14 @@
*/
abstract class BaseApplication implements
ConsoleApplicationInterface,
EventApplicationInterface,
EventDispatcherInterface,
HttpApplicationInterface,
PluginApplicationInterface
{

use EventDispatcherTrait;

/**
* @var string Contains the path of the config directory
*/
Expand All @@ -54,11 +63,13 @@ abstract class BaseApplication implements
* Constructor
*
* @param string $configDir The directory the bootstrap configuration is held in.
* @param \Cake\Event\EventManagerInterface $eventManager Application event manager instance.
*/
public function __construct($configDir)
public function __construct($configDir, EventManagerInterface $eventManager = null)
{
$this->configDir = $configDir;
$this->plugins = Plugin::getCollection();
$this->_eventManager = $eventManager ?: EventManager::instance();
}

/**
Expand Down Expand Up @@ -197,6 +208,14 @@ public function pluginConsole($commands)
return $commands;
}

/**
* {@inheritDoc}
*/
public function events(EventManagerInterface $eventManager)
{
return $eventManager;
}

/**
* Invoke the application.
*
Expand All @@ -221,6 +240,6 @@ public function __invoke(ServerRequestInterface $request, ResponseInterface $res
*/
protected function getDispatcher()
{
return new ActionDispatcher(null, null, DispatcherFactory::filters());
return new ActionDispatcher(null, $this->getEventManager(), DispatcherFactory::filters());
}
}

0 comments on commit 1e59a8d

Please sign in to comment.