summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--app/Console/PluginUpgradeCommand.php3
-rw-r--r--app/Console/WorkerCommand.php28
-rw-r--r--app/Controller/PluginController.php3
-rw-r--r--app/Core/Base.php1
-rw-r--r--app/Core/Mail/Client.php31
-rw-r--r--app/Core/Plugin/Directory.php56
-rw-r--r--app/Core/Queue/JobHandler.php50
-rw-r--r--app/Core/Queue/QueueManager.php71
-rw-r--r--app/Job/BaseJob.php33
-rw-r--r--app/Job/EmailJob.php54
-rw-r--r--app/Job/NotificationJob.php85
-rw-r--r--app/Job/ProjectMetricJob.php40
-rw-r--r--app/Model/UserNotification.php7
-rw-r--r--app/ServiceProvider/ActionProvider.php2
-rw-r--r--app/ServiceProvider/AuthenticationProvider.php2
-rw-r--r--app/ServiceProvider/AvatarProvider.php2
-rw-r--r--app/ServiceProvider/ClassProvider.php6
-rw-r--r--app/ServiceProvider/DatabaseProvider.php6
-rw-r--r--app/ServiceProvider/EventDispatcherProvider.php6
-rw-r--r--app/ServiceProvider/ExternalLinkProvider.php2
-rw-r--r--app/ServiceProvider/FilterProvider.php2
-rw-r--r--app/ServiceProvider/GroupProvider.php2
-rw-r--r--app/ServiceProvider/HelperProvider.php6
-rw-r--r--app/ServiceProvider/LoggingProvider.php6
-rw-r--r--app/ServiceProvider/NotificationProvider.php2
-rw-r--r--app/ServiceProvider/PluginProvider.php2
-rw-r--r--app/ServiceProvider/QueueProvider.php27
-rw-r--r--app/ServiceProvider/RouteProvider.php2
-rw-r--r--app/ServiceProvider/SessionProvider.php2
-rw-r--r--app/Subscriber/NotificationSubscriber.php74
-rw-r--r--app/Subscriber/ProjectDailySummarySubscriber.php4
-rw-r--r--app/common.php1
-rw-r--r--composer.json4
-rw-r--r--composer.lock1022
-rwxr-xr-xkanboard2
-rw-r--r--tests/units/Base.php17
-rw-r--r--tests/units/Core/Plugin/DirectoryTest.php44
-rw-r--r--tests/units/Model/UserNotificationTest.php29
39 files changed, 1631 insertions, 109 deletions
diff --git a/ChangeLog b/ChangeLog
index a1113dcc..a10fc4bd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -17,6 +17,10 @@ Improvements:
* Use Gulp and Bower to manage assets
* Controller and Middleware refactoring
+Bug fixes:
+
+* Do not send notifications to disabled users
+
Version 1.0.28
--------------
diff --git a/app/Console/PluginUpgradeCommand.php b/app/Console/PluginUpgradeCommand.php
index 6ec5836d..839124b1 100644
--- a/app/Console/PluginUpgradeCommand.php
+++ b/app/Console/PluginUpgradeCommand.php
@@ -3,6 +3,7 @@
namespace Kanboard\Console;
use Kanboard\Core\Plugin\Base as BasePlugin;
+use Kanboard\Core\Plugin\Directory;
use Kanboard\Core\Plugin\Installer;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
@@ -24,7 +25,7 @@ class PluginUpgradeCommand extends BaseCommand
}
$installer = new Installer($this->container);
- $availablePlugins = $this->httpClient->getJson(PLUGIN_API_URL);
+ $availablePlugins = Directory::getInstance($this->container)->getAvailablePlugins();
foreach ($this->pluginLoader->getPlugins() as $installedPlugin) {
$pluginDetails = $this->getPluginDetails($availablePlugins, $installedPlugin);
diff --git a/app/Console/WorkerCommand.php b/app/Console/WorkerCommand.php
new file mode 100644
index 00000000..e332624b
--- /dev/null
+++ b/app/Console/WorkerCommand.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace Kanboard\Console;
+
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+/**
+ * Class WorkerCommand
+ *
+ * @package Kanboard\Console
+ * @author Frederic Guillot
+ */
+class WorkerCommand extends BaseCommand
+{
+ protected function configure()
+ {
+ $this
+ ->setName('worker')
+ ->setDescription('Execute queue worker')
+ ;
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $this->queueManager->listen();
+ }
+}
diff --git a/app/Controller/PluginController.php b/app/Controller/PluginController.php
index b6f9a33b..7b9d64d9 100644
--- a/app/Controller/PluginController.php
+++ b/app/Controller/PluginController.php
@@ -2,6 +2,7 @@
namespace Kanboard\Controller;
+use Kanboard\Core\Plugin\Directory;
use Kanboard\Core\Plugin\Installer;
use Kanboard\Core\Plugin\PluginInstallerException;
@@ -40,7 +41,7 @@ class PluginController extends BaseController
$this->response->html($this->helper->layout->plugin('plugin/directory', array(
'installed_plugins' => $installedPlugins,
- 'available_plugins' => $this->httpClient->getJson(PLUGIN_API_URL),
+ 'available_plugins' => Directory::getInstance($this->container)->getAvailablePlugins(),
'title' => t('Plugin Directory'),
'is_configured' => Installer::isConfigured(),
)));
diff --git a/app/Core/Base.php b/app/Core/Base.php
index 39a8ccd6..e490484c 100644
--- a/app/Core/Base.php
+++ b/app/Core/Base.php
@@ -27,6 +27,7 @@ use Pimple\Container;
* @property \Kanboard\Core\Http\Response $response
* @property \Kanboard\Core\Http\Router $router
* @property \Kanboard\Core\Http\Route $route
+ * @property \Kanboard\Core\Queue\QueueManager $queueManager
* @property \Kanboard\Core\Mail\Client $emailClient
* @property \Kanboard\Core\ObjectStorage\ObjectStorageInterface $objectStorage
* @property \Kanboard\Core\Plugin\Hook $hook
diff --git a/app/Core/Mail/Client.php b/app/Core/Mail/Client.php
index 641b6abe..44f4753a 100644
--- a/app/Core/Mail/Client.php
+++ b/app/Core/Mail/Client.php
@@ -2,6 +2,7 @@
namespace Kanboard\Core\Mail;
+use Kanboard\Job\EmailJob;
use Pimple\Container;
use Kanboard\Core\Base;
@@ -46,23 +47,29 @@ class Client extends Base
public function send($email, $name, $subject, $html)
{
if (! empty($email)) {
- $this->logger->debug('Sending email to '.$email.' ('.MAIL_TRANSPORT.')');
-
- $start_time = microtime(true);
- $author = 'Kanboard';
+ $this->queueManager->push(EmailJob::getInstance($this->container)
+ ->withParams($email, $name, $subject, $html, $this->getAuthor())
+ );
+ }
- if ($this->userSession->isLogged()) {
- $author = e('%s via Kanboard', $this->helper->user->getFullname());
- }
+ return $this;
+ }
- $this->getTransport(MAIL_TRANSPORT)->sendEmail($email, $name, $subject, $html, $author);
+ /**
+ * Get email author
+ *
+ * @access public
+ * @return string
+ */
+ public function getAuthor()
+ {
+ $author = 'Kanboard';
- if (DEBUG) {
- $this->logger->debug('Email sent in '.round(microtime(true) - $start_time, 6).' seconds');
- }
+ if ($this->userSession->isLogged()) {
+ $author = e('%s via Kanboard', $this->helper->user->getFullname());
}
- return $this;
+ return $author;
}
/**
diff --git a/app/Core/Plugin/Directory.php b/app/Core/Plugin/Directory.php
new file mode 100644
index 00000000..21f11ca9
--- /dev/null
+++ b/app/Core/Plugin/Directory.php
@@ -0,0 +1,56 @@
+<?php
+
+namespace Kanboard\Core\Plugin;
+
+use Kanboard\Core\Base as BaseCore;
+
+/**
+ * Class Directory
+ *
+ * @package Kanboard\Core\Plugin
+ * @author Frederic Guillot
+ */
+class Directory extends BaseCore
+{
+ /**
+ * Get all plugins available
+ *
+ * @access public
+ * @param string $url
+ * @return array
+ */
+ public function getAvailablePlugins($url = PLUGIN_API_URL)
+ {
+ $plugins = $this->httpClient->getJson($url);
+ $plugins = array_filter($plugins, array($this, 'isCompatible'));
+ $plugins = array_filter($plugins, array($this, 'isInstallable'));
+ return $plugins;
+ }
+
+ /**
+ * Filter plugins
+ *
+ * @param array $plugin
+ * @param string $appVersion
+ * @return bool
+ */
+ public function isCompatible(array $plugin, $appVersion = APP_VERSION)
+ {
+ if (strpos($appVersion, 'master') !== false) {
+ return true;
+ }
+
+ return $plugin['compatible_version'] === $appVersion;
+ }
+
+ /**
+ * Filter plugins
+ *
+ * @param array $plugin
+ * @return bool
+ */
+ public function isInstallable(array $plugin)
+ {
+ return $plugin['remote_install'];
+ }
+}
diff --git a/app/Core/Queue/JobHandler.php b/app/Core/Queue/JobHandler.php
new file mode 100644
index 00000000..a2c4a2c7
--- /dev/null
+++ b/app/Core/Queue/JobHandler.php
@@ -0,0 +1,50 @@
+<?php
+
+namespace Kanboard\Core\Queue;
+
+use Kanboard\Core\Base;
+use Kanboard\Job\BaseJob;
+use SimpleQueue\Job;
+
+/**
+ * Class JobHandler
+ *
+ * @package Kanboard\Core\Queue
+ * @author Frederic Guillot
+ */
+class JobHandler extends Base
+{
+ /**
+ * Serialize a job
+ *
+ * @access public
+ * @param BaseJob $job
+ * @return Job
+ */
+ public function serializeJob(BaseJob $job)
+ {
+ return new Job(array(
+ 'class' => get_class($job),
+ 'params' => $job->getJobParams(),
+ ));
+ }
+
+ /**
+ * Execute a job
+ *
+ * @access public
+ * @param Job $job
+ */
+ public function executeJob(Job $job)
+ {
+ $payload = $job->getBody();
+ $className = $payload['class'];
+
+ if (DEBUG) {
+ $this->logger->debug(__METHOD__.' Received job => '.$className);
+ }
+
+ $worker = new $className($this->container);
+ call_user_func_array(array($worker, 'execute'), $payload['params']);
+ }
+}
diff --git a/app/Core/Queue/QueueManager.php b/app/Core/Queue/QueueManager.php
new file mode 100644
index 00000000..f34cb220
--- /dev/null
+++ b/app/Core/Queue/QueueManager.php
@@ -0,0 +1,71 @@
+<?php
+
+namespace Kanboard\Core\Queue;
+
+use Kanboard\Core\Base;
+use Kanboard\Job\BaseJob;
+use LogicException;
+use SimpleQueue\Queue;
+
+/**
+ * Class QueueManager
+ *
+ * @package Kanboard\Core\Queue
+ * @author Frederic Guillot
+ */
+class QueueManager extends Base
+{
+ /**
+ * @var Queue
+ */
+ protected $queue = null;
+
+ /**
+ * Set queue driver
+ *
+ * @access public
+ * @param Queue $queue
+ * @return $this
+ */
+ public function setQueue(Queue $queue)
+ {
+ $this->queue = $queue;
+ return $this;
+ }
+
+ /**
+ * Send a new job to the queue
+ *
+ * @access public
+ * @param BaseJob $job
+ * @return $this
+ */
+ public function push(BaseJob $job)
+ {
+ if ($this->queue !== null) {
+ $this->queue->push(JobHandler::getInstance($this->container)->serializeJob($job));
+ } else {
+ call_user_func_array(array($job, 'execute'), $job->getJobParams());
+ }
+
+ return $this;
+ }
+
+ /**
+ * Wait for new jobs
+ *
+ * @access public
+ * @throws LogicException
+ */
+ public function listen()
+ {
+ if ($this->queue === null) {
+ throw new LogicException('No Queue Driver defined!');
+ }
+
+ while ($job = $this->queue->pull()) {
+ JobHandler::getInstance($this->container)->executeJob($job);
+ $this->queue->completed($job);
+ }
+ }
+}
diff --git a/app/Job/BaseJob.php b/app/Job/BaseJob.php
new file mode 100644
index 00000000..60522ac6
--- /dev/null
+++ b/app/Job/BaseJob.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace Kanboard\Job;
+
+use Kanboard\Core\Base;
+
+/**
+ * Class BaseJob
+ *
+ * @package Kanboard\Job
+ * @author Frederic Guillot
+ */
+abstract class BaseJob extends Base
+{
+ /**
+ * Job parameters
+ *
+ * @access protected
+ * @var array
+ */
+ protected $jobParams = array();
+
+ /**
+ * Get job parameters
+ *
+ * @access public
+ * @return array
+ */
+ public function getJobParams()
+ {
+ return $this->jobParams;
+ }
+}
diff --git a/app/Job/EmailJob.php b/app/Job/EmailJob.php
new file mode 100644
index 00000000..9293a1d4
--- /dev/null
+++ b/app/Job/EmailJob.php
@@ -0,0 +1,54 @@
+<?php
+
+namespace Kanboard\Job;
+
+/**
+ * Class EmailJob
+ *
+ * @package Kanboard\Job
+ * @author Frederic Guillot
+ */
+class EmailJob extends BaseJob
+{
+ /**
+ * Set job parameters
+ *
+ * @access public
+ * @param string $email
+ * @param string $name
+ * @param string $subject
+ * @param string $html
+ * @param string $author
+ * @return $this
+ */
+ public function withParams($email, $name, $subject, $html, $author)
+ {
+ $this->jobParams = array($email, $name, $subject, $html, $author);
+ return $this;
+ }
+
+ /**
+ * Execute job
+ *
+ * @access public
+ * @param string $email
+ * @param string $name
+ * @param string $subject
+ * @param string $html
+ * @param string $author
+ */
+ public function execute($email, $name, $subject, $html, $author)
+ {
+ $this->logger->debug(__METHOD__.' Sending email to '.$email.' via '.MAIL_TRANSPORT);
+ $startTime = microtime(true);
+
+ $this->emailClient
+ ->getTransport(MAIL_TRANSPORT)
+ ->sendEmail($email, $name, $subject, $html, $author)
+ ;
+
+ if (DEBUG) {
+ $this->logger->debug('Email sent in '.round(microtime(true) - $startTime, 6).' seconds');
+ }
+ }
+}
diff --git a/app/Job/NotificationJob.php b/app/Job/NotificationJob.php
new file mode 100644
index 00000000..d5fce222
--- /dev/null
+++ b/app/Job/NotificationJob.php
@@ -0,0 +1,85 @@
+<?php
+
+namespace Kanboard\Job;
+
+use Kanboard\Event\GenericEvent;
+
+/**
+ * Class NotificationJob
+ *
+ * @package Kanboard\Job
+ * @author Frederic Guillot
+ */
+class NotificationJob extends BaseJob
+{
+ /**
+ * Set job parameters
+ *
+ * @param GenericEvent $event
+ * @param string $eventName
+ * @param string $eventObjectName
+ * @return $this
+ */
+ public function withParams(GenericEvent $event, $eventName, $eventObjectName)
+ {
+ $this->jobParams = array($event->getAll(), $eventName, $eventObjectName);
+ return $this;
+ }
+
+ /**
+ * Execute job
+ *
+ * @param array $event
+ * @param string $eventName
+ * @param string $eventObjectName
+ */
+ public function execute(array $event, $eventName, $eventObjectName)
+ {
+ $eventData = $this->getEventData($event, $eventObjectName);
+
+ if (! empty($eventData)) {
+ if (! empty($event['mention'])) {
+ $this->userNotification->sendUserNotification($event['mention'], $eventName, $eventData);
+ } else {
+ $this->userNotification->sendNotifications($eventName, $eventData);
+ $this->projectNotification->sendNotifications($eventData['task']['project_id'], $eventName, $eventData);
+ }
+ }
+ }
+
+ /**
+ * Get event data
+ *
+ * @param array $event
+ * @param string $eventObjectName
+ * @return array
+ */
+ public function getEventData(array $event, $eventObjectName)
+ {
+ $values = array();
+
+ if (! empty($event['changes'])) {
+ $values['changes'] = $event['changes'];
+ }
+
+ switch ($eventObjectName) {
+ case 'Kanboard\Event\TaskEvent':
+ $values['task'] = $this->taskFinder->getDetails($event['task_id']);
+ break;
+ case 'Kanboard\Event\SubtaskEvent':
+ $values['subtask'] = $this->subtask->getById($event['id'], true);
+ $values['task'] = $this->taskFinder->getDetails($values['subtask']['task_id']);
+ break;
+ case 'Kanboard\Event\FileEvent':
+ $values['file'] = $event;
+ $values['task'] = $this->taskFinder->getDetails($values['file']['task_id']);
+ break;
+ case 'Kanboard\Event\CommentEvent':
+ $values['comment'] = $this->comment->getById($event['id']);
+ $values['task'] = $this->taskFinder->getDetails($values['comment']['task_id']);
+ break;
+ }
+
+ return $values;
+ }
+}
diff --git a/app/Job/ProjectMetricJob.php b/app/Job/ProjectMetricJob.php
new file mode 100644
index 00000000..2c3e589c
--- /dev/null
+++ b/app/Job/ProjectMetricJob.php
@@ -0,0 +1,40 @@
+<?php
+
+namespace Kanboard\Job;
+
+/**
+ * Class ProjectMetricJob
+ *
+ * @package Kanboard\Job
+ * @author Frederic Guillot
+ */
+class ProjectMetricJob extends BaseJob
+{
+ /**
+ * Set job parameters
+ *
+ * @access public
+ * @param integer $projectId
+ * @return $this
+ */
+ public function withParams($projectId)
+ {
+ $this->jobParams = array($projectId);
+ return $this;
+ }
+
+ /**
+ * Execute job
+ *
+ * @access public
+ * @param integer $projectId
+ */
+ public function execute($projectId)
+ {
+ $this->logger->debug(__METHOD__.' Run project metrics calculation');
+ $now = date('Y-m-d');
+
+ $this->projectDailyColumnStats->updateTotals($projectId, $now);
+ $this->projectDailyStats->updateTotals($projectId, $now);
+ }
+}
diff --git a/app/Model/UserNotification.php b/app/Model/UserNotification.php
index fcd1761b..6882e671 100644
--- a/app/Model/UserNotification.php
+++ b/app/Model/UserNotification.php
@@ -162,8 +162,9 @@ class UserNotification extends Base
->table(ProjectUserRole::TABLE)
->columns(User::TABLE.'.id', User::TABLE.'.username', User::TABLE.'.name', User::TABLE.'.email', User::TABLE.'.language', User::TABLE.'.notifications_filter')
->join(User::TABLE, 'id', 'user_id')
- ->eq('project_id', $project_id)
- ->eq('notifications_enabled', '1')
+ ->eq(ProjectUserRole::TABLE.'.project_id', $project_id)
+ ->eq(User::TABLE.'.notifications_enabled', '1')
+ ->eq(User::TABLE.'.is_active', 1)
->neq(User::TABLE.'.id', $exclude_user_id)
->findAll();
}
@@ -178,6 +179,7 @@ class UserNotification extends Base
->eq(ProjectGroupRole::TABLE.'.project_id', $project_id)
->eq(User::TABLE.'.notifications_enabled', '1')
->neq(User::TABLE.'.id', $exclude_user_id)
+ ->eq(User::TABLE.'.is_active', 1)
->findAll();
}
@@ -195,6 +197,7 @@ class UserNotification extends Base
->columns(User::TABLE.'.id', User::TABLE.'.username', User::TABLE.'.name', User::TABLE.'.email', User::TABLE.'.language', User::TABLE.'.notifications_filter')
->eq('notifications_enabled', '1')
->neq(User::TABLE.'.id', $exclude_user_id)
+ ->eq(User::TABLE.'.is_active', 1)
->findAll();
}
}
diff --git a/app/ServiceProvider/ActionProvider.php b/app/ServiceProvider/ActionProvider.php
index 7c92f3ce..34202052 100644
--- a/app/ServiceProvider/ActionProvider.php
+++ b/app/ServiceProvider/ActionProvider.php
@@ -36,7 +36,7 @@ use Kanboard\Action\TaskCloseNoActivity;
/**
* Action Provider
*
- * @package serviceProvider
+ * @package Kanboard\ServiceProvider
* @author Frederic Guillot
*/
class ActionProvider implements ServiceProviderInterface
diff --git a/app/ServiceProvider/AuthenticationProvider.php b/app/ServiceProvider/AuthenticationProvider.php
index 6b037940..d4f130e2 100644
--- a/app/ServiceProvider/AuthenticationProvider.php
+++ b/app/ServiceProvider/AuthenticationProvider.php
@@ -17,7 +17,7 @@ use Kanboard\Auth\ReverseProxyAuth;
/**
* Authentication Provider
*
- * @package serviceProvider
+ * @package Kanboard\ServiceProvider
* @author Frederic Guillot
*/
class AuthenticationProvider implements ServiceProviderInterface
diff --git a/app/ServiceProvider/AvatarProvider.php b/app/ServiceProvider/AvatarProvider.php
index aac4fcab..d17985ed 100644
--- a/app/ServiceProvider/AvatarProvider.php
+++ b/app/ServiceProvider/AvatarProvider.php
@@ -12,7 +12,7 @@ use Kanboard\User\Avatar\LetterAvatarProvider;
/**
* Avatar Provider
*
- * @package serviceProvider
+ * @package Kanboard\ServiceProvider
* @author Frederic Guillot
*/
class AvatarProvider implements ServiceProviderInterface
diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php
index 31e3a20b..154b921f 100644
--- a/app/ServiceProvider/ClassProvider.php
+++ b/app/ServiceProvider/ClassProvider.php
@@ -11,6 +11,12 @@ use Kanboard\Core\Http\OAuth2;
use Kanboard\Core\Tool;
use Kanboard\Core\Http\Client as HttpClient;
+/**
+ * Class ClassProvider
+ *
+ * @package Kanboard\ServiceProvider
+ * @author Frederic Guillot
+ */
class ClassProvider implements ServiceProviderInterface
{
private $classes = array(
diff --git a/app/ServiceProvider/DatabaseProvider.php b/app/ServiceProvider/DatabaseProvider.php
index c0dcd366..a3f57457 100644
--- a/app/ServiceProvider/DatabaseProvider.php
+++ b/app/ServiceProvider/DatabaseProvider.php
@@ -8,6 +8,12 @@ use Pimple\Container;
use Pimple\ServiceProviderInterface;
use PicoDb\Database;
+/**
+ * Class DatabaseProvider
+ *
+ * @package Kanboard\ServiceProvider
+ * @author Frederic Guillot
+ */
class DatabaseProvider implements ServiceProviderInterface
{
/**
diff --git a/app/ServiceProvider/EventDispatcherProvider.php b/app/ServiceProvider/EventDispatcherProvider.php
index 6b3dc098..57543fe4 100644
--- a/app/ServiceProvider/EventDispatcherProvider.php
+++ b/app/ServiceProvider/EventDispatcherProvider.php
@@ -15,6 +15,12 @@ use Kanboard\Subscriber\SubtaskTimeTrackingSubscriber;
use Kanboard\Subscriber\TransitionSubscriber;
use Kanboard\Subscriber\RecurringTaskSubscriber;
+/**
+ * Class EventDispatcherProvider
+ *
+ * @package Kanboard\ServiceProvider
+ * @author Frederic Guillot
+ */
class EventDispatcherProvider implements ServiceProviderInterface
{
public function register(Container $container)
diff --git a/app/ServiceProvider/ExternalLinkProvider.php b/app/ServiceProvider/ExternalLinkProvider.php
index 8b71ec81..2cec768d 100644
--- a/app/ServiceProvider/ExternalLinkProvider.php
+++ b/app/ServiceProvider/ExternalLinkProvider.php
@@ -12,7 +12,7 @@ use Kanboard\ExternalLink\FileLinkProvider;
/**
* External Link Provider
*
- * @package serviceProvider
+ * @package Kanboard\ServiceProvider
* @author Frederic Guillot
*/
class ExternalLinkProvider implements ServiceProviderInterface
diff --git a/app/ServiceProvider/FilterProvider.php b/app/ServiceProvider/FilterProvider.php
index f3918d77..b79c5185 100644
--- a/app/ServiceProvider/FilterProvider.php
+++ b/app/ServiceProvider/FilterProvider.php
@@ -37,7 +37,7 @@ use Pimple\ServiceProviderInterface;
/**
* Filter Provider
*
- * @package serviceProvider
+ * @package Kanboard\ServiceProvider
* @author Frederic Guillot
*/
class FilterProvider implements ServiceProviderInterface
diff --git a/app/ServiceProvider/GroupProvider.php b/app/ServiceProvider/GroupProvider.php
index b222b218..08548c73 100644
--- a/app/ServiceProvider/GroupProvider.php
+++ b/app/ServiceProvider/GroupProvider.php
@@ -11,7 +11,7 @@ use Kanboard\Group\LdapBackendGroupProvider;
/**
* Group Provider
*
- * @package serviceProvider
+ * @package Kanboard\ServiceProvider
* @author Frederic Guillot
*/
class GroupProvider implements ServiceProviderInterface
diff --git a/app/ServiceProvider/HelperProvider.php b/app/ServiceProvider/HelperProvider.php
index bf3956a2..114212d2 100644
--- a/app/ServiceProvider/HelperProvider.php
+++ b/app/ServiceProvider/HelperProvider.php
@@ -7,6 +7,12 @@ use Kanboard\Core\Template;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
+/**
+ * Class HelperProvider
+ *
+ * @package Kanboard\ServiceProvider
+ * @author Frederic Guillot
+ */
class HelperProvider implements ServiceProviderInterface
{
public function register(Container $container)
diff --git a/app/ServiceProvider/LoggingProvider.php b/app/ServiceProvider/LoggingProvider.php
index 4d6adbe4..cb6d0baa 100644
--- a/app/ServiceProvider/LoggingProvider.php
+++ b/app/ServiceProvider/LoggingProvider.php
@@ -11,6 +11,12 @@ use SimpleLogger\Stdout;
use SimpleLogger\Syslog;
use SimpleLogger\File;
+/**
+ * Class LoggingProvider
+ *
+ * @package Kanboard\ServiceProvider
+ * @author Frederic Guillot
+ */
class LoggingProvider implements ServiceProviderInterface
{
public function register(Container $container)
diff --git a/app/ServiceProvider/NotificationProvider.php b/app/ServiceProvider/NotificationProvider.php
index 83daf65d..23d1d516 100644
--- a/app/ServiceProvider/NotificationProvider.php
+++ b/app/ServiceProvider/NotificationProvider.php
@@ -12,7 +12,7 @@ use Kanboard\Notification\Web as WebNotification;
/**
* Notification Provider
*
- * @package serviceProvider
+ * @package Kanboard\ServiceProvider
* @author Frederic Guillot
*/
class NotificationProvider implements ServiceProviderInterface
diff --git a/app/ServiceProvider/PluginProvider.php b/app/ServiceProvider/PluginProvider.php
index d2f1666b..4cf57251 100644
--- a/app/ServiceProvider/PluginProvider.php
+++ b/app/ServiceProvider/PluginProvider.php
@@ -9,7 +9,7 @@ use Kanboard\Core\Plugin\Loader;
/**
* Plugin Provider
*
- * @package serviceProvider
+ * @package Kanboard\ServiceProvider
* @author Frederic Guillot
*/
class PluginProvider implements ServiceProviderInterface
diff --git a/app/ServiceProvider/QueueProvider.php b/app/ServiceProvider/QueueProvider.php
new file mode 100644
index 00000000..946b436a
--- /dev/null
+++ b/app/ServiceProvider/QueueProvider.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace Kanboard\ServiceProvider;
+
+use Kanboard\Core\Queue\QueueManager;
+use Pimple\Container;
+use Pimple\ServiceProviderInterface;
+
+/**
+ * Class QueueProvider
+ *
+ * @package Kanboard\ServiceProvider
+ * @author Frederic Guillot
+ */
+class QueueProvider implements ServiceProviderInterface
+{
+ /**
+ * Registers services on the given container.
+ *
+ * @param Container $container
+ */
+ public function register(Container $container)
+ {
+ $container['queueManager'] = new QueueManager($container);
+ return $container;
+ }
+}
diff --git a/app/ServiceProvider/RouteProvider.php b/app/ServiceProvider/RouteProvider.php
index a7338994..4a126b58 100644
--- a/app/ServiceProvider/RouteProvider.php
+++ b/app/ServiceProvider/RouteProvider.php
@@ -10,7 +10,7 @@ use Kanboard\Core\Http\Router;
/**
* Route Provider
*
- * @package serviceProvider
+ * @package Kanboard\ServiceProvider
* @author Frederic Guillot
*/
class RouteProvider implements ServiceProviderInterface
diff --git a/app/ServiceProvider/SessionProvider.php b/app/ServiceProvider/SessionProvider.php
index 0999d531..96dcac2e 100644
--- a/app/ServiceProvider/SessionProvider.php
+++ b/app/ServiceProvider/SessionProvider.php
@@ -11,7 +11,7 @@ use Kanboard\Core\Session\FlashMessage;
/**
* Session Provider
*
- * @package serviceProvider
+ * @package Kanboard\ServiceProvider
* @author Frederic Guillot
*/
class SessionProvider implements ServiceProviderInterface
diff --git a/app/Subscriber/NotificationSubscriber.php b/app/Subscriber/NotificationSubscriber.php
index 651b8a96..2a1fe6c7 100644
--- a/app/Subscriber/NotificationSubscriber.php
+++ b/app/Subscriber/NotificationSubscriber.php
@@ -3,6 +3,7 @@
namespace Kanboard\Subscriber;
use Kanboard\Event\GenericEvent;
+use Kanboard\Job\NotificationJob;
use Kanboard\Model\Task;
use Kanboard\Model\Comment;
use Kanboard\Model\Subtask;
@@ -14,67 +15,32 @@ class NotificationSubscriber extends BaseSubscriber implements EventSubscriberIn
public static function getSubscribedEvents()
{
return array(
- Task::EVENT_USER_MENTION => 'handleEvent',
- Task::EVENT_CREATE => 'handleEvent',
- Task::EVENT_UPDATE => 'handleEvent',
- Task::EVENT_CLOSE => 'handleEvent',
- Task::EVENT_OPEN => 'handleEvent',
- Task::EVENT_MOVE_COLUMN => 'handleEvent',
- Task::EVENT_MOVE_POSITION => 'handleEvent',
- Task::EVENT_MOVE_SWIMLANE => 'handleEvent',
+ Task::EVENT_USER_MENTION => 'handleEvent',
+ Task::EVENT_CREATE => 'handleEvent',
+ Task::EVENT_UPDATE => 'handleEvent',
+ Task::EVENT_CLOSE => 'handleEvent',
+ Task::EVENT_OPEN => 'handleEvent',
+ Task::EVENT_MOVE_COLUMN => 'handleEvent',
+ Task::EVENT_MOVE_POSITION => 'handleEvent',
+ Task::EVENT_MOVE_SWIMLANE => 'handleEvent',
Task::EVENT_ASSIGNEE_CHANGE => 'handleEvent',
- Subtask::EVENT_CREATE => 'handleEvent',
- Subtask::EVENT_UPDATE => 'handleEvent',
- Comment::EVENT_CREATE => 'handleEvent',
- Comment::EVENT_UPDATE => 'handleEvent',
+ Subtask::EVENT_CREATE => 'handleEvent',
+ Subtask::EVENT_UPDATE => 'handleEvent',
+ Comment::EVENT_CREATE => 'handleEvent',
+ Comment::EVENT_UPDATE => 'handleEvent',
Comment::EVENT_USER_MENTION => 'handleEvent',
- TaskFile::EVENT_CREATE => 'handleEvent',
+ TaskFile::EVENT_CREATE => 'handleEvent',
);
}
- public function handleEvent(GenericEvent $event, $event_name)
+ public function handleEvent(GenericEvent $event, $eventName)
{
- if (! $this->isExecuted($event_name)) {
- $this->logger->debug('Subscriber executed: '.__METHOD__);
- $event_data = $this->getEventData($event);
+ if (!$this->isExecuted($eventName)) {
+ $this->logger->debug('Subscriber executed: ' . __METHOD__);
- if (! empty($event_data)) {
- if (! empty($event['mention'])) {
- $this->userNotification->sendUserNotification($event['mention'], $event_name, $event_data);
- } else {
- $this->userNotification->sendNotifications($event_name, $event_data);
- $this->projectNotification->sendNotifications($event_data['task']['project_id'], $event_name, $event_data);
- }
- }
+ $this->queueManager->push(NotificationJob::getInstance($this->container)
+ ->withParams($event, $eventName, get_class($event))
+ );
}
}
-
- public function getEventData(GenericEvent $event)
- {
- $values = array();
-
- if (! empty($event['changes'])) {
- $values['changes'] = $event['changes'];
- }
-
- switch (get_class($event)) {
- case 'Kanboard\Event\TaskEvent':
- $values['task'] = $this->taskFinder->getDetails($event['task_id']);
- break;
- case 'Kanboard\Event\SubtaskEvent':
- $values['subtask'] = $this->subtask->getById($event['id'], true);
- $values['task'] = $this->taskFinder->getDetails($values['subtask']['task_id']);
- break;
- case 'Kanboard\Event\FileEvent':
- $values['file'] = $event->getAll();
- $values['task'] = $this->taskFinder->getDetails($values['file']['task_id']);
- break;
- case 'Kanboard\Event\CommentEvent':
- $values['comment'] = $this->comment->getById($event['id']);
- $values['task'] = $this->taskFinder->getDetails($values['comment']['task_id']);
- break;
- }
-
- return $values;
- }
}
diff --git a/app/Subscriber/ProjectDailySummarySubscriber.php b/app/Subscriber/ProjectDailySummarySubscriber.php
index 44138f43..982240c1 100644
--- a/app/Subscriber/ProjectDailySummarySubscriber.php
+++ b/app/Subscriber/ProjectDailySummarySubscriber.php
@@ -3,6 +3,7 @@
namespace Kanboard\Subscriber;
use Kanboard\Event\TaskEvent;
+use Kanboard\Job\ProjectMetricJob;
use Kanboard\Model\Task;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
@@ -23,8 +24,7 @@ class ProjectDailySummarySubscriber extends BaseSubscriber implements EventSubsc
{
if (isset($event['project_id']) && !$this->isExecuted()) {
$this->logger->debug('Subscriber executed: '.__METHOD__);
- $this->projectDailyColumnStats->updateTotals($event['project_id'], date('Y-m-d'));
- $this->projectDailyStats->updateTotals($event['project_id'], date('Y-m-d'));
+ $this->queueManager->push(ProjectMetricJob::getInstance($this->container)->withParams($event['project_id']));
}
}
}
diff --git a/app/common.php b/app/common.php
index fa95773b..e018aa12 100644
--- a/app/common.php
+++ b/app/common.php
@@ -45,4 +45,5 @@ $container->register(new Kanboard\ServiceProvider\ActionProvider());
$container->register(new Kanboard\ServiceProvider\ExternalLinkProvider());
$container->register(new Kanboard\ServiceProvider\AvatarProvider());
$container->register(new Kanboard\ServiceProvider\FilterProvider());
+$container->register(new Kanboard\ServiceProvider\QueueProvider());
$container->register(new Kanboard\ServiceProvider\PluginProvider());
diff --git a/composer.json b/composer.json
index df91d0c5..5cdac14a 100644
--- a/composer.json
+++ b/composer.json
@@ -30,6 +30,7 @@
"fguillot/picodb" : "1.0.11",
"fguillot/simpleLogger" : "1.0.1",
"fguillot/simple-validator" : "1.0.0",
+ "fguillot/simple-queue" : "dev-master",
"paragonie/random_compat": "@stable",
"pimple/pimple" : "~3.0",
"ramsey/array_column": "@stable",
@@ -49,6 +50,7 @@
]
},
"require-dev" : {
- "symfony/stopwatch" : "~2.6"
+ "symfony/stopwatch" : "~2.6",
+ "phpunit/phpunit": "4.8.*"
}
}
diff --git a/composer.lock b/composer.lock
index 91d88ee2..fa5b52f3 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,8 +4,8 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
- "hash": "7679ea6537bad9f8be67619d321a72f9",
- "content-hash": "ef2d3ad0af1dcad85710d537150ec151",
+ "hash": "7dce69b83d7c6e14d2260e7b63352f8c",
+ "content-hash": "39143d0a5ad67dd0394826aa1845cad7",
"packages": [
{
"name": "christian-riesen/base32",
@@ -275,6 +275,55 @@
"time": "2016-05-15 01:02:48"
},
{
+ "name": "fguillot/simple-queue",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/fguillot/simple-queue.git",
+ "reference": "ae4359e9ee3b36da646766557c9242bb6ee3dcab"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/fguillot/simple-queue/zipball/ae4359e9ee3b36da646766557c9242bb6ee3dcab",
+ "reference": "ae4359e9ee3b36da646766557c9242bb6ee3dcab",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "aws/aws-sdk-php": "~3.0",
+ "mariano/disque-php": "~2.0",
+ "pda/pheanstalk": "~3.0",
+ "php-amqplib/php-amqplib": "2.6.*",
+ "phpunit/phpunit": "5.3.*"
+ },
+ "suggest": {
+ "aws/aws-sdk-php": "Required to use the AWS SQS queue driver (~3.0).",
+ "mariano/disque-php": "Required to use the Disque queue driver (~2.0).",
+ "pda/pheanstalk": "Required to use the Beanstalk queue driver (~3.0).",
+ "php-amqplib/php-amqplib": "Required to use the RabbitMQ queue driver (2.6.*)."
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "SimpleQueue\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Frédéric Guillot"
+ }
+ ],
+ "description": "Abstraction layer for multiple queue systems",
+ "homepage": "https://github.com/fguillot/simple-queue",
+ "time": "2016-05-24 23:58:05"
+ },
+ {
"name": "fguillot/simple-validator",
"version": "1.0.0",
"source": {
@@ -747,16 +796,16 @@
},
{
"name": "symfony/polyfill-mbstring",
- "version": "v1.1.1",
+ "version": "v1.2.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
- "reference": "1289d16209491b584839022f29257ad859b8532d"
+ "reference": "dff51f72b0706335131b00a7f49606168c582594"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/1289d16209491b584839022f29257ad859b8532d",
- "reference": "1289d16209491b584839022f29257ad859b8532d",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/dff51f72b0706335131b00a7f49606168c582594",
+ "reference": "dff51f72b0706335131b00a7f49606168c582594",
"shasum": ""
},
"require": {
@@ -768,7 +817,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.1-dev"
+ "dev-master": "1.2-dev"
}
},
"autoload": {
@@ -802,11 +851,918 @@
"portable",
"shim"
],
- "time": "2016-01-20 09:13:37"
+ "time": "2016-05-18 14:26:46"
}
],
"packages-dev": [
{
+ "name": "doctrine/instantiator",
+ "version": "1.0.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/instantiator.git",
+ "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d",
+ "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3,<8.0-DEV"
+ },
+ "require-dev": {
+ "athletic/athletic": "~0.1.8",
+ "ext-pdo": "*",
+ "ext-phar": "*",
+ "phpunit/phpunit": "~4.0",
+ "squizlabs/php_codesniffer": "~2.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Marco Pivetta",
+ "email": "ocramius@gmail.com",
+ "homepage": "http://ocramius.github.com/"
+ }
+ ],
+ "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
+ "homepage": "https://github.com/doctrine/instantiator",
+ "keywords": [
+ "constructor",
+ "instantiate"
+ ],
+ "time": "2015-06-14 21:17:01"
+ },
+ {
+ "name": "phpdocumentor/reflection-docblock",
+ "version": "2.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
+ "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8",
+ "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.0"
+ },
+ "suggest": {
+ "dflydev/markdown": "~1.0",
+ "erusev/parsedown": "~1.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "phpDocumentor": [
+ "src/"
+ ]
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Mike van Riel",
+ "email": "mike.vanriel@naenius.com"
+ }
+ ],
+ "time": "2015-02-03 12:10:50"
+ },
+ {
+ "name": "phpspec/prophecy",
+ "version": "v1.6.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpspec/prophecy.git",
+ "reference": "3c91bdf81797d725b14cb62906f9a4ce44235972"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpspec/prophecy/zipball/3c91bdf81797d725b14cb62906f9a4ce44235972",
+ "reference": "3c91bdf81797d725b14cb62906f9a4ce44235972",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/instantiator": "^1.0.2",
+ "php": "^5.3|^7.0",
+ "phpdocumentor/reflection-docblock": "~2.0",
+ "sebastian/comparator": "~1.1",
+ "sebastian/recursion-context": "~1.0"
+ },
+ "require-dev": {
+ "phpspec/phpspec": "~2.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.5.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Prophecy\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Konstantin Kudryashov",
+ "email": "ever.zet@gmail.com",
+ "homepage": "http://everzet.com"
+ },
+ {
+ "name": "Marcello Duarte",
+ "email": "marcello.duarte@gmail.com"
+ }
+ ],
+ "description": "Highly opinionated mocking framework for PHP 5.3+",
+ "homepage": "https://github.com/phpspec/prophecy",
+ "keywords": [
+ "Double",
+ "Dummy",
+ "fake",
+ "mock",
+ "spy",
+ "stub"
+ ],
+ "time": "2016-02-15 07:46:21"
+ },
+ {
+ "name": "phpunit/php-code-coverage",
+ "version": "2.2.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
+ "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979",
+ "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3",
+ "phpunit/php-file-iterator": "~1.3",
+ "phpunit/php-text-template": "~1.2",
+ "phpunit/php-token-stream": "~1.3",
+ "sebastian/environment": "^1.3.2",
+ "sebastian/version": "~1.0"
+ },
+ "require-dev": {
+ "ext-xdebug": ">=2.1.4",
+ "phpunit/phpunit": "~4"
+ },
+ "suggest": {
+ "ext-dom": "*",
+ "ext-xdebug": ">=2.2.1",
+ "ext-xmlwriter": "*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.2.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sb@sebastian-bergmann.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
+ "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
+ "keywords": [
+ "coverage",
+ "testing",
+ "xunit"
+ ],
+ "time": "2015-10-06 15:47:00"
+ },
+ {
+ "name": "phpunit/php-file-iterator",
+ "version": "1.4.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
+ "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0",
+ "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.4.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sb@sebastian-bergmann.de",
+ "role": "lead"
+ }
+ ],
+ "description": "FilterIterator implementation that filters files based on a list of suffixes.",
+ "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
+ "keywords": [
+ "filesystem",
+ "iterator"
+ ],
+ "time": "2015-06-21 13:08:43"
+ },
+ {
+ "name": "phpunit/php-text-template",
+ "version": "1.2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-text-template.git",
+ "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
+ "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Simple template engine.",
+ "homepage": "https://github.com/sebastianbergmann/php-text-template/",
+ "keywords": [
+ "template"
+ ],
+ "time": "2015-06-21 13:50:34"
+ },
+ {
+ "name": "phpunit/php-timer",
+ "version": "1.0.8",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-timer.git",
+ "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260",
+ "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4|~5"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sb@sebastian-bergmann.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Utility class for timing",
+ "homepage": "https://github.com/sebastianbergmann/php-timer/",
+ "keywords": [
+ "timer"
+ ],
+ "time": "2016-05-12 18:03:57"
+ },
+ {
+ "name": "phpunit/php-token-stream",
+ "version": "1.4.8",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-token-stream.git",
+ "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da",
+ "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da",
+ "shasum": ""
+ },
+ "require": {
+ "ext-tokenizer": "*",
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.2"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.4-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Wrapper around PHP's tokenizer extension.",
+ "homepage": "https://github.com/sebastianbergmann/php-token-stream/",
+ "keywords": [
+ "tokenizer"
+ ],
+ "time": "2015-09-15 10:49:45"
+ },
+ {
+ "name": "phpunit/phpunit",
+ "version": "4.8.26",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/phpunit.git",
+ "reference": "fc1d8cd5b5de11625979125c5639347896ac2c74"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fc1d8cd5b5de11625979125c5639347896ac2c74",
+ "reference": "fc1d8cd5b5de11625979125c5639347896ac2c74",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-json": "*",
+ "ext-pcre": "*",
+ "ext-reflection": "*",
+ "ext-spl": "*",
+ "php": ">=5.3.3",
+ "phpspec/prophecy": "^1.3.1",
+ "phpunit/php-code-coverage": "~2.1",
+ "phpunit/php-file-iterator": "~1.4",
+ "phpunit/php-text-template": "~1.2",
+ "phpunit/php-timer": "^1.0.6",
+ "phpunit/phpunit-mock-objects": "~2.3",
+ "sebastian/comparator": "~1.1",
+ "sebastian/diff": "~1.2",
+ "sebastian/environment": "~1.3",
+ "sebastian/exporter": "~1.2",
+ "sebastian/global-state": "~1.0",
+ "sebastian/version": "~1.0",
+ "symfony/yaml": "~2.1|~3.0"
+ },
+ "suggest": {
+ "phpunit/php-invoker": "~1.1"
+ },
+ "bin": [
+ "phpunit"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.8.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "The PHP Unit Testing framework.",
+ "homepage": "https://phpunit.de/",
+ "keywords": [
+ "phpunit",
+ "testing",
+ "xunit"
+ ],
+ "time": "2016-05-17 03:09:28"
+ },
+ {
+ "name": "phpunit/phpunit-mock-objects",
+ "version": "2.3.8",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
+ "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983",
+ "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/instantiator": "^1.0.2",
+ "php": ">=5.3.3",
+ "phpunit/php-text-template": "~1.2",
+ "sebastian/exporter": "~1.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.4"
+ },
+ "suggest": {
+ "ext-soap": "*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.3.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sb@sebastian-bergmann.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Mock Object library for PHPUnit",
+ "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
+ "keywords": [
+ "mock",
+ "xunit"
+ ],
+ "time": "2015-10-02 06:51:40"
+ },
+ {
+ "name": "sebastian/comparator",
+ "version": "1.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/comparator.git",
+ "reference": "937efb279bd37a375bcadf584dec0726f84dbf22"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22",
+ "reference": "937efb279bd37a375bcadf584dec0726f84dbf22",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3",
+ "sebastian/diff": "~1.2",
+ "sebastian/exporter": "~1.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.4"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.2.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Jeff Welch",
+ "email": "whatthejeff@gmail.com"
+ },
+ {
+ "name": "Volker Dusch",
+ "email": "github@wallbash.com"
+ },
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@2bepublished.at"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Provides the functionality to compare PHP values for equality",
+ "homepage": "http://www.github.com/sebastianbergmann/comparator",
+ "keywords": [
+ "comparator",
+ "compare",
+ "equality"
+ ],
+ "time": "2015-07-26 15:48:44"
+ },
+ {
+ "name": "sebastian/diff",
+ "version": "1.4.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/diff.git",
+ "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e",
+ "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.8"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.4-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Kore Nordmann",
+ "email": "mail@kore-nordmann.de"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Diff implementation",
+ "homepage": "https://github.com/sebastianbergmann/diff",
+ "keywords": [
+ "diff"
+ ],
+ "time": "2015-12-08 07:14:41"
+ },
+ {
+ "name": "sebastian/environment",
+ "version": "1.3.7",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/environment.git",
+ "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/4e8f0da10ac5802913afc151413bc8c53b6c2716",
+ "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.4"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.3.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Provides functionality to handle HHVM/PHP environments",
+ "homepage": "http://www.github.com/sebastianbergmann/environment",
+ "keywords": [
+ "Xdebug",
+ "environment",
+ "hhvm"
+ ],
+ "time": "2016-05-17 03:18:57"
+ },
+ {
+ "name": "sebastian/exporter",
+ "version": "1.2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/exporter.git",
+ "reference": "7ae5513327cb536431847bcc0c10edba2701064e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/7ae5513327cb536431847bcc0c10edba2701064e",
+ "reference": "7ae5513327cb536431847bcc0c10edba2701064e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3",
+ "sebastian/recursion-context": "~1.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.4"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.2.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Jeff Welch",
+ "email": "whatthejeff@gmail.com"
+ },
+ {
+ "name": "Volker Dusch",
+ "email": "github@wallbash.com"
+ },
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@2bepublished.at"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Adam Harvey",
+ "email": "aharvey@php.net"
+ }
+ ],
+ "description": "Provides the functionality to export PHP variables for visualization",
+ "homepage": "http://www.github.com/sebastianbergmann/exporter",
+ "keywords": [
+ "export",
+ "exporter"
+ ],
+ "time": "2015-06-21 07:55:53"
+ },
+ {
+ "name": "sebastian/global-state",
+ "version": "1.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/global-state.git",
+ "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4",
+ "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.2"
+ },
+ "suggest": {
+ "ext-uopz": "*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Snapshotting of global state",
+ "homepage": "http://www.github.com/sebastianbergmann/global-state",
+ "keywords": [
+ "global state"
+ ],
+ "time": "2015-10-12 03:26:01"
+ },
+ {
+ "name": "sebastian/recursion-context",
+ "version": "1.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/recursion-context.git",
+ "reference": "913401df809e99e4f47b27cdd781f4a258d58791"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791",
+ "reference": "913401df809e99e4f47b27cdd781f4a258d58791",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.4"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Jeff Welch",
+ "email": "whatthejeff@gmail.com"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Adam Harvey",
+ "email": "aharvey@php.net"
+ }
+ ],
+ "description": "Provides functionality to recursively process PHP variables",
+ "homepage": "http://www.github.com/sebastianbergmann/recursion-context",
+ "time": "2015-11-11 19:50:13"
+ },
+ {
+ "name": "sebastian/version",
+ "version": "1.0.6",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/version.git",
+ "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
+ "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
+ "shasum": ""
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library that helps with managing the version number of Git-hosted PHP projects",
+ "homepage": "https://github.com/sebastianbergmann/version",
+ "time": "2015-06-21 13:59:46"
+ },
+ {
"name": "symfony/stopwatch",
"version": "v2.8.6",
"source": {
@@ -854,11 +1810,61 @@
"description": "Symfony Stopwatch Component",
"homepage": "https://symfony.com",
"time": "2016-03-04 07:54:35"
+ },
+ {
+ "name": "symfony/yaml",
+ "version": "v3.0.6",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/yaml.git",
+ "reference": "0047c8366744a16de7516622c5b7355336afae96"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/yaml/zipball/0047c8366744a16de7516622c5b7355336afae96",
+ "reference": "0047c8366744a16de7516622c5b7355336afae96",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.5.9"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Yaml\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Yaml Component",
+ "homepage": "https://symfony.com",
+ "time": "2016-03-04 07:55:57"
}
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {
+ "fguillot/simple-queue": 20,
"paragonie/random_compat": 0,
"ramsey/array_column": 0
},
diff --git a/kanboard b/kanboard
index 49f3fe17..0121f8dd 100755
--- a/kanboard
+++ b/kanboard
@@ -6,6 +6,7 @@ use Kanboard\Console\PluginUninstallCommand;
use Kanboard\Console\PluginUpgradeCommand;
use Kanboard\Console\ResetPasswordCommand;
use Kanboard\Console\ResetTwoFactorCommand;
+use Kanboard\Console\WorkerCommand;
use Symfony\Component\Console\Application;
use Symfony\Component\EventDispatcher\Event;
use Kanboard\Console\TaskOverdueNotificationCommand;
@@ -37,6 +38,7 @@ try {
$application->add(new LocaleComparatorCommand($container));
$application->add(new TaskTriggerCommand($container));
$application->add(new CronjobCommand($container));
+ $application->add(new WorkerCommand($container));
$application->add(new ResetPasswordCommand($container));
$application->add(new ResetTwoFactorCommand($container));
$application->add(new PluginUpgradeCommand($container));
diff --git a/tests/units/Base.php b/tests/units/Base.php
index 171f9b2b..16c34573 100644
--- a/tests/units/Base.php
+++ b/tests/units/Base.php
@@ -33,14 +33,15 @@ abstract class Base extends PHPUnit_Framework_TestCase
}
$this->container = new Pimple\Container;
- $this->container->register(new Kanboard\ServiceProvider\HelperProvider);
- $this->container->register(new Kanboard\ServiceProvider\AuthenticationProvider);
- $this->container->register(new Kanboard\ServiceProvider\DatabaseProvider);
- $this->container->register(new Kanboard\ServiceProvider\ClassProvider);
- $this->container->register(new Kanboard\ServiceProvider\NotificationProvider);
- $this->container->register(new Kanboard\ServiceProvider\RouteProvider);
- $this->container->register(new Kanboard\ServiceProvider\AvatarProvider);
- $this->container->register(new Kanboard\ServiceProvider\FilterProvider);
+ $this->container->register(new Kanboard\ServiceProvider\HelperProvider());
+ $this->container->register(new Kanboard\ServiceProvider\AuthenticationProvider());
+ $this->container->register(new Kanboard\ServiceProvider\DatabaseProvider());
+ $this->container->register(new Kanboard\ServiceProvider\ClassProvider());
+ $this->container->register(new Kanboard\ServiceProvider\NotificationProvider());
+ $this->container->register(new Kanboard\ServiceProvider\RouteProvider());
+ $this->container->register(new Kanboard\ServiceProvider\AvatarProvider());
+ $this->container->register(new Kanboard\ServiceProvider\FilterProvider());
+ $this->container->register(new Kanboard\ServiceProvider\QueueProvider());
$this->container['dispatcher'] = new TraceableEventDispatcher(
new EventDispatcher,
diff --git a/tests/units/Core/Plugin/DirectoryTest.php b/tests/units/Core/Plugin/DirectoryTest.php
new file mode 100644
index 00000000..13aef4b9
--- /dev/null
+++ b/tests/units/Core/Plugin/DirectoryTest.php
@@ -0,0 +1,44 @@
+<?php
+
+use Kanboard\Core\Plugin\Directory;
+
+require_once __DIR__.'/../../Base.php';
+
+class DirectoryTest extends Base
+{
+ public function testIsCompatible()
+ {
+ $pluginDirectory = new Directory($this->container);
+ $this->assertFalse($pluginDirectory->isCompatible(array('compatible_version' => '1.0.29'), '1.0.28'));
+ $this->assertTrue($pluginDirectory->isCompatible(array('compatible_version' => '1.0.28'), '1.0.28'));
+ $this->assertTrue($pluginDirectory->isCompatible(array('compatible_version' => '1.0.28'), 'master.1234'));
+ }
+
+ public function testGetAvailablePlugins()
+ {
+ $plugins = array(
+ array(
+ 'title' => 'Plugin A',
+ 'compatible_version' => '1.0.30',
+ 'remote_install' => true,
+ ),
+ array(
+ 'title' => 'Plugin B',
+ 'compatible_version' => '1.0.29',
+ 'remote_install' => false,
+ ),
+ );
+
+ $this->container['httpClient']
+ ->expects($this->once())
+ ->method('getJson')
+ ->with('api_url')
+ ->will($this->returnValue($plugins));
+
+ $pluginDirectory = new Directory($this->container);
+ $availablePlugins = $pluginDirectory->getAvailablePlugins('api_url');
+
+ $this->assertCount(1, $availablePlugins);
+ $this->assertEquals('Plugin A', $availablePlugins[0]['title']);
+ }
+}
diff --git a/tests/units/Model/UserNotificationTest.php b/tests/units/Model/UserNotificationTest.php
index 53034e20..42db54b4 100644
--- a/tests/units/Model/UserNotificationTest.php
+++ b/tests/units/Model/UserNotificationTest.php
@@ -109,7 +109,8 @@ class UserNotificationTest extends Base
$this->assertEquals(2, $userModel->create(array('username' => 'user1', 'email' => 'user1@here', 'notifications_enabled' => 1)));
$this->assertEquals(3, $userModel->create(array('username' => 'user2', 'email' => '', 'notifications_enabled' => 1)));
- $this->assertEquals(4, $userModel->create(array('username' => 'user3')));
+ $this->assertEquals(4, $userModel->create(array('username' => 'user3', 'email' => '', 'notifications_enabled' => 1, 'is_active' => 0)));
+ $this->assertEquals(5, $userModel->create(array('username' => 'user4')));
$this->assertEquals(1, $groupModel->create('G1'));
$this->assertEquals(2, $groupModel->create('G2'));
@@ -117,6 +118,7 @@ class UserNotificationTest extends Base
$this->assertTrue($groupMemberModel->addUser(1, 2));
$this->assertTrue($groupMemberModel->addUser(1, 3));
$this->assertTrue($groupMemberModel->addUser(1, 4));
+ $this->assertTrue($groupMemberModel->addUser(1, 5));
$this->assertTrue($groupMemberModel->addUser(2, 2));
$this->assertTrue($groupMemberModel->addUser(2, 3));
@@ -143,26 +145,30 @@ class UserNotificationTest extends Base
$this->assertEquals(1, $p->create(array('name' => 'UnitTest1')));
// Email + Notifications enabled
- $this->assertNotFalse($u->create(array('username' => 'user1', 'email' => 'user1@here', 'notifications_enabled' => 1)));
+ $this->assertEquals(2, $u->create(array('username' => 'user1', 'email' => 'user1@here', 'notifications_enabled' => 1)));
// No email + Notifications enabled
- $this->assertNotFalse($u->create(array('username' => 'user2', 'email' => '', 'notifications_enabled' => 1)));
+ $this->assertEquals(3, $u->create(array('username' => 'user2', 'email' => '', 'notifications_enabled' => 1)));
// Email + Notifications enabled
- $this->assertNotFalse($u->create(array('username' => 'user3', 'email' => 'user3@here', 'notifications_enabled' => 1)));
+ $this->assertEquals(4, $u->create(array('username' => 'user3', 'email' => 'user3@here', 'notifications_enabled' => 1)));
+
+ // User disabled
+ $this->assertEquals(5, $u->create(array('username' => 'user4', 'email' => 'user3@here', 'notifications_enabled' => 1, 'is_active' => 0)));
// No email + notifications disabled
- $this->assertNotFalse($u->create(array('username' => 'user4')));
+ $this->assertEquals(6, $u->create(array('username' => 'user5')));
// Nobody is member of any projects
$this->assertEmpty($pp->getUsers(1));
$this->assertEmpty($n->getUsersWithNotificationEnabled(1));
// We allow all users to be member of our projects
- $this->assertTrue($pp->addUser(1, 1, Role::PROJECT_MEMBER));
$this->assertTrue($pp->addUser(1, 2, Role::PROJECT_MEMBER));
$this->assertTrue($pp->addUser(1, 3, Role::PROJECT_MEMBER));
$this->assertTrue($pp->addUser(1, 4, Role::PROJECT_MEMBER));
+ $this->assertTrue($pp->addUser(1, 5, Role::PROJECT_MEMBER));
+ $this->assertTrue($pp->addUser(1, 6, Role::PROJECT_MEMBER));
$this->assertNotEmpty($pp->getUsers(1));
$users = $n->getUsersWithNotificationEnabled(1);
@@ -185,16 +191,19 @@ class UserNotificationTest extends Base
$this->assertTrue($pp->isEverybodyAllowed(1));
// Email + Notifications enabled
- $this->assertNotFalse($u->create(array('username' => 'user1', 'email' => 'user1@here', 'notifications_enabled' => 1)));
+ $this->assertEquals(2, $u->create(array('username' => 'user1', 'email' => 'user1@here', 'notifications_enabled' => 1)));
// No email + Notifications enabled
- $this->assertNotFalse($u->create(array('username' => 'user2', 'email' => '', 'notifications_enabled' => 1)));
+ $this->assertEquals(3, $u->create(array('username' => 'user2', 'email' => '', 'notifications_enabled' => 1)));
// Email + Notifications enabled
- $this->assertNotFalse($u->create(array('username' => 'user3', 'email' => 'user3@here', 'notifications_enabled' => 1)));
+ $this->assertEquals(4, $u->create(array('username' => 'user3', 'email' => 'user3@here', 'notifications_enabled' => 1)));
+
+ // User disabled
+ $this->assertEquals(5, $u->create(array('username' => 'user4', 'email' => 'user3@here', 'notifications_enabled' => 1, 'is_active' => 0)));
// No email + notifications disabled
- $this->assertNotFalse($u->create(array('username' => 'user4')));
+ $this->assertEquals(6, $u->create(array('username' => 'user5')));
$users = $n->getUsersWithNotificationEnabled(1);