diff options
32 files changed, 525 insertions, 62 deletions
diff --git a/README.markdown b/README.markdown index 47a0bb38..c003b110 100644 --- a/README.markdown +++ b/README.markdown @@ -110,6 +110,7 @@ Documentation - [Github webhooks](docs/github-webhooks.markdown) - [Gitlab webhooks](docs/gitlab-webhooks.markdown) - [Hipchat](docs/hipchat.markdown) +- [Jabber](docs/jabber.markdown) - [Mailgun](docs/mailgun.markdown) - [Sendgrid](docs/sendgrid.markdown) - [Slack](docs/slack.markdown) diff --git a/app/Controller/Config.php b/app/Controller/Config.php index 3c884191..c17b9f64 100644 --- a/app/Controller/Config.php +++ b/app/Controller/Config.php @@ -44,7 +44,7 @@ class Config extends Base $values += array('subtask_restriction' => 0, 'subtask_time_tracking' => 0, 'subtask_forecast' => 0); } else if ($redirect === 'integrations') { - $values += array('integration_slack_webhook' => 0, 'integration_hipchat' => 0, 'integration_gravatar' => 0); + $values += array('integration_slack_webhook' => 0, 'integration_hipchat' => 0, 'integration_gravatar' => 0, 'integration_jabber' => 0); } if ($this->config->save($values)) { diff --git a/app/Controller/Project.php b/app/Controller/Project.php index 185c55be..3015ecc0 100644 --- a/app/Controller/Project.php +++ b/app/Controller/Project.php @@ -97,7 +97,7 @@ class Project extends Base if ($this->request->isPost()) { $params = $this->request->getValues(); - $params += array('hipchat' => 0, 'slack' => 0); + $params += array('hipchat' => 0, 'slack' => 0, 'jabber' => 0); $this->projectIntegration->saveParameters($project['id'], $params); } diff --git a/app/Integration/Jabber.php b/app/Integration/Jabber.php new file mode 100644 index 00000000..d6917186 --- /dev/null +++ b/app/Integration/Jabber.php @@ -0,0 +1,129 @@ +<?php + +namespace Integration; + +use Exception; +use Fabiang\Xmpp\Options; +use Fabiang\Xmpp\Client; +use Fabiang\Xmpp\Protocol\Message; +use Fabiang\Xmpp\Protocol\Presence; + +/** + * Jabber + * + * @package integration + * @author Frederic Guillot + */ +class Jabber extends Base +{ + /** + * Return true if Jabber is enabled for this project or globally + * + * @access public + * @param integer $project_id + * @return boolean + */ + public function isActivated($project_id) + { + return $this->config->get('integration_jabber') == 1 || $this->projectIntegration->hasValue($project_id, 'jabber', 1); + } + + /** + * Get connection parameters + * + * @access public + * @param integer $project_id + * @return array + */ + public function getParameters($project_id) + { + if ($this->config->get('integration_jabber') == 1) { + return array( + 'server' => $this->config->get('integration_jabber_server'), + 'domain' => $this->config->get('integration_jabber_domain'), + 'username' => $this->config->get('integration_jabber_username'), + 'password' => $this->config->get('integration_jabber_password'), + 'nickname' => $this->config->get('integration_jabber_nickname'), + 'room' => $this->config->get('integration_jabber_room'), + ); + } + + $options = $this->projectIntegration->getParameters($project_id); + + return array( + 'server' => $options['jabber_server'], + 'domain' => $options['jabber_domain'], + 'username' => $options['jabber_username'], + 'password' => $options['jabber_password'], + 'nickname' => $options['jabber_nickname'], + 'room' => $options['jabber_room'], + ); + } + + /** + * Build and send the message + * + * @access public + * @param integer $project_id Project id + * @param integer $task_id Task id + * @param string $event_name Event name + * @param array $event Event data + */ + public function notify($project_id, $task_id, $event_name, array $event) + { + if ($this->isActivated($project_id)) { + + $project = $this->project->getbyId($project_id); + + $event['event_name'] = $event_name; + $event['author'] = $this->user->getFullname($this->session['user']); + + $payload = '['.$project['name'].'] '.str_replace('"', '"', $this->projectActivity->getTitle($event)).(isset($event['task']['title']) ? ' ('.$event['task']['title'].')' : ''); + + if ($this->config->get('application_url')) { + $payload .= ' '.$this->config->get('application_url'); + $payload .= $this->helper->url('task', 'show', array('task_id' => $task_id, 'project_id' => $project_id)); + } + + $this->sendMessage($project_id, $payload); + } + } + + /** + * Send message to the XMPP server + * + * @access public + * @param integer $project_id + * @param string $payload + */ + public function sendMessage($project_id, $payload) + { + try { + + $params = $this->getParameters($project_id); + + $options = new Options($params['server']); + $options->setUsername($params['username']); + $options->setPassword($params['password']); + $options->setTo($params['domain']); + + $client = new Client($options); + + $channel = new Presence; + $channel->setTo($params['room'])->setNickName($params['nickname']); + $client->send($channel); + + $message = new Message; + $message->setMessage($payload) + ->setTo($params['room']) + ->setType(Message::TYPE_GROUPCHAT); + + $client->send($message); + + $client->disconnect(); + } + catch (Exception $e) { + $this->container['logger']->error('Jabber error: '.$e->getMessage()); + } + } +} diff --git a/app/Locale/da_DK/translations.php b/app/Locale/da_DK/translations.php index 20994881..36d6eb9f 100644 --- a/app/Locale/da_DK/translations.php +++ b/app/Locale/da_DK/translations.php @@ -900,4 +900,12 @@ return array( // 'When task is moved from first column' => '', // 'When task is moved to last column' => '', // 'Year(s)' => '', + // 'Jabber (XMPP)' => '', + // 'Send notifications to Jabber' => '', + // 'XMPP server address' => '', + // 'Jabber domain' => '', + // 'Jabber nickname' => '', + // 'Multi-user chat room' => '', + // 'Help on Jabber integration' => '', + // 'The server address must use this format: "tcp://hostname:5222"' => '', ); diff --git a/app/Locale/de_DE/translations.php b/app/Locale/de_DE/translations.php index 6b89433c..ee91a3d2 100644 --- a/app/Locale/de_DE/translations.php +++ b/app/Locale/de_DE/translations.php @@ -900,4 +900,12 @@ return array( // 'When task is moved from first column' => '', // 'When task is moved to last column' => '', // 'Year(s)' => '', + // 'Jabber (XMPP)' => '', + // 'Send notifications to Jabber' => '', + // 'XMPP server address' => '', + // 'Jabber domain' => '', + // 'Jabber nickname' => '', + // 'Multi-user chat room' => '', + // 'Help on Jabber integration' => '', + // 'The server address must use this format: "tcp://hostname:5222"' => '', ); diff --git a/app/Locale/es_ES/translations.php b/app/Locale/es_ES/translations.php index 8eff2428..a9d8dde7 100644 --- a/app/Locale/es_ES/translations.php +++ b/app/Locale/es_ES/translations.php @@ -900,4 +900,12 @@ return array( // 'When task is moved from first column' => '', // 'When task is moved to last column' => '', // 'Year(s)' => '', + // 'Jabber (XMPP)' => '', + // 'Send notifications to Jabber' => '', + // 'XMPP server address' => '', + // 'Jabber domain' => '', + // 'Jabber nickname' => '', + // 'Multi-user chat room' => '', + // 'Help on Jabber integration' => '', + // 'The server address must use this format: "tcp://hostname:5222"' => '', ); diff --git a/app/Locale/fi_FI/translations.php b/app/Locale/fi_FI/translations.php index 9ce8b2b6..b975d664 100644 --- a/app/Locale/fi_FI/translations.php +++ b/app/Locale/fi_FI/translations.php @@ -900,4 +900,12 @@ return array( // 'When task is moved from first column' => '', // 'When task is moved to last column' => '', // 'Year(s)' => '', + // 'Jabber (XMPP)' => '', + // 'Send notifications to Jabber' => '', + // 'XMPP server address' => '', + // 'Jabber domain' => '', + // 'Jabber nickname' => '', + // 'Multi-user chat room' => '', + // 'Help on Jabber integration' => '', + // 'The server address must use this format: "tcp://hostname:5222"' => '', ); diff --git a/app/Locale/fr_FR/translations.php b/app/Locale/fr_FR/translations.php index b7436323..03bb59f5 100644 --- a/app/Locale/fr_FR/translations.php +++ b/app/Locale/fr_FR/translations.php @@ -902,4 +902,12 @@ return array( 'When task is moved from first column' => 'Lorsque la tâche est déplacée en dehors de la première colonne', 'When task is moved to last column' => 'Lorsque la tâche est déplacée dans la dernière colonne', 'Year(s)' => 'Année(s)', + 'Jabber (XMPP)' => 'Jabber (XMPP)', + 'Send notifications to Jabber' => 'Envoyer les notifications vers Jabber', + 'XMPP server address' => 'Adresse du serveur XMPP', + 'Jabber domain' => 'Nom de domaine Jabber', + 'Jabber nickname' => 'Pseudonyme Jabber', + 'Multi-user chat room' => 'Salon de discussion multi-utilisateurs', + 'Help on Jabber integration' => 'Aide sur l\'intégration avec Jabber', + 'The server address must use this format: "tcp://hostname:5222"' => 'L\'adresse du serveur doit utiliser le format suivant : « tcp://hostname:5222 »', ); diff --git a/app/Locale/hu_HU/translations.php b/app/Locale/hu_HU/translations.php index b0a10f89..ceae14bd 100644 --- a/app/Locale/hu_HU/translations.php +++ b/app/Locale/hu_HU/translations.php @@ -900,4 +900,12 @@ return array( // 'When task is moved from first column' => '', // 'When task is moved to last column' => '', // 'Year(s)' => '', + // 'Jabber (XMPP)' => '', + // 'Send notifications to Jabber' => '', + // 'XMPP server address' => '', + // 'Jabber domain' => '', + // 'Jabber nickname' => '', + // 'Multi-user chat room' => '', + // 'Help on Jabber integration' => '', + // 'The server address must use this format: "tcp://hostname:5222"' => '', ); diff --git a/app/Locale/it_IT/translations.php b/app/Locale/it_IT/translations.php index fb5293eb..a3b5d3a1 100644 --- a/app/Locale/it_IT/translations.php +++ b/app/Locale/it_IT/translations.php @@ -900,4 +900,12 @@ return array( // 'When task is moved from first column' => '', // 'When task is moved to last column' => '', // 'Year(s)' => '', + // 'Jabber (XMPP)' => '', + // 'Send notifications to Jabber' => '', + // 'XMPP server address' => '', + // 'Jabber domain' => '', + // 'Jabber nickname' => '', + // 'Multi-user chat room' => '', + // 'Help on Jabber integration' => '', + // 'The server address must use this format: "tcp://hostname:5222"' => '', ); diff --git a/app/Locale/ja_JP/translations.php b/app/Locale/ja_JP/translations.php index 89ed3f7d..0be0c91f 100644 --- a/app/Locale/ja_JP/translations.php +++ b/app/Locale/ja_JP/translations.php @@ -900,4 +900,12 @@ return array( // 'When task is moved from first column' => '', // 'When task is moved to last column' => '', // 'Year(s)' => '', + // 'Jabber (XMPP)' => '', + // 'Send notifications to Jabber' => '', + // 'XMPP server address' => '', + // 'Jabber domain' => '', + // 'Jabber nickname' => '', + // 'Multi-user chat room' => '', + // 'Help on Jabber integration' => '', + // 'The server address must use this format: "tcp://hostname:5222"' => '', ); diff --git a/app/Locale/nl_NL/translations.php b/app/Locale/nl_NL/translations.php index 24bf8f91..c971f95c 100644 --- a/app/Locale/nl_NL/translations.php +++ b/app/Locale/nl_NL/translations.php @@ -900,4 +900,12 @@ return array( // 'When task is moved from first column' => '', // 'When task is moved to last column' => '', // 'Year(s)' => '', + // 'Jabber (XMPP)' => '', + // 'Send notifications to Jabber' => '', + // 'XMPP server address' => '', + // 'Jabber domain' => '', + // 'Jabber nickname' => '', + // 'Multi-user chat room' => '', + // 'Help on Jabber integration' => '', + // 'The server address must use this format: "tcp://hostname:5222"' => '', ); diff --git a/app/Locale/pl_PL/translations.php b/app/Locale/pl_PL/translations.php index 6370830a..5f035b5d 100644 --- a/app/Locale/pl_PL/translations.php +++ b/app/Locale/pl_PL/translations.php @@ -900,4 +900,12 @@ return array( // 'When task is moved from first column' => '', // 'When task is moved to last column' => '', // 'Year(s)' => '', + // 'Jabber (XMPP)' => '', + // 'Send notifications to Jabber' => '', + // 'XMPP server address' => '', + // 'Jabber domain' => '', + // 'Jabber nickname' => '', + // 'Multi-user chat room' => '', + // 'Help on Jabber integration' => '', + // 'The server address must use this format: "tcp://hostname:5222"' => '', ); diff --git a/app/Locale/pt_BR/translations.php b/app/Locale/pt_BR/translations.php index bc579c04..acf5a6be 100644 --- a/app/Locale/pt_BR/translations.php +++ b/app/Locale/pt_BR/translations.php @@ -900,4 +900,12 @@ return array( // 'When task is moved from first column' => '', // 'When task is moved to last column' => '', // 'Year(s)' => '', + // 'Jabber (XMPP)' => '', + // 'Send notifications to Jabber' => '', + // 'XMPP server address' => '', + // 'Jabber domain' => '', + // 'Jabber nickname' => '', + // 'Multi-user chat room' => '', + // 'Help on Jabber integration' => '', + // 'The server address must use this format: "tcp://hostname:5222"' => '', ); diff --git a/app/Locale/ru_RU/translations.php b/app/Locale/ru_RU/translations.php index 6e688406..37d5c50f 100644 --- a/app/Locale/ru_RU/translations.php +++ b/app/Locale/ru_RU/translations.php @@ -900,4 +900,12 @@ return array( // 'When task is moved from first column' => '', // 'When task is moved to last column' => '', // 'Year(s)' => '', + // 'Jabber (XMPP)' => '', + // 'Send notifications to Jabber' => '', + // 'XMPP server address' => '', + // 'Jabber domain' => '', + // 'Jabber nickname' => '', + // 'Multi-user chat room' => '', + // 'Help on Jabber integration' => '', + // 'The server address must use this format: "tcp://hostname:5222"' => '', ); diff --git a/app/Locale/sr_Latn_RS/translations.php b/app/Locale/sr_Latn_RS/translations.php index e7e624f9..eec57454 100644 --- a/app/Locale/sr_Latn_RS/translations.php +++ b/app/Locale/sr_Latn_RS/translations.php @@ -900,4 +900,12 @@ return array( // 'When task is moved from first column' => '', // 'When task is moved to last column' => '', // 'Year(s)' => '', + // 'Jabber (XMPP)' => '', + // 'Send notifications to Jabber' => '', + // 'XMPP server address' => '', + // 'Jabber domain' => '', + // 'Jabber nickname' => '', + // 'Multi-user chat room' => '', + // 'Help on Jabber integration' => '', + // 'The server address must use this format: "tcp://hostname:5222"' => '', ); diff --git a/app/Locale/sv_SE/translations.php b/app/Locale/sv_SE/translations.php index d756c75d..28addb8c 100644 --- a/app/Locale/sv_SE/translations.php +++ b/app/Locale/sv_SE/translations.php @@ -900,4 +900,12 @@ return array( // 'When task is moved from first column' => '', // 'When task is moved to last column' => '', // 'Year(s)' => '', + // 'Jabber (XMPP)' => '', + // 'Send notifications to Jabber' => '', + // 'XMPP server address' => '', + // 'Jabber domain' => '', + // 'Jabber nickname' => '', + // 'Multi-user chat room' => '', + // 'Help on Jabber integration' => '', + // 'The server address must use this format: "tcp://hostname:5222"' => '', ); diff --git a/app/Locale/th_TH/translations.php b/app/Locale/th_TH/translations.php index 88007e84..6ce86433 100644 --- a/app/Locale/th_TH/translations.php +++ b/app/Locale/th_TH/translations.php @@ -900,4 +900,12 @@ return array( // 'When task is moved from first column' => '', // 'When task is moved to last column' => '', // 'Year(s)' => '', + // 'Jabber (XMPP)' => '', + // 'Send notifications to Jabber' => '', + // 'XMPP server address' => '', + // 'Jabber domain' => '', + // 'Jabber nickname' => '', + // 'Multi-user chat room' => '', + // 'Help on Jabber integration' => '', + // 'The server address must use this format: "tcp://hostname:5222"' => '', ); diff --git a/app/Locale/tr_TR/translations.php b/app/Locale/tr_TR/translations.php index e7edd856..1daeb36a 100644 --- a/app/Locale/tr_TR/translations.php +++ b/app/Locale/tr_TR/translations.php @@ -900,4 +900,12 @@ return array( // 'When task is moved from first column' => '', // 'When task is moved to last column' => '', // 'Year(s)' => '', + // 'Jabber (XMPP)' => '', + // 'Send notifications to Jabber' => '', + // 'XMPP server address' => '', + // 'Jabber domain' => '', + // 'Jabber nickname' => '', + // 'Multi-user chat room' => '', + // 'Help on Jabber integration' => '', + // 'The server address must use this format: "tcp://hostname:5222"' => '', ); diff --git a/app/Locale/zh_CN/translations.php b/app/Locale/zh_CN/translations.php index 4cac3c48..f5353b2e 100644 --- a/app/Locale/zh_CN/translations.php +++ b/app/Locale/zh_CN/translations.php @@ -900,4 +900,12 @@ return array( // 'When task is moved from first column' => '', // 'When task is moved to last column' => '', // 'Year(s)' => '', + // 'Jabber (XMPP)' => '', + // 'Send notifications to Jabber' => '', + // 'XMPP server address' => '', + // 'Jabber domain' => '', + // 'Jabber nickname' => '', + // 'Multi-user chat room' => '', + // 'Help on Jabber integration' => '', + // 'The server address must use this format: "tcp://hostname:5222"' => '', ); diff --git a/app/Schema/Mysql.php b/app/Schema/Mysql.php index 9ed23ee0..369d4826 100644 --- a/app/Schema/Mysql.php +++ b/app/Schema/Mysql.php @@ -6,7 +6,27 @@ use PDO; use Core\Security; use Model\Link; -const VERSION = 67; +const VERSION = 68; + +function version_68($pdo) +{ + $rq = $pdo->prepare('INSERT INTO settings VALUES (?, ?)'); + $rq->execute(array('integration_jabber', '0')); + $rq->execute(array('integration_jabber_server', '')); + $rq->execute(array('integration_jabber_domain', '')); + $rq->execute(array('integration_jabber_username', '')); + $rq->execute(array('integration_jabber_password', '')); + $rq->execute(array('integration_jabber_nickname', 'kanboard')); + $rq->execute(array('integration_jabber_room', '')); + + $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber INTEGER DEFAULT '0'"); + $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_server TEXT DEFAULT ''"); + $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_domain TEXT DEFAULT ''"); + $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_username TEXT DEFAULT ''"); + $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_password TEXT DEFAULT ''"); + $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_nickname TEXT DEFAULT 'kanboard'"); + $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_room TEXT DEFAULT ''"); +} function version_67($pdo) { diff --git a/app/Schema/Postgres.php b/app/Schema/Postgres.php index f1262816..1cd0ab8f 100644 --- a/app/Schema/Postgres.php +++ b/app/Schema/Postgres.php @@ -6,7 +6,27 @@ use PDO; use Core\Security; use Model\Link; -const VERSION = 48; +const VERSION = 49; + +function version_49($pdo) +{ + $rq = $pdo->prepare('INSERT INTO settings VALUES (?, ?)'); + $rq->execute(array('integration_jabber', '0')); + $rq->execute(array('integration_jabber_server', '')); + $rq->execute(array('integration_jabber_domain', '')); + $rq->execute(array('integration_jabber_username', '')); + $rq->execute(array('integration_jabber_password', '')); + $rq->execute(array('integration_jabber_nickname', 'kanboard')); + $rq->execute(array('integration_jabber_room', '')); + + $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber INTEGER DEFAULT '0'"); + $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_server TEXT DEFAULT ''"); + $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_domain TEXT DEFAULT ''"); + $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_username TEXT DEFAULT ''"); + $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_password TEXT DEFAULT ''"); + $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_nickname TEXT DEFAULT 'kanboard'"); + $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_room TEXT DEFAULT ''"); +} function version_48($pdo) { diff --git a/app/Schema/Sqlite.php b/app/Schema/Sqlite.php index 714d0e2f..830fd916 100644 --- a/app/Schema/Sqlite.php +++ b/app/Schema/Sqlite.php @@ -6,7 +6,27 @@ use Core\Security; use PDO; use Model\Link; -const VERSION = 66; +const VERSION = 67; + +function version_67($pdo) +{ + $rq = $pdo->prepare('INSERT INTO settings VALUES (?, ?)'); + $rq->execute(array('integration_jabber', '0')); + $rq->execute(array('integration_jabber_server', '')); + $rq->execute(array('integration_jabber_domain', '')); + $rq->execute(array('integration_jabber_username', '')); + $rq->execute(array('integration_jabber_password', '')); + $rq->execute(array('integration_jabber_nickname', 'kanboard')); + $rq->execute(array('integration_jabber_room', '')); + + $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber INTEGER DEFAULT '0'"); + $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_server TEXT DEFAULT ''"); + $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_domain TEXT DEFAULT ''"); + $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_username TEXT DEFAULT ''"); + $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_password TEXT DEFAULT ''"); + $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_nickname TEXT DEFAULT 'kanboard'"); + $pdo->exec("ALTER TABLE project_integrations ADD COLUMN jabber_room TEXT DEFAULT ''"); +} function version_66($pdo) { diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php index b78eb71a..c016b7eb 100644 --- a/app/ServiceProvider/ClassProvider.php +++ b/app/ServiceProvider/ClassProvider.php @@ -81,6 +81,7 @@ class ClassProvider implements ServiceProviderInterface 'SendgridWebhook', 'SlackWebhook', 'PostmarkWebhook', + 'Jabber', ) ); diff --git a/app/Subscriber/ProjectActivitySubscriber.php b/app/Subscriber/ProjectActivitySubscriber.php index 1c20a996..8988d6c1 100644 --- a/app/Subscriber/ProjectActivitySubscriber.php +++ b/app/Subscriber/ProjectActivitySubscriber.php @@ -42,31 +42,18 @@ class ProjectActivitySubscriber extends Base implements EventSubscriberInterface $values ); - $this->sendSlackNotification($event_name, $values); - $this->sendHipchatNotification($event_name, $values); + // Send notifications to third-party services + foreach (array('slackWebhook', 'hipchatWebhook', 'jabber') as $model) { + $this->$model->notify( + $values['task']['project_id'], + $values['task']['id'], + $event_name, + $values + ); + } } } - private function sendSlackNotification($event_name, array $values) - { - $this->slackWebhook->notify( - $values['task']['project_id'], - $values['task']['id'], - $event_name, - $values - ); - } - - private function sendHipchatNotification($event_name, array $values) - { - $this->hipchatWebhook->notify( - $values['task']['project_id'], - $values['task']['id'], - $event_name, - $values - ); - } - private function getValues(GenericEvent $event) { $values = array(); diff --git a/app/Template/config/integrations.php b/app/Template/config/integrations.php index bf051cfc..f9e7f537 100644 --- a/app/Template/config/integrations.php +++ b/app/Template/config/integrations.php @@ -29,6 +29,32 @@ <?= $this->formCheckbox('integration_gravatar', t('Enable Gravatar images'), 1, $values['integration_gravatar'] == 1) ?> </div> + <h3><img src="assets/img/jabber-icon.png"/> <?= t('Jabber (XMPP)') ?></h3> + <div class="listing"> + <?= $this->formCheckbox('integration_jabber', t('Send notifications to Jabber'), 1, $values['integration_jabber'] == 1) ?> + + <?= $this->formLabel(t('XMPP server address'), 'integration_jabber_server') ?> + <?= $this->formText('integration_jabber_server', $values, $errors, array('placeholder="tcp://myserver:5222"')) ?> + <p class="form-help"><?= t('The server address must use this format: "tcp://hostname:5222"') ?></p> + + <?= $this->formLabel(t('Jabber domain'), 'integration_jabber_domain') ?> + <?= $this->formText('integration_jabber_domain', $values, $errors, array('placeholder="example.com"')) ?> + + <?= $this->formLabel(t('Username'), 'integration_jabber_username') ?> + <?= $this->formText('integration_jabber_username', $values, $errors) ?> + + <?= $this->formLabel(t('Password'), 'integration_jabber_password') ?> + <?= $this->formPassword('integration_jabber_password', $values, $errors) ?> + + <?= $this->formLabel(t('Jabber nickname'), 'integration_jabber_nickname') ?> + <?= $this->formText('integration_jabber_nickname', $values, $errors) ?> + + <?= $this->formLabel(t('Multi-user chat room'), 'integration_jabber_room') ?> + <?= $this->formText('integration_jabber_room', $values, $errors, array('placeholder="myroom@conference.example.com"')) ?> + + <p class="form-help"><a href="http://kanboard.net/documentation/jabber" target="_blank"><?= t('Help on Jabber integration') ?></a></p> + </div> + <h3><img src="assets/img/hipchat-icon.png"/> <?= t('Hipchat') ?></h3> <div class="listing"> <?= $this->formCheckbox('integration_hipchat', t('Send notifications to Hipchat'), 1, $values['integration_hipchat'] == 1) ?> diff --git a/app/Template/project/integrations.php b/app/Template/project/integrations.php index da27e430..d4fab23b 100644 --- a/app/Template/project/integrations.php +++ b/app/Template/project/integrations.php @@ -27,6 +27,37 @@ </div> + <h3><img src="assets/img/jabber-icon.png"/> <?= t('Jabber (XMPP)') ?></h3> + <div class="listing"> + <?= $this->formCheckbox('jabber', t('Send notifications to Jabber'), 1, isset($values['jabber']) && $values['jabber'] == 1) ?> + + <?= $this->formLabel(t('XMPP server address'), 'jabber_server') ?> + <?= $this->formText('jabber_server', $values, $errors, array('placeholder="tcp://myserver:5222"')) ?> + <p class="form-help"><?= t('The server address must use this format: "tcp://hostname:5222"') ?></p> + + <?= $this->formLabel(t('Jabber domain'), 'jabber_domain') ?> + <?= $this->formText('jabber_domain', $values, $errors, array('placeholder="example.com"')) ?> + + <?= $this->formLabel(t('Username'), 'jabber_username') ?> + <?= $this->formText('jabber_username', $values, $errors) ?> + + <?= $this->formLabel(t('Password'), 'jabber_password') ?> + <?= $this->formPassword('jabber_password', $values, $errors) ?> + + <?= $this->formLabel(t('Jabber nickname'), 'jabber_nickname') ?> + <?= $this->formText('jabber_nickname', $values, $errors) ?> + + <?= $this->formLabel(t('Multi-user chat room'), 'jabber_room') ?> + <?= $this->formText('jabber_room', $values, $errors, array('placeholder="myroom@conference.example.com"')) ?> + + <p class="form-help"><a href="http://kanboard.net/documentation/jabber" target="_blank"><?= t('Help on Jabber integration') ?></a></p> + + <div class="form-actions"> + <input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/> + </div> + </div> + + <h3><img src="assets/img/hipchat-icon.png"/> <?= t('Hipchat') ?></h3> <div class="listing"> <?= $this->formCheckbox('hipchat', t('Send notifications to Hipchat'), 1, isset($values['hipchat']) && $values['hipchat'] == 1) ?> diff --git a/assets/img/jabber-icon.png b/assets/img/jabber-icon.png Binary files differnew file mode 100644 index 00000000..00832279 --- /dev/null +++ b/assets/img/jabber-icon.png diff --git a/composer.json b/composer.json index 9e08dfc7..766f2372 100644 --- a/composer.json +++ b/composer.json @@ -1,8 +1,8 @@ { "require" : { - "php": ">=5.3", + "php" : ">=5.3", "ext-mbstring" : "*", - "ext-gd": "*", + "ext-gd" : "*", "fguillot/simple-validator" : "dev-master", "swiftmailer/swiftmailer" : "@stable", "fguillot/json-rpc" : "0.0.1", @@ -13,8 +13,9 @@ "symfony/console" : "@stable", "symfony/event-dispatcher" : "~2.6", "fguillot/simpleLogger" : "0.0.1", - "christian-riesen/otp": "1.4", - "nickcernis/html-to-markdown": "2.2.1" + "christian-riesen/otp" : "1.4", + "nickcernis/html-to-markdown" : "2.2.1", + "fabiang/xmpp" : "0.6.1" }, "autoload" : { "psr-0" : { diff --git a/composer.lock b/composer.lock index a50f9480..d13f1aee 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "1799891b06d5a8a516a48fefd429a3ed", + "hash": "9a3f10be467a1640c3c6645ce2c318fe", "packages": [ { "name": "christian-riesen/base32", @@ -148,6 +148,64 @@ "time": "2015-01-24 13:01:47" }, { + "name": "fabiang/xmpp", + "version": "0.6.1", + "source": { + "type": "git", + "url": "https://github.com/fabiang/xmpp.git", + "reference": "47fdbe4a60ef0e726c4aaf39d6eb57afd42915c8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/fabiang/xmpp/zipball/47fdbe4a60ef0e726c4aaf39d6eb57afd42915c8", + "reference": "47fdbe4a60ef0e726c4aaf39d6eb57afd42915c8", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "psr/log": "~1.0" + }, + "require-dev": { + "behat/behat": "~2.5", + "monolog/monolog": "~1.11", + "phpunit/phpunit": "~4.3", + "satooshi/php-coveralls": "~0.6" + }, + "suggest": { + "psr/log-implementation": "Allows more advanced logging of the xmpp connection" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Fabiang\\Xmpp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Fabian Grutschus", + "email": "f.grutschus@lubyte.de", + "homepage": "http://www.lubyte.de/", + "role": "developer" + } + ], + "description": "Library for XMPP protocol (Jabber) connections", + "homepage": "https://github.com/fabiang/xmpp", + "keywords": [ + "jabber", + "xmpp" + ], + "time": "2014-11-20 08:59:24" + }, + { "name": "fguillot/json-rpc", "version": "v0.0.1", "source": { @@ -540,17 +598,17 @@ }, { "name": "symfony/console", - "version": "v2.6.6", + "version": "v2.6.7", "target-dir": "Symfony/Component/Console", "source": { "type": "git", "url": "https://github.com/symfony/Console.git", - "reference": "5b91dc4ed5eb08553f57f6df04c4730a73992667" + "reference": "ebc5679854aa24ed7d65062e9e3ab0b18a917272" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Console/zipball/5b91dc4ed5eb08553f57f6df04c4730a73992667", - "reference": "5b91dc4ed5eb08553f57f6df04c4730a73992667", + "url": "https://api.github.com/repos/symfony/Console/zipball/ebc5679854aa24ed7d65062e9e3ab0b18a917272", + "reference": "ebc5679854aa24ed7d65062e9e3ab0b18a917272", "shasum": "" }, "require": { @@ -584,31 +642,31 @@ ], "authors": [ { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, - { "name": "Fabien Potencier", "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], "description": "Symfony Console Component", - "homepage": "http://symfony.com", - "time": "2015-03-30 15:54:10" + "homepage": "https://symfony.com", + "time": "2015-05-02 15:18:45" }, { "name": "symfony/event-dispatcher", - "version": "v2.6.6", + "version": "v2.6.7", "target-dir": "Symfony/Component/EventDispatcher", "source": { "type": "git", "url": "https://github.com/symfony/EventDispatcher.git", - "reference": "70f7c8478739ad21e3deef0d977b38c77f1fb284" + "reference": "672593bc4b0043a0acf91903bb75a1c82d8f2e02" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/70f7c8478739ad21e3deef0d977b38c77f1fb284", - "reference": "70f7c8478739ad21e3deef0d977b38c77f1fb284", + "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/672593bc4b0043a0acf91903bb75a1c82d8f2e02", + "reference": "672593bc4b0043a0acf91903bb75a1c82d8f2e02", "shasum": "" }, "require": { @@ -643,33 +701,33 @@ ], "authors": [ { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, - { "name": "Fabien Potencier", "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], "description": "Symfony EventDispatcher Component", - "homepage": "http://symfony.com", - "time": "2015-03-13 17:37:22" + "homepage": "https://symfony.com", + "time": "2015-05-02 15:18:45" } ], "packages-dev": [ { "name": "symfony/stopwatch", - "version": "v2.6.6", + "version": "v2.6.7", "target-dir": "Symfony/Component/Stopwatch", "source": { "type": "git", "url": "https://github.com/symfony/Stopwatch.git", - "reference": "5f196e84b5640424a166d2ce9cca161ce1e9d912" + "reference": "b470f87c69837cb71115f1fa720388bb19b63635" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Stopwatch/zipball/5f196e84b5640424a166d2ce9cca161ce1e9d912", - "reference": "5f196e84b5640424a166d2ce9cca161ce1e9d912", + "url": "https://api.github.com/repos/symfony/Stopwatch/zipball/b470f87c69837cb71115f1fa720388bb19b63635", + "reference": "b470f87c69837cb71115f1fa720388bb19b63635", "shasum": "" }, "require": { @@ -695,17 +753,17 @@ ], "authors": [ { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, - { "name": "Fabien Potencier", "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], "description": "Symfony Stopwatch Component", - "homepage": "http://symfony.com", - "time": "2015-03-22 16:55:57" + "homepage": "https://symfony.com", + "time": "2015-05-02 15:18:45" } ], "aliases": [], diff --git a/docs/jabber.markdown b/docs/jabber.markdown new file mode 100644 index 00000000..74e81a8d --- /dev/null +++ b/docs/jabber.markdown @@ -0,0 +1,33 @@ +Jabber/XMPP integration +======================= + +You can send notifications to a Jabber room for all projects or only for specific projects. + +- To send notifications for all projects, go to **Settings > Integrations > Jabber** +- To send notifications for only some projects, go to **Project settings > Integrations > Jabber** + +Each project can send notifications to a separate room. + +## Example of notification + +Here an example with the Jabber client Adium: + +![Jabber notification](http://kanboard.net/screenshots/documentation/jabber-notification.png) + +## Configuration + +![Jabber settings](http://kanboard.net/screenshots/documentation/jabber-settings.png) + +1. Go to **Settings > Integrations > Jabber** or **Project settings > Integrations > Jabber** +2. **XMPP server address**: URL of the XMPP server, example: **tcp://172.28.128.3:5222** +3. **Jabber domain**: The **"to"** attribute of the XMPP protocol, example: **example.com** +4. **Username**: The Jabber username used by Kanboard, example: **kanboard** +5. **Password**: The Jabber password +6. **Jabber nickname**: The nickname used to connect to the room +7. **Multi-user chat room**: The address of the room, example: **demo@conference.example.com** + +Now, Kanboard events will be sent to the Jabber conference room. + +## Troubleshooting + +- All connection errors with the XMPP server are recorded in the log files `data/debug.log` or syslog |