Move events handling to Symfony\EventDispatcher
This commit is contained in:
@@ -2,9 +2,8 @@
|
||||
|
||||
namespace Action;
|
||||
|
||||
use Event\GenericEvent;
|
||||
use Pimple\Container;
|
||||
use Core\Listener;
|
||||
use Core\Tool;
|
||||
|
||||
/**
|
||||
* Base class for automatic actions
|
||||
@@ -21,8 +20,16 @@ use Core\Tool;
|
||||
* @property \Model\TaskFinder $taskFinder
|
||||
* @property \Model\TaskStatus $taskStatus
|
||||
*/
|
||||
abstract class Base implements Listener
|
||||
abstract class Base
|
||||
{
|
||||
/**
|
||||
* Flag for called listener
|
||||
*
|
||||
* @access private
|
||||
* @var boolean
|
||||
*/
|
||||
private $called = false;
|
||||
|
||||
/**
|
||||
* Project id
|
||||
*
|
||||
@@ -114,6 +121,7 @@ abstract class Base implements Listener
|
||||
$this->container = $container;
|
||||
$this->project_id = $project_id;
|
||||
$this->event_name = $event_name;
|
||||
$this->called = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,7 +144,7 @@ abstract class Base implements Listener
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
return Tool::loadModel($this->container, $name);
|
||||
return $this->container[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -225,12 +233,20 @@ abstract class Base implements Listener
|
||||
* Execute the action
|
||||
*
|
||||
* @access public
|
||||
* @param array $data Event data dictionary
|
||||
* @return bool True if the action was executed or false when not executed
|
||||
* @param \Event\GenericEvent $event Event data dictionary
|
||||
* @return bool True if the action was executed or false when not executed
|
||||
*/
|
||||
public function execute(array $data)
|
||||
public function execute(GenericEvent $event)
|
||||
{
|
||||
// Avoid infinite loop, a listener instance can be called only one time
|
||||
if ($this->called) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$data = $event->getAll();
|
||||
|
||||
if ($this->isExecutable($data)) {
|
||||
$this->called = true;
|
||||
return $this->doAction($data);
|
||||
}
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ class TaskAssignCategoryColor extends Base
|
||||
'category_id' => $this->getParam('category_id'),
|
||||
);
|
||||
|
||||
return $this->taskModification->update($values, false);
|
||||
return $this->taskModification->update($values);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -67,7 +67,7 @@ class TaskAssignCategoryLabel extends Base
|
||||
'category_id' => isset($data['category_id']) ? $data['category_id'] : $this->getParam('category_id'),
|
||||
);
|
||||
|
||||
return $this->taskModification->update($values, false);
|
||||
return $this->taskModification->update($values);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -67,7 +67,7 @@ class TaskAssignColorCategory extends Base
|
||||
'color_id' => $this->getParam('color_id'),
|
||||
);
|
||||
|
||||
return $this->taskModification->update($values, false);
|
||||
return $this->taskModification->update($values);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -68,7 +68,7 @@ class TaskAssignColorUser extends Base
|
||||
'color_id' => $this->getParam('color_id'),
|
||||
);
|
||||
|
||||
return $this->taskModification->update($values, false);
|
||||
return $this->taskModification->update($values);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -62,12 +62,16 @@ class TaskAssignCurrentUser extends Base
|
||||
*/
|
||||
public function doAction(array $data)
|
||||
{
|
||||
if (! $this->acl->isLogged()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$values = array(
|
||||
'id' => $data['task_id'],
|
||||
'owner_id' => $this->acl->getUserId(),
|
||||
);
|
||||
|
||||
return $this->taskModification->update($values, false);
|
||||
return $this->taskModification->update($values);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -68,7 +68,7 @@ class TaskAssignSpecificUser extends Base
|
||||
'owner_id' => $this->getParam('user_id'),
|
||||
);
|
||||
|
||||
return $this->taskModification->update($values, false);
|
||||
return $this->taskModification->update($values);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -64,7 +64,7 @@ class TaskAssignUser extends Base
|
||||
'owner_id' => $data['owner_id'],
|
||||
);
|
||||
|
||||
return $this->taskModification->update($values, false);
|
||||
return $this->taskModification->update($values);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -63,7 +63,7 @@ class TaskCreation extends Base
|
||||
'project_id' => $data['project_id'],
|
||||
'title' => $data['title'],
|
||||
'reference' => $data['reference'],
|
||||
'description' => $data['description'],
|
||||
'description' => isset($data['description']) ? $data['description'] : '',
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace Auth;
|
||||
|
||||
use Core\Tool;
|
||||
use Pimple\Container;
|
||||
|
||||
/**
|
||||
@@ -54,6 +53,6 @@ abstract class Base
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
return Tool::loadModel($this->container, $name);
|
||||
return $this->container[$name];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace Console;
|
||||
|
||||
use Core\Tool;
|
||||
use Pimple\Container;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
|
||||
@@ -52,6 +51,6 @@ abstract class Base extends Command
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
return Tool::loadModel($this->container, $name);
|
||||
return $this->container[$name];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
namespace Controller;
|
||||
|
||||
use Pimple\Container;
|
||||
use Core\Tool;
|
||||
use Core\Security;
|
||||
use Core\Request;
|
||||
use Core\Response;
|
||||
@@ -129,7 +128,7 @@ abstract class Base
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
return Tool::loadModel($this->container, $name);
|
||||
return $this->container[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -156,9 +155,6 @@ abstract class Base
|
||||
$this->response->hsts();
|
||||
}
|
||||
|
||||
$this->config->setupTranslations();
|
||||
$this->config->setupTimezone();
|
||||
|
||||
// Authentication
|
||||
if (! $this->authentication->isAuthenticated($controller, $action)) {
|
||||
|
||||
@@ -173,30 +169,6 @@ abstract class Base
|
||||
if (! $this->acl->isPageAccessAllowed($controller, $action)) {
|
||||
$this->response->redirect('?controller=user&action=forbidden');
|
||||
}
|
||||
|
||||
// Attach events
|
||||
$this->attachEvents();
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach events
|
||||
*
|
||||
* @access private
|
||||
*/
|
||||
private function attachEvents()
|
||||
{
|
||||
$models = array(
|
||||
'projectActivity', // Order is important
|
||||
'projectDailySummary',
|
||||
'action',
|
||||
'project',
|
||||
'webhook',
|
||||
'notification',
|
||||
);
|
||||
|
||||
foreach ($models as $model) {
|
||||
$this->$model->attachEvents();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,175 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Core;
|
||||
|
||||
/**
|
||||
* Event dispatcher class
|
||||
*
|
||||
* @package core
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Event
|
||||
{
|
||||
/**
|
||||
* Contains all listeners
|
||||
*
|
||||
* @access private
|
||||
* @var array
|
||||
*/
|
||||
private $listeners = array();
|
||||
|
||||
/**
|
||||
* The last listener executed
|
||||
*
|
||||
* @access private
|
||||
* @var string
|
||||
*/
|
||||
private $lastListener = '';
|
||||
|
||||
/**
|
||||
* The last triggered event
|
||||
*
|
||||
* @access private
|
||||
* @var string
|
||||
*/
|
||||
private $lastEvent = '';
|
||||
|
||||
/**
|
||||
* Triggered events list
|
||||
*
|
||||
* @access private
|
||||
* @var array
|
||||
*/
|
||||
private $events = array();
|
||||
|
||||
/**
|
||||
* Attach a listener object to an event
|
||||
*
|
||||
* @access public
|
||||
* @param string $eventName Event name
|
||||
* @param Listener $listener Object that implements the Listener interface
|
||||
*/
|
||||
public function attach($eventName, Listener $listener)
|
||||
{
|
||||
if (! isset($this->listeners[$eventName])) {
|
||||
$this->listeners[$eventName] = array();
|
||||
}
|
||||
|
||||
$this->listeners[$eventName][] = $listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger an event
|
||||
*
|
||||
* @access public
|
||||
* @param string $eventName Event name
|
||||
* @param array $data Event data
|
||||
*/
|
||||
public function trigger($eventName, array $data)
|
||||
{
|
||||
if (! $this->isEventTriggered($eventName)) {
|
||||
|
||||
$this->events[$eventName] = $data;
|
||||
|
||||
if (isset($this->listeners[$eventName])) {
|
||||
|
||||
foreach ($this->listeners[$eventName] as $listener) {
|
||||
|
||||
$this->lastEvent = $eventName;
|
||||
|
||||
if ($listener->execute($data)) {
|
||||
$this->lastListener = get_class($listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last listener executed
|
||||
*
|
||||
* @access public
|
||||
* @return string Event name
|
||||
*/
|
||||
public function getLastListenerExecuted()
|
||||
{
|
||||
return $this->lastListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last fired event
|
||||
*
|
||||
* @access public
|
||||
* @return string Event name
|
||||
*/
|
||||
public function getLastTriggeredEvent()
|
||||
{
|
||||
return $this->lastEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of triggered events
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getTriggeredEvents()
|
||||
{
|
||||
return $this->events;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of triggered events
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getEventData($eventName)
|
||||
{
|
||||
return isset($this->events[$eventName]) ? $this->events[$eventName] : array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an event have been triggered
|
||||
*
|
||||
* @access public
|
||||
* @param string $eventName Event name
|
||||
* @return bool
|
||||
*/
|
||||
public function isEventTriggered($eventName)
|
||||
{
|
||||
return isset($this->events[$eventName]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush the list of triggered events
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function clearTriggeredEvents()
|
||||
{
|
||||
$this->events = array();
|
||||
$this->lastEvent = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a listener bind to an event
|
||||
*
|
||||
* @access public
|
||||
* @param string $eventName Event name
|
||||
* @param mixed $instance Instance name or object itself
|
||||
* @return bool Yes or no
|
||||
*/
|
||||
public function hasListener($eventName, $instance)
|
||||
{
|
||||
if (isset($this->listeners[$eventName])) {
|
||||
foreach ($this->listeners[$eventName] as $listener) {
|
||||
if ($listener instanceof $instance) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Core;
|
||||
|
||||
/**
|
||||
* Event listener interface
|
||||
*
|
||||
* @package core
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
interface Listener
|
||||
{
|
||||
/**
|
||||
* Execute the listener
|
||||
*
|
||||
* @access public
|
||||
* @param array $data Event data
|
||||
* @return boolean
|
||||
*/
|
||||
public function execute(array $data);
|
||||
}
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace Core;
|
||||
|
||||
use Pimple\Container;
|
||||
|
||||
/**
|
||||
* Tool class
|
||||
*
|
||||
@@ -33,23 +31,4 @@ class Tool
|
||||
fclose($fp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load and register a model
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @param Pimple\Container $container Container instance
|
||||
* @param string $name Model name
|
||||
* @return mixed
|
||||
*/
|
||||
public static function loadModel(Container $container, $name)
|
||||
{
|
||||
if (! isset($container[$name])) {
|
||||
$class = '\Model\\'.ucfirst($name);
|
||||
$container[$name] = new $class($container);
|
||||
}
|
||||
|
||||
return $container[$name];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Event;
|
||||
|
||||
use Pimple\Container;
|
||||
use Core\Listener;
|
||||
use Core\Tool;
|
||||
|
||||
/**
|
||||
* Base Listener
|
||||
*
|
||||
* @package event
|
||||
* @author Frederic Guillot
|
||||
*
|
||||
* @property \Model\Comment $comment
|
||||
* @property \Model\Project $project
|
||||
* @property \Model\ProjectActivity $projectActivity
|
||||
* @property \Model\SubTask $subTask
|
||||
* @property \Model\Task $task
|
||||
* @property \Model\TaskFinder $taskFinder
|
||||
*/
|
||||
abstract class Base implements Listener
|
||||
{
|
||||
/**
|
||||
* Container instance
|
||||
*
|
||||
* @access protected
|
||||
* @var \Pimple\Container
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @access public
|
||||
* @param \Pimple\Container $container
|
||||
*/
|
||||
public function __construct(Container $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return class information
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return get_called_class();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load automatically models
|
||||
*
|
||||
* @access public
|
||||
* @param string $name Model name
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
return Tool::loadModel($this->container, $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get event namespace
|
||||
*
|
||||
* Event = task.close | Namespace = task
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function getEventNamespace()
|
||||
{
|
||||
$event_name = $this->container['event']->getLastTriggeredEvent();
|
||||
return substr($event_name, 0, strpos($event_name, '.'));
|
||||
}
|
||||
}
|
||||
7
app/Event/CommentEvent.php
Normal file
7
app/Event/CommentEvent.php
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Event;
|
||||
|
||||
class CommentEvent extends GenericEvent
|
||||
{
|
||||
}
|
||||
7
app/Event/FileEvent.php
Normal file
7
app/Event/FileEvent.php
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Event;
|
||||
|
||||
class FileEvent extends GenericEvent
|
||||
{
|
||||
}
|
||||
45
app/Event/GenericEvent.php
Normal file
45
app/Event/GenericEvent.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace Event;
|
||||
|
||||
use ArrayAccess;
|
||||
use Symfony\Component\EventDispatcher\Event as BaseEvent;
|
||||
|
||||
class GenericEvent extends BaseEvent implements ArrayAccess
|
||||
{
|
||||
private $container = array();
|
||||
|
||||
public function __construct(array $values = array())
|
||||
{
|
||||
$this->container = $values;
|
||||
}
|
||||
|
||||
public function getAll()
|
||||
{
|
||||
return $this->container;
|
||||
}
|
||||
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
if (is_null($offset)) {
|
||||
$this->container[] = $value;
|
||||
} else {
|
||||
$this->container[$offset] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return isset($this->container[$offset]);
|
||||
}
|
||||
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
unset($this->container[$offset]);
|
||||
}
|
||||
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return isset($this->container[$offset]) ? $this->container[$offset] : null;
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Event;
|
||||
|
||||
/**
|
||||
* Notification listener
|
||||
*
|
||||
* @package event
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class NotificationListener extends Base
|
||||
{
|
||||
/**
|
||||
* Template name
|
||||
*
|
||||
* @accesss private
|
||||
* @var string
|
||||
*/
|
||||
private $template = '';
|
||||
|
||||
/**
|
||||
* Set template name
|
||||
*
|
||||
* @access public
|
||||
* @param string $template Template name
|
||||
*/
|
||||
public function setTemplate($template)
|
||||
{
|
||||
$this->template = $template;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the action
|
||||
*
|
||||
* @access public
|
||||
* @param array $data Event data dictionary
|
||||
* @return bool True if the action was executed or false when not executed
|
||||
*/
|
||||
public function execute(array $data)
|
||||
{
|
||||
$values = $this->getTemplateData($data);
|
||||
$users = $this->notification->getUsersList($values['task']['project_id']);
|
||||
|
||||
if ($users) {
|
||||
$this->notification->sendEmails($this->template, $users, $values);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch data for the mail template
|
||||
*
|
||||
* @access public
|
||||
* @param array $data Event data
|
||||
* @return array
|
||||
*/
|
||||
public function getTemplateData(array $data)
|
||||
{
|
||||
$values = array();
|
||||
|
||||
switch ($this->getEventNamespace()) {
|
||||
case 'task':
|
||||
$values['task'] = $this->taskFinder->getDetails($data['task_id']);
|
||||
break;
|
||||
case 'subtask':
|
||||
$values['subtask'] = $this->subtask->getById($data['id'], true);
|
||||
$values['task'] = $this->taskFinder->getDetails($data['task_id']);
|
||||
break;
|
||||
case 'file':
|
||||
$values['file'] = $data;
|
||||
$values['task'] = $this->taskFinder->getDetails($data['task_id']);
|
||||
break;
|
||||
case 'comment':
|
||||
$values['comment'] = $this->comment->getById($data['id']);
|
||||
$values['task'] = $this->taskFinder->getDetails($values['comment']['task_id']);
|
||||
break;
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Event;
|
||||
|
||||
/**
|
||||
* Project activity listener
|
||||
*
|
||||
* @package event
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class ProjectActivityListener extends Base
|
||||
{
|
||||
/**
|
||||
* Execute the action
|
||||
*
|
||||
* @access public
|
||||
* @param array $data Event data dictionary
|
||||
* @return bool True if the action was executed or false when not executed
|
||||
*/
|
||||
public function execute(array $data)
|
||||
{
|
||||
if (isset($data['task_id'])) {
|
||||
|
||||
$values = $this->getValues($data);
|
||||
|
||||
return $this->projectActivity->createEvent(
|
||||
$values['task']['project_id'],
|
||||
$values['task']['id'],
|
||||
$this->acl->getUserId(),
|
||||
$this->container['event']->getLastTriggeredEvent(),
|
||||
$values
|
||||
);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get event activity data
|
||||
*
|
||||
* @access private
|
||||
* @param array $data Event data dictionary
|
||||
* @return array
|
||||
*/
|
||||
private function getValues(array $data)
|
||||
{
|
||||
$values = array();
|
||||
$values['task'] = $this->taskFinder->getDetails($data['task_id']);
|
||||
|
||||
switch ($this->getEventNamespace()) {
|
||||
case 'subtask':
|
||||
$values['subtask'] = $this->subTask->getById($data['id'], true);
|
||||
break;
|
||||
case 'comment':
|
||||
$values['comment'] = $this->comment->getById($data['id']);
|
||||
break;
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Event;
|
||||
|
||||
/**
|
||||
* Project daily summary listener
|
||||
*
|
||||
* @package event
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class ProjectDailySummaryListener extends Base
|
||||
{
|
||||
/**
|
||||
* Execute the action
|
||||
*
|
||||
* @access public
|
||||
* @param array $data Event data dictionary
|
||||
* @return bool True if the action was executed or false when not executed
|
||||
*/
|
||||
public function execute(array $data)
|
||||
{
|
||||
if (isset($data['project_id'])) {
|
||||
return $this->projectDailySummary->updateTotals($data['project_id'], date('Y-m-d'));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Event;
|
||||
|
||||
/**
|
||||
* Project modification date listener
|
||||
*
|
||||
* Update the "last_modified" field for a project
|
||||
*
|
||||
* @package event
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class ProjectModificationDateListener extends Base
|
||||
{
|
||||
/**
|
||||
* Execute the action
|
||||
*
|
||||
* @access public
|
||||
* @param array $data Event data dictionary
|
||||
* @return bool True if the action was executed or false when not executed
|
||||
*/
|
||||
public function execute(array $data)
|
||||
{
|
||||
if (isset($data['project_id'])) {
|
||||
return $this->project->updateModificationDate($data['project_id']);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
7
app/Event/SubtaskEvent.php
Normal file
7
app/Event/SubtaskEvent.php
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Event;
|
||||
|
||||
class SubtaskEvent extends GenericEvent
|
||||
{
|
||||
}
|
||||
7
app/Event/TaskEvent.php
Normal file
7
app/Event/TaskEvent.php
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Event;
|
||||
|
||||
class TaskEvent extends GenericEvent
|
||||
{
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Event;
|
||||
|
||||
/**
|
||||
* Webhook task events
|
||||
*
|
||||
* @package event
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class WebhookListener extends Base
|
||||
{
|
||||
/**
|
||||
* Url to call
|
||||
*
|
||||
* @access private
|
||||
* @var string
|
||||
*/
|
||||
private $url = '';
|
||||
|
||||
/**
|
||||
* Set webhook url
|
||||
*
|
||||
* @access public
|
||||
* @param string $url URL to call
|
||||
*/
|
||||
public function setUrl($url)
|
||||
{
|
||||
$this->url = $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the action
|
||||
*
|
||||
* @access public
|
||||
* @param array $data Event data dictionary
|
||||
* @return bool True if the action was executed or false when not executed
|
||||
*/
|
||||
public function execute(array $data)
|
||||
{
|
||||
$this->webhook->notify($this->url, $data);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -248,7 +248,7 @@ class Action extends Base
|
||||
$listener->setParam($param['name'], $param['value']);
|
||||
}
|
||||
|
||||
$this->event->attach($action['event_name'], $listener);
|
||||
$this->container['dispatcher']->addListener($action['event_name'], array($listener, 'execute'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,10 +2,7 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use Core\Event;
|
||||
use Core\Tool;
|
||||
use Pimple\Container;
|
||||
use PicoDb\Database;
|
||||
|
||||
/**
|
||||
* Base model class
|
||||
@@ -51,14 +48,6 @@ abstract class Base
|
||||
*/
|
||||
protected $db;
|
||||
|
||||
/**
|
||||
* Event dispatcher instance
|
||||
*
|
||||
* @access public
|
||||
* @var \Core\Event
|
||||
*/
|
||||
public $event;
|
||||
|
||||
/**
|
||||
* Container instance
|
||||
*
|
||||
@@ -77,7 +66,6 @@ abstract class Base
|
||||
{
|
||||
$this->container = $container;
|
||||
$this->db = $this->container['db'];
|
||||
$this->event = $this->container['event'];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,7 +77,7 @@ abstract class Base
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
return Tool::loadModel($this->container, $name);
|
||||
return $this->container[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use Event\CommentEvent;
|
||||
use SimpleValidator\Validator;
|
||||
use SimpleValidator\Validators;
|
||||
|
||||
@@ -107,7 +108,7 @@ class Comment extends Base
|
||||
$comment_id = $this->persist(self::TABLE, $values);
|
||||
|
||||
if ($comment_id) {
|
||||
$this->event->trigger(self::EVENT_CREATE, array('id' => $comment_id) + $values);
|
||||
$this->container['dispatcher']->dispatch(self::EVENT_CREATE, new CommentEvent(array('id' => $comment_id) + $values));
|
||||
}
|
||||
|
||||
return $comment_id;
|
||||
@@ -127,7 +128,7 @@ class Comment extends Base
|
||||
->eq('id', $values['id'])
|
||||
->update(array('comment' => $values['comment']));
|
||||
|
||||
$this->event->trigger(self::EVENT_UPDATE, $values);
|
||||
$this->container['dispatcher']->dispatch(self::EVENT_UPDATE, new CommentEvent($values));
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use Event\FileEvent;
|
||||
|
||||
/**
|
||||
* File model
|
||||
*
|
||||
@@ -89,7 +91,10 @@ class File extends Base
|
||||
*/
|
||||
public function create($task_id, $name, $path, $is_image)
|
||||
{
|
||||
$this->event->trigger(self::EVENT_CREATE, array('task_id' => $task_id, 'name' => $name));
|
||||
$this->container['dispatcher']->dispatch(
|
||||
self::EVENT_CREATE,
|
||||
new FileEvent(array('task_id' => $task_id, 'name' => $name))
|
||||
);
|
||||
|
||||
return $this->db->table(self::TABLE)->save(array(
|
||||
'task_id' => $task_id,
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use Event\GenericEvent;
|
||||
|
||||
/**
|
||||
* Github Webhook model
|
||||
*
|
||||
@@ -88,7 +90,10 @@ class GithubWebhook extends Base
|
||||
}
|
||||
|
||||
if ($task['is_active'] == Task::STATUS_OPEN) {
|
||||
$this->event->trigger(self::EVENT_COMMIT, array('task_id' => $task_id) + $task);
|
||||
$this->container['dispatcher']->dispatch(
|
||||
self::EVENT_COMMIT,
|
||||
new GenericEvent(array('task_id' => $task_id) + $task)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,7 +151,11 @@ class GithubWebhook extends Base
|
||||
'task_id' => $task['id'],
|
||||
);
|
||||
|
||||
$this->event->trigger(self::EVENT_ISSUE_COMMENT, $event);
|
||||
$this->container['dispatcher']->dispatch(
|
||||
self::EVENT_ISSUE_COMMENT,
|
||||
new GenericEvent($event)
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -169,7 +178,11 @@ class GithubWebhook extends Base
|
||||
'description' => $issue['body']."\n\n[".t('Github Issue').']('.$issue['html_url'].')',
|
||||
);
|
||||
|
||||
$this->event->trigger(self::EVENT_ISSUE_OPENED, $event);
|
||||
$this->container['dispatcher']->dispatch(
|
||||
self::EVENT_ISSUE_OPENED,
|
||||
new GenericEvent($event)
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -191,7 +204,11 @@ class GithubWebhook extends Base
|
||||
'reference' => $issue['number'],
|
||||
);
|
||||
|
||||
$this->event->trigger(self::EVENT_ISSUE_CLOSED, $event);
|
||||
$this->container['dispatcher']->dispatch(
|
||||
self::EVENT_ISSUE_CLOSED,
|
||||
new GenericEvent($event)
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -216,7 +233,11 @@ class GithubWebhook extends Base
|
||||
'reference' => $issue['number'],
|
||||
);
|
||||
|
||||
$this->event->trigger(self::EVENT_ISSUE_REOPENED, $event);
|
||||
$this->container['dispatcher']->dispatch(
|
||||
self::EVENT_ISSUE_REOPENED,
|
||||
new GenericEvent($event)
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -244,7 +265,11 @@ class GithubWebhook extends Base
|
||||
'reference' => $issue['number'],
|
||||
);
|
||||
|
||||
$this->event->trigger(self::EVENT_ISSUE_ASSIGNEE_CHANGE, $event);
|
||||
$this->container['dispatcher']->dispatch(
|
||||
self::EVENT_ISSUE_ASSIGNEE_CHANGE,
|
||||
new GenericEvent($event)
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -271,7 +296,11 @@ class GithubWebhook extends Base
|
||||
'reference' => $issue['number'],
|
||||
);
|
||||
|
||||
$this->event->trigger(self::EVENT_ISSUE_ASSIGNEE_CHANGE, $event);
|
||||
$this->container['dispatcher']->dispatch(
|
||||
self::EVENT_ISSUE_ASSIGNEE_CHANGE,
|
||||
new GenericEvent($event)
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -299,7 +328,11 @@ class GithubWebhook extends Base
|
||||
'label' => $label['name'],
|
||||
);
|
||||
|
||||
$this->event->trigger(self::EVENT_ISSUE_LABEL_CHANGE, $event);
|
||||
$this->container['dispatcher']->dispatch(
|
||||
self::EVENT_ISSUE_LABEL_CHANGE,
|
||||
new GenericEvent($event)
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -328,7 +361,11 @@ class GithubWebhook extends Base
|
||||
'category_id' => 0,
|
||||
);
|
||||
|
||||
$this->event->trigger(self::EVENT_ISSUE_LABEL_CHANGE, $event);
|
||||
$this->container['dispatcher']->dispatch(
|
||||
self::EVENT_ISSUE_LABEL_CHANGE,
|
||||
new GenericEvent($event)
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -93,37 +93,6 @@ class Notification extends Base
|
||||
return $users;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach events
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function attachEvents()
|
||||
{
|
||||
$events = array(
|
||||
Task::EVENT_CREATE => 'task_creation',
|
||||
Task::EVENT_UPDATE => 'task_update',
|
||||
Task::EVENT_CLOSE => 'task_close',
|
||||
Task::EVENT_OPEN => 'task_open',
|
||||
Task::EVENT_MOVE_COLUMN => 'task_move_column',
|
||||
Task::EVENT_MOVE_POSITION => 'task_move_position',
|
||||
Task::EVENT_ASSIGNEE_CHANGE => 'task_assignee_change',
|
||||
SubTask::EVENT_CREATE => 'subtask_creation',
|
||||
SubTask::EVENT_UPDATE => 'subtask_update',
|
||||
Comment::EVENT_CREATE => 'comment_creation',
|
||||
Comment::EVENT_UPDATE => 'comment_update',
|
||||
File::EVENT_CREATE => 'file_creation',
|
||||
);
|
||||
|
||||
foreach ($events as $event_name => $template_name) {
|
||||
|
||||
$listener = new NotificationListener($this->container);
|
||||
$listener->setTemplate($template_name);
|
||||
|
||||
$this->event->attach($event_name, $listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the email notifications
|
||||
*
|
||||
|
||||
@@ -4,7 +4,6 @@ namespace Model;
|
||||
|
||||
use SimpleValidator\Validator;
|
||||
use SimpleValidator\Validators;
|
||||
use Event\ProjectModificationDateListener;
|
||||
use Core\Security;
|
||||
|
||||
/**
|
||||
@@ -489,34 +488,4 @@ class Project extends Base
|
||||
$v->getErrors()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach events
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function attachEvents()
|
||||
{
|
||||
$events = array(
|
||||
Task::EVENT_CREATE_UPDATE,
|
||||
Task::EVENT_CLOSE,
|
||||
Task::EVENT_OPEN,
|
||||
Task::EVENT_MOVE_COLUMN,
|
||||
Task::EVENT_MOVE_POSITION,
|
||||
Task::EVENT_ASSIGNEE_CHANGE,
|
||||
GithubWebhook::EVENT_ISSUE_OPENED,
|
||||
GithubWebhook::EVENT_ISSUE_CLOSED,
|
||||
GithubWebhook::EVENT_ISSUE_REOPENED,
|
||||
GithubWebhook::EVENT_ISSUE_ASSIGNEE_CHANGE,
|
||||
GithubWebhook::EVENT_ISSUE_LABEL_CHANGE,
|
||||
GithubWebhook::EVENT_ISSUE_COMMENT,
|
||||
GithubWebhook::EVENT_COMMIT,
|
||||
);
|
||||
|
||||
$listener = new ProjectModificationDateListener($this->container);
|
||||
|
||||
foreach ($events as $event_name) {
|
||||
$this->event->attach($event_name, $listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
namespace Model;
|
||||
|
||||
use Core\Template;
|
||||
use Event\ProjectActivityListener;
|
||||
|
||||
/**
|
||||
* Project activity model
|
||||
@@ -126,34 +125,6 @@ class ProjectActivity extends Base
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach events to be able to record the history
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function attachEvents()
|
||||
{
|
||||
$events = array(
|
||||
Task::EVENT_ASSIGNEE_CHANGE,
|
||||
Task::EVENT_UPDATE,
|
||||
Task::EVENT_CREATE,
|
||||
Task::EVENT_CLOSE,
|
||||
Task::EVENT_OPEN,
|
||||
Task::EVENT_MOVE_COLUMN,
|
||||
Task::EVENT_MOVE_POSITION,
|
||||
Comment::EVENT_UPDATE,
|
||||
Comment::EVENT_CREATE,
|
||||
SubTask::EVENT_UPDATE,
|
||||
SubTask::EVENT_CREATE,
|
||||
);
|
||||
|
||||
$listener = new ProjectActivityListener($this->container);
|
||||
|
||||
foreach ($events as $event_name) {
|
||||
$this->event->attach($event_name, $listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the event html content
|
||||
*
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
namespace Model;
|
||||
|
||||
use Core\Template;
|
||||
use Event\ProjectDailySummaryListener;
|
||||
|
||||
/**
|
||||
* Project daily summary
|
||||
@@ -157,25 +156,4 @@ class ProjectDailySummary extends Base
|
||||
|
||||
return $metrics;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach events to be able to record the metrics
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function attachEvents()
|
||||
{
|
||||
$events = array(
|
||||
Task::EVENT_CREATE,
|
||||
Task::EVENT_CLOSE,
|
||||
Task::EVENT_OPEN,
|
||||
Task::EVENT_MOVE_COLUMN,
|
||||
);
|
||||
|
||||
$listener = new ProjectDailySummaryListener($this->container);
|
||||
|
||||
foreach ($events as $event_name) {
|
||||
$this->event->attach($event_name, $listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use Event\SubtaskEvent;
|
||||
use SimpleValidator\Validator;
|
||||
use SimpleValidator\Validators;
|
||||
|
||||
@@ -146,7 +147,10 @@ class SubTask extends Base
|
||||
$subtask_id = $this->persist(self::TABLE, $values);
|
||||
|
||||
if ($subtask_id) {
|
||||
$this->event->trigger(self::EVENT_CREATE, array('id' => $subtask_id) + $values);
|
||||
$this->container['dispatcher']->dispatch(
|
||||
self::EVENT_CREATE,
|
||||
new SubtaskEvent(array('id' => $subtask_id) + $values)
|
||||
);
|
||||
}
|
||||
|
||||
return $subtask_id;
|
||||
@@ -165,7 +169,10 @@ class SubTask extends Base
|
||||
$result = $this->db->table(self::TABLE)->eq('id', $values['id'])->save($values);
|
||||
|
||||
if ($result) {
|
||||
$this->event->trigger(self::EVENT_UPDATE, $values);
|
||||
$this->container['dispatcher']->dispatch(
|
||||
self::EVENT_UPDATE,
|
||||
new SubtaskEvent($values)
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
||||
@@ -30,6 +30,7 @@ class Task extends Base
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const EVENT_MOVE_PROJECT = 'task.move.project';
|
||||
const EVENT_MOVE_COLUMN = 'task.move.column';
|
||||
const EVENT_MOVE_POSITION = 'task.move.position';
|
||||
const EVENT_MOVE_SWIMLANE = 'task.move.swimlane';
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use Event\TaskEvent;
|
||||
|
||||
/**
|
||||
* Task Creation
|
||||
*
|
||||
@@ -64,7 +66,7 @@ class TaskCreation extends Base
|
||||
private function fireEvents($task_id, array $values)
|
||||
{
|
||||
$values['task_id'] = $task_id;
|
||||
$this->event->trigger(Task::EVENT_CREATE_UPDATE, $values);
|
||||
$this->event->trigger(Task::EVENT_CREATE, $values);
|
||||
$this->container['dispatcher']->dispatch(Task::EVENT_CREATE_UPDATE, new TaskEvent($values));
|
||||
$this->container['dispatcher']->dispatch(Task::EVENT_CREATE, new TaskEvent($values));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use Event\TaskEvent;
|
||||
|
||||
/**
|
||||
* Task Duplication
|
||||
*
|
||||
@@ -84,7 +86,14 @@ class TaskDuplication extends Base
|
||||
|
||||
$this->checkDestinationProjectValues($values);
|
||||
|
||||
return $this->db->table(Task::TABLE)->eq('id', $task['id'])->update($values);
|
||||
if ($this->db->table(Task::TABLE)->eq('id', $task['id'])->update($values)) {
|
||||
$this->container['dispatcher']->dispatch(
|
||||
Task::EVENT_MOVE_PROJECT,
|
||||
new TaskEvent(array_merge($task, $values, array('task_id' => $task['id'])))
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use Event\TaskEvent;
|
||||
|
||||
/**
|
||||
* Task Modification
|
||||
*
|
||||
@@ -15,17 +17,16 @@ class TaskModification extends Base
|
||||
*
|
||||
* @access public
|
||||
* @param array $values
|
||||
* @param boolean $fire_events
|
||||
* @return boolean
|
||||
*/
|
||||
public function update(array $values, $fire_events = true)
|
||||
public function update(array $values)
|
||||
{
|
||||
$original_task = $this->taskFinder->getById($values['id']);
|
||||
|
||||
$this->prepare($values);
|
||||
$result = $this->db->table(Task::TABLE)->eq('id', $original_task['id'])->update($values);
|
||||
|
||||
if ($result && $fire_events) {
|
||||
if ($result) {
|
||||
$this->fireEvents($original_task, $values);
|
||||
}
|
||||
|
||||
@@ -51,7 +52,7 @@ class TaskModification extends Base
|
||||
}
|
||||
|
||||
foreach ($events as $event) {
|
||||
$this->event->trigger($event, $event_data);
|
||||
$this->container['dispatcher']->dispatch($event, new TaskEvent($event_data));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use Event\TaskEvent;
|
||||
|
||||
/**
|
||||
* Task Position
|
||||
*
|
||||
@@ -139,13 +141,13 @@ class TaskPosition extends Base
|
||||
);
|
||||
|
||||
if ($task['swimlane_id'] != $new_swimlane_id) {
|
||||
$this->event->trigger(Task::EVENT_MOVE_SWIMLANE, $event_data);
|
||||
$this->container['dispatcher']->dispatch(Task::EVENT_MOVE_SWIMLANE, new TaskEvent($event_data));
|
||||
}
|
||||
else if ($task['column_id'] != $new_column_id) {
|
||||
$this->event->trigger(Task::EVENT_MOVE_COLUMN, $event_data);
|
||||
$this->container['dispatcher']->dispatch(Task::EVENT_MOVE_COLUMN, new TaskEvent($event_data));
|
||||
}
|
||||
else if ($task['position'] != $new_position) {
|
||||
$this->event->trigger(Task::EVENT_MOVE_POSITION, $event_data);
|
||||
$this->container['dispatcher']->dispatch(Task::EVENT_MOVE_POSITION, new TaskEvent($event_data));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use Event\TaskEvent;
|
||||
|
||||
/**
|
||||
* Task Status
|
||||
*
|
||||
@@ -84,9 +86,9 @@ class TaskStatus extends Base
|
||||
));
|
||||
|
||||
if ($result) {
|
||||
$this->event->trigger(
|
||||
$this->container['dispatcher']->dispatch(
|
||||
$event,
|
||||
array('task_id' => $task_id) + $this->taskFinder->getById($task_id)
|
||||
new TaskEvent(array('task_id' => $task_id) + $this->taskFinder->getById($task_id))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use Event\WebhookListener;
|
||||
|
||||
/**
|
||||
* Webhook model
|
||||
*
|
||||
@@ -33,87 +31,6 @@ class Webhook extends Base
|
||||
*/
|
||||
const HTTP_USER_AGENT = 'Kanboard Webhook';
|
||||
|
||||
/**
|
||||
* URL to call for task creation
|
||||
*
|
||||
* @access private
|
||||
* @var string
|
||||
*/
|
||||
private $url_task_creation = '';
|
||||
|
||||
/**
|
||||
* URL to call for task modification
|
||||
*
|
||||
* @access private
|
||||
* @var string
|
||||
*/
|
||||
private $url_task_modification = '';
|
||||
|
||||
/**
|
||||
* Webook token
|
||||
*
|
||||
* @access private
|
||||
* @var string
|
||||
*/
|
||||
private $token = '';
|
||||
|
||||
/**
|
||||
* Attach events
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function attachEvents()
|
||||
{
|
||||
$this->url_task_creation = $this->config->get('webhook_url_task_creation');
|
||||
$this->url_task_modification = $this->config->get('webhook_url_task_modification');
|
||||
$this->token = $this->config->get('webhook_token');
|
||||
|
||||
if ($this->url_task_creation) {
|
||||
$this->attachCreateEvents();
|
||||
}
|
||||
|
||||
if ($this->url_task_modification) {
|
||||
$this->attachUpdateEvents();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach events for task modification
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function attachUpdateEvents()
|
||||
{
|
||||
$events = array(
|
||||
Task::EVENT_UPDATE,
|
||||
Task::EVENT_CLOSE,
|
||||
Task::EVENT_OPEN,
|
||||
Task::EVENT_MOVE_COLUMN,
|
||||
Task::EVENT_MOVE_POSITION,
|
||||
Task::EVENT_ASSIGNEE_CHANGE,
|
||||
);
|
||||
|
||||
$listener = new WebhookListener($this->container);
|
||||
$listener->setUrl($this->url_task_modification);
|
||||
|
||||
foreach ($events as $event_name) {
|
||||
$this->event->attach($event_name, $listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach events for task creation
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function attachCreateEvents()
|
||||
{
|
||||
$listener = new WebhookListener($this->container);
|
||||
$listener->setUrl($this->url_task_creation);
|
||||
|
||||
$this->event->attach(Task::EVENT_CREATE, $listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the external URL
|
||||
*
|
||||
@@ -123,6 +40,8 @@ class Webhook extends Base
|
||||
*/
|
||||
public function notify($url, array $task)
|
||||
{
|
||||
$token = $this->config->get('webhook_token');
|
||||
|
||||
$headers = array(
|
||||
'Connection: close',
|
||||
'User-Agent: '.self::HTTP_USER_AGENT,
|
||||
@@ -140,10 +59,10 @@ class Webhook extends Base
|
||||
));
|
||||
|
||||
if (strpos($url, '?') !== false) {
|
||||
$url .= '&token='.$this->token;
|
||||
$url .= '&token='.$token;
|
||||
}
|
||||
else {
|
||||
$url .= '?token='.$this->token;
|
||||
$url .= '?token='.$token;
|
||||
}
|
||||
|
||||
@file_get_contents($url, false, $context);
|
||||
|
||||
@@ -4,9 +4,9 @@ namespace ServiceProvider;
|
||||
|
||||
use Pimple\Container;
|
||||
use Pimple\ServiceProviderInterface;
|
||||
use PicoDb\Database as Dbal;
|
||||
use PicoDb\Database;
|
||||
|
||||
class Database implements ServiceProviderInterface
|
||||
class DatabaseProvider implements ServiceProviderInterface
|
||||
{
|
||||
public function register(Container $container)
|
||||
{
|
||||
@@ -55,7 +55,7 @@ class Database implements ServiceProviderInterface
|
||||
{
|
||||
require_once __DIR__.'/../Schema/Sqlite.php';
|
||||
|
||||
return new Dbal(array(
|
||||
return new Database(array(
|
||||
'driver' => 'sqlite',
|
||||
'filename' => DB_FILENAME
|
||||
));
|
||||
@@ -70,7 +70,7 @@ class Database implements ServiceProviderInterface
|
||||
{
|
||||
require_once __DIR__.'/../Schema/Mysql.php';
|
||||
|
||||
return new Dbal(array(
|
||||
return new Database(array(
|
||||
'driver' => 'mysql',
|
||||
'hostname' => DB_HOSTNAME,
|
||||
'username' => DB_USERNAME,
|
||||
@@ -89,7 +89,7 @@ class Database implements ServiceProviderInterface
|
||||
{
|
||||
require_once __DIR__.'/../Schema/Postgres.php';
|
||||
|
||||
return new Dbal(array(
|
||||
return new Database(array(
|
||||
'driver' => 'postgres',
|
||||
'hostname' => DB_HOSTNAME,
|
||||
'username' => DB_USERNAME,
|
||||
@@ -1,15 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace ServiceProvider;
|
||||
|
||||
use Pimple\Container;
|
||||
use Pimple\ServiceProviderInterface;
|
||||
use Core\Event as EventDispatcher;
|
||||
|
||||
class Event implements ServiceProviderInterface
|
||||
{
|
||||
public function register(Container $container)
|
||||
{
|
||||
$container['event'] = new EventDispatcher;
|
||||
}
|
||||
}
|
||||
28
app/ServiceProvider/EventDispatcherProvider.php
Normal file
28
app/ServiceProvider/EventDispatcherProvider.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace ServiceProvider;
|
||||
|
||||
use Pimple\Container;
|
||||
use Pimple\ServiceProviderInterface;
|
||||
use Subscriber\NotificationSubscriber;
|
||||
use Subscriber\ProjectActivitySubscriber;
|
||||
use Subscriber\ProjectDailySummarySubscriber;
|
||||
use Subscriber\ProjectModificationDateSubscriber;
|
||||
use Subscriber\WebhookSubscriber;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
|
||||
class EventDispatcherProvider implements ServiceProviderInterface
|
||||
{
|
||||
public function register(Container $container)
|
||||
{
|
||||
$container['dispatcher'] = new EventDispatcher;
|
||||
$container['dispatcher']->addSubscriber(new ProjectActivitySubscriber($container));
|
||||
$container['dispatcher']->addSubscriber(new ProjectDailySummarySubscriber($container));
|
||||
$container['dispatcher']->addSubscriber(new ProjectModificationDateSubscriber($container));
|
||||
$container['dispatcher']->addSubscriber(new WebhookSubscriber($container));
|
||||
$container['dispatcher']->addSubscriber(new NotificationSubscriber($container));
|
||||
|
||||
// Automatic actions
|
||||
$container['action']->attachEvents();
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ use Monolog\Logger;
|
||||
use Monolog\Handler\StreamHandler;
|
||||
use Monolog\Handler\SyslogHandler;
|
||||
|
||||
class Logging implements ServiceProviderInterface
|
||||
class LoggingProvider implements ServiceProviderInterface
|
||||
{
|
||||
public function register(Container $container)
|
||||
{
|
||||
@@ -8,7 +8,7 @@ use Swift_SmtpTransport;
|
||||
use Swift_SendmailTransport;
|
||||
use Swift_MailTransport;
|
||||
|
||||
class Mailer implements ServiceProviderInterface
|
||||
class MailerProvider implements ServiceProviderInterface
|
||||
{
|
||||
public function register(Container $container)
|
||||
{
|
||||
63
app/ServiceProvider/ModelProvider.php
Normal file
63
app/ServiceProvider/ModelProvider.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace ServiceProvider;
|
||||
|
||||
use Model\Config;
|
||||
use Model\Project;
|
||||
use Model\Webhook;
|
||||
use Pimple\Container;
|
||||
use Pimple\ServiceProviderInterface;
|
||||
|
||||
class ModelProvider implements ServiceProviderInterface
|
||||
{
|
||||
private $models = array(
|
||||
'Acl',
|
||||
'Action',
|
||||
'Authentication',
|
||||
'Board',
|
||||
'Category',
|
||||
'Color',
|
||||
'Comment',
|
||||
'Config',
|
||||
'DateParser',
|
||||
'File',
|
||||
'GithubWebhook',
|
||||
'LastLogin',
|
||||
'Notification',
|
||||
'Project',
|
||||
'ProjectActivity',
|
||||
'ProjectAnalytics',
|
||||
'ProjectDailySummary',
|
||||
'ProjectPaginator',
|
||||
'ProjectPermission',
|
||||
'SubTask',
|
||||
'SubtaskPaginator',
|
||||
'Swimlane',
|
||||
'Task',
|
||||
'TaskCreation',
|
||||
'TaskDuplication',
|
||||
'TaskExport',
|
||||
'TaskFinder',
|
||||
'TaskModification',
|
||||
'TaskPaginator',
|
||||
'TaskPermission',
|
||||
'TaskPosition',
|
||||
'TaskStatus',
|
||||
'TaskValidator',
|
||||
'TimeTracking',
|
||||
'User',
|
||||
'Webhook',
|
||||
);
|
||||
|
||||
public function register(Container $container)
|
||||
{
|
||||
foreach ($this->models as $model) {
|
||||
|
||||
$class = '\Model\\'.$model;
|
||||
|
||||
$container[lcfirst($model)] = function ($c) use ($class) {
|
||||
return new $class($c);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
47
app/Subscriber/Base.php
Normal file
47
app/Subscriber/Base.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace Subscriber;
|
||||
|
||||
use Event\TaskEvent;
|
||||
use Model\Task;
|
||||
use Pimple\Container;
|
||||
|
||||
/**
|
||||
* Base subscriber class
|
||||
*
|
||||
* @package subscriber
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
abstract class Base
|
||||
{
|
||||
/**
|
||||
* Container instance
|
||||
*
|
||||
* @access protected
|
||||
* @var \Pimple\Container
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @access public
|
||||
* @param \Pimple\Container $container
|
||||
*/
|
||||
public function __construct(Container $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load automatically models
|
||||
*
|
||||
* @access public
|
||||
* @param string $name Model name
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
return $this->container[$name];
|
||||
}
|
||||
}
|
||||
81
app/Subscriber/NotificationSubscriber.php
Normal file
81
app/Subscriber/NotificationSubscriber.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace Subscriber;
|
||||
|
||||
use Event\GenericEvent;
|
||||
use Model\Task;
|
||||
use Model\Comment;
|
||||
use Model\SubTask;
|
||||
use Model\File;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
class NotificationSubscriber extends Base implements EventSubscriberInterface
|
||||
{
|
||||
private $templates = array(
|
||||
Task::EVENT_CREATE => 'task_creation',
|
||||
Task::EVENT_UPDATE => 'task_update',
|
||||
Task::EVENT_CLOSE => 'task_close',
|
||||
Task::EVENT_OPEN => 'task_open',
|
||||
Task::EVENT_MOVE_COLUMN => 'task_move_column',
|
||||
Task::EVENT_MOVE_POSITION => 'task_move_position',
|
||||
Task::EVENT_ASSIGNEE_CHANGE => 'task_assignee_change',
|
||||
SubTask::EVENT_CREATE => 'subtask_creation',
|
||||
SubTask::EVENT_UPDATE => 'subtask_update',
|
||||
Comment::EVENT_CREATE => 'comment_creation',
|
||||
Comment::EVENT_UPDATE => 'comment_update',
|
||||
File::EVENT_CREATE => 'file_creation',
|
||||
);
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
Task::EVENT_CREATE => array('execute', 0),
|
||||
Task::EVENT_UPDATE => array('execute', 0),
|
||||
Task::EVENT_CLOSE => array('execute', 0),
|
||||
Task::EVENT_OPEN => array('execute', 0),
|
||||
Task::EVENT_MOVE_COLUMN => array('execute', 0),
|
||||
Task::EVENT_MOVE_POSITION => array('execute', 0),
|
||||
Task::EVENT_ASSIGNEE_CHANGE => array('execute', 0),
|
||||
SubTask::EVENT_CREATE => array('execute', 0),
|
||||
SubTask::EVENT_UPDATE => array('execute', 0),
|
||||
Comment::EVENT_CREATE => array('execute', 0),
|
||||
Comment::EVENT_UPDATE => array('execute', 0),
|
||||
File::EVENT_CREATE => array('execute', 0),
|
||||
);
|
||||
}
|
||||
|
||||
public function execute(GenericEvent $event)
|
||||
{
|
||||
$values = $this->getTemplateData($event);
|
||||
$users = $this->notification->getUsersList($values['task']['project_id']);
|
||||
|
||||
if ($users) {
|
||||
$this->notification->sendEmails($this->templates[$event->getName()], $users, $values);
|
||||
}
|
||||
}
|
||||
|
||||
public function getTemplateData(GenericEvent $event)
|
||||
{
|
||||
$values = array();
|
||||
|
||||
switch (get_class($event)) {
|
||||
case 'Event\TaskEvent':
|
||||
$values['task'] = $this->taskFinder->getDetails($event['task_id']);
|
||||
break;
|
||||
case 'Event\SubtaskEvent':
|
||||
$values['subtask'] = $this->subTask->getById($event['id'], true);
|
||||
$values['task'] = $this->taskFinder->getDetails($event['task_id']);
|
||||
break;
|
||||
case 'Event\FileEvent':
|
||||
$values['file'] = $event->getAll();
|
||||
$values['task'] = $this->taskFinder->getDetails($event['task_id']);
|
||||
break;
|
||||
case 'Event\CommentEvent':
|
||||
$values['comment'] = $this->comment->getById($event['id']);
|
||||
$values['task'] = $this->taskFinder->getDetails($values['comment']['task_id']);
|
||||
break;
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
}
|
||||
63
app/Subscriber/ProjectActivitySubscriber.php
Normal file
63
app/Subscriber/ProjectActivitySubscriber.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace Subscriber;
|
||||
|
||||
use Event\GenericEvent;
|
||||
use Model\Task;
|
||||
use Model\Comment;
|
||||
use Model\SubTask;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
class ProjectActivitySubscriber extends Base implements EventSubscriberInterface
|
||||
{
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
Task::EVENT_ASSIGNEE_CHANGE => array('execute', 0),
|
||||
Task::EVENT_UPDATE => array('execute', 0),
|
||||
Task::EVENT_CREATE => array('execute', 0),
|
||||
Task::EVENT_CLOSE => array('execute', 0),
|
||||
Task::EVENT_OPEN => array('execute', 0),
|
||||
Task::EVENT_MOVE_COLUMN => array('execute', 0),
|
||||
Task::EVENT_MOVE_POSITION => array('execute', 0),
|
||||
Comment::EVENT_UPDATE => array('execute', 0),
|
||||
Comment::EVENT_CREATE => array('execute', 0),
|
||||
SubTask::EVENT_UPDATE => array('execute', 0),
|
||||
SubTask::EVENT_CREATE => array('execute', 0),
|
||||
);
|
||||
}
|
||||
|
||||
public function execute(GenericEvent $event)
|
||||
{
|
||||
// Executed only when someone is logged
|
||||
if ($this->container['acl']->isLogged() && isset($event['task_id'])) {
|
||||
|
||||
$values = $this->getValues($event);
|
||||
|
||||
$this->projectActivity->createEvent(
|
||||
$values['task']['project_id'],
|
||||
$values['task']['id'],
|
||||
$this->acl->getUserId(),
|
||||
$event->getName(),
|
||||
$values
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private function getValues(GenericEvent $event)
|
||||
{
|
||||
$values = array();
|
||||
$values['task'] = $this->taskFinder->getDetails($event['task_id']);
|
||||
|
||||
switch (get_class($event)) {
|
||||
case 'Event\SubtaskEvent':
|
||||
$values['subtask'] = $this->subTask->getById($event['id'], true);
|
||||
break;
|
||||
case 'Event\CommentEvent':
|
||||
$values['comment'] = $this->comment->getById($event['id']);
|
||||
break;
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
}
|
||||
27
app/Subscriber/ProjectDailySummarySubscriber.php
Normal file
27
app/Subscriber/ProjectDailySummarySubscriber.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Subscriber;
|
||||
|
||||
use Event\TaskEvent;
|
||||
use Model\Task;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
class ProjectDailySummarySubscriber extends Base implements EventSubscriberInterface
|
||||
{
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
Task::EVENT_CREATE => array('execute', 0),
|
||||
Task::EVENT_CLOSE => array('execute', 0),
|
||||
Task::EVENT_OPEN => array('execute', 0),
|
||||
Task::EVENT_MOVE_COLUMN => array('execute', 0),
|
||||
);
|
||||
}
|
||||
|
||||
public function execute(TaskEvent $event)
|
||||
{
|
||||
if (isset($event['project_id'])) {
|
||||
$this->projectDailySummary->updateTotals($event['project_id'], date('Y-m-d'));
|
||||
}
|
||||
}
|
||||
}
|
||||
38
app/Subscriber/ProjectModificationDateSubscriber.php
Normal file
38
app/Subscriber/ProjectModificationDateSubscriber.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Subscriber;
|
||||
|
||||
use Event\GenericEvent;
|
||||
use Model\Task;
|
||||
use Model\GithubWebhook;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
class ProjectModificationDateSubscriber extends Base implements EventSubscriberInterface
|
||||
{
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
Task::EVENT_CREATE_UPDATE => array('execute', 0),
|
||||
Task::EVENT_CLOSE => array('execute', 0),
|
||||
Task::EVENT_OPEN => array('execute', 0),
|
||||
Task::EVENT_MOVE_COLUMN => array('execute', 0),
|
||||
Task::EVENT_MOVE_POSITION => array('execute', 0),
|
||||
Task::EVENT_MOVE_PROJECT => array('execute', 0),
|
||||
Task::EVENT_ASSIGNEE_CHANGE => array('execute', 0),
|
||||
GithubWebhook::EVENT_ISSUE_OPENED => array('execute', 0),
|
||||
GithubWebhook::EVENT_ISSUE_CLOSED => array('execute', 0),
|
||||
GithubWebhook::EVENT_ISSUE_REOPENED => array('execute', 0),
|
||||
GithubWebhook::EVENT_ISSUE_ASSIGNEE_CHANGE => array('execute', 0),
|
||||
GithubWebhook::EVENT_ISSUE_LABEL_CHANGE => array('execute', 0),
|
||||
GithubWebhook::EVENT_ISSUE_COMMENT => array('execute', 0),
|
||||
GithubWebhook::EVENT_COMMIT => array('execute', 0),
|
||||
);
|
||||
}
|
||||
|
||||
public function execute(GenericEvent $event)
|
||||
{
|
||||
if (isset($event['project_id'])) {
|
||||
$this->project->updateModificationDate($event['project_id']);
|
||||
}
|
||||
}
|
||||
}
|
||||
42
app/Subscriber/WebhookSubscriber.php
Normal file
42
app/Subscriber/WebhookSubscriber.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Subscriber;
|
||||
|
||||
use Event\TaskEvent;
|
||||
use Model\Task;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
class WebhookSubscriber extends Base implements EventSubscriberInterface
|
||||
{
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
Task::EVENT_CREATE => array('onTaskCreation', 0),
|
||||
Task::EVENT_UPDATE => array('onTaskModification', 0),
|
||||
Task::EVENT_CLOSE => array('onTaskModification', 0),
|
||||
Task::EVENT_OPEN => array('onTaskModification', 0),
|
||||
Task::EVENT_MOVE_COLUMN => array('onTaskModification', 0),
|
||||
Task::EVENT_MOVE_POSITION => array('onTaskModification', 0),
|
||||
Task::EVENT_ASSIGNEE_CHANGE => array('onTaskModification', 0),
|
||||
);
|
||||
}
|
||||
|
||||
public function onTaskCreation(TaskEvent $event)
|
||||
{
|
||||
$this->executeRequest('webhook_url_task_creation');
|
||||
}
|
||||
|
||||
public function onTaskModification(TaskEvent $event)
|
||||
{
|
||||
$this->executeRequest('webhook_url_task_modification');
|
||||
}
|
||||
|
||||
public function executeRequest($parameter)
|
||||
{
|
||||
$url = $this->config->get($parameter);
|
||||
|
||||
if (! empty($url)) {
|
||||
$this->webhook->notify($url, $event->getAll());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,11 @@ if (file_exists('config.php')) {
|
||||
require __DIR__.'/constants.php';
|
||||
|
||||
$container = new Pimple\Container;
|
||||
$container->register(new ServiceProvider\Logging);
|
||||
$container->register(new ServiceProvider\Database);
|
||||
$container->register(new ServiceProvider\Event);
|
||||
$container->register(new ServiceProvider\Mailer);
|
||||
$container->register(new ServiceProvider\LoggingProvider);
|
||||
$container->register(new ServiceProvider\DatabaseProvider);
|
||||
$container->register(new ServiceProvider\ModelProvider);
|
||||
$container->register(new ServiceProvider\EventDispatcherProvider);
|
||||
$container->register(new ServiceProvider\MailerProvider);
|
||||
|
||||
$container['config']->setupTranslations();
|
||||
$container['config']->setupTimezone();
|
||||
|
||||
Reference in New Issue
Block a user