diff options
| -rw-r--r-- | README.markdown | 3 | ||||
| -rw-r--r-- | app/Event/ProjectModificationDate.php | 3 | ||||
| -rw-r--r-- | app/Model/Project.php | 9 | ||||
| -rw-r--r-- | docs/api-json-rpc.markdown | 54 | ||||
| -rw-r--r-- | docs/automatic-actions.markdown | 8 | ||||
| -rw-r--r-- | docs/editing-projects.markdown | 8 | ||||
| -rwxr-xr-x | scripts/make-archive.sh | 24 | ||||
| -rw-r--r-- | tests/units/ProjectTest.php | 45 | ||||
| -rw-r--r-- | vendor/swiftmailer/classes/Swift/Encoding.php | 64 | ||||
| -rw-r--r-- | vendor/swiftmailer/classes/Swift/Plugins/RedirectingPlugin.php | 9 | ||||
| -rw-r--r-- | vendor/swiftmailer/classes/Swift/Transport/AbstractSmtpTransport.php | 15 |
11 files changed, 153 insertions, 89 deletions
diff --git a/README.markdown b/README.markdown index 5f526bad..d8274737 100644 --- a/README.markdown +++ b/README.markdown @@ -55,6 +55,7 @@ Documentation #### Working with projects - [Creating projects](docs/creating-projects.markdown) +- [Editing projects](docs/editing-projects.markdown) - [Sharing boards and tasks](docs/sharing-projects.markdown) - [Automatic actions](docs/automatic-actions.markdown) @@ -125,7 +126,7 @@ Original author: [Frédéric Guillot](http://fredericguillot.com/) Contributors: -- Alex Butum: https://github.com/dZkF9RWJT6wN8ux +- Alex Butum - Ashish Kulkarni: https://github.com/ashkulz - Claudio Lobo - Cmer: https://github.com/chncsu diff --git a/app/Event/ProjectModificationDate.php b/app/Event/ProjectModificationDate.php index d0d1e846..1b0b3736 100644 --- a/app/Event/ProjectModificationDate.php +++ b/app/Event/ProjectModificationDate.php @@ -55,8 +55,7 @@ class ProjectModificationDate implements Listener public function execute(array $data) { if (isset($data['project_id'])) { - $this->project->updateModificationDate($data['project_id']); - return true; + return $this->project->updateModificationDate($data['project_id']); } return false; diff --git a/app/Model/Project.php b/app/Model/Project.php index f8df1ae1..3edd82c5 100644 --- a/app/Model/Project.php +++ b/app/Model/Project.php @@ -489,6 +489,7 @@ class Project extends Base $this->db->startTransaction(); $values['token'] = ''; + $values['last_modified'] = time(); if (! $this->db->table(self::TABLE)->save($values)) { $this->db->cancelTransaction(); @@ -539,7 +540,7 @@ class Project extends Base */ public function updateModificationDate($project_id) { - return $this->db->table(self::TABLE)->eq('id', $project_id)->save(array( + return $this->db->table(self::TABLE)->eq('id', $project_id)->update(array( 'last_modified' => time() )); } @@ -730,10 +731,12 @@ class Project extends Base public function attachEvents() { $events = array( - Task::EVENT_UPDATE, - Task::EVENT_CREATE, + Task::EVENT_CREATE_UPDATE, Task::EVENT_CLOSE, Task::EVENT_OPEN, + Task::EVENT_MOVE_COLUMN, + Task::EVENT_MOVE_POSITION, + Task::EVENT_ASSIGNEE_CHANGE, ); $listener = new ProjectModificationDate($this); diff --git a/docs/api-json-rpc.markdown b/docs/api-json-rpc.markdown index 37b90530..23cc3518 100644 --- a/docs/api-json-rpc.markdown +++ b/docs/api-json-rpc.markdown @@ -56,6 +56,60 @@ Response from the server: } ``` +### Example with Python + +Here a basic example written in Python to create a task: + +```python +#!/usr/bin/env python + +import requests +import json + +def main(): + url = "http://demo.kanboard.net/jsonrpc.php" + api_key = "be4271664ca8169d32af49d8e1ec854edb0290bc3588a2e356275eab9505" + headers = {"content-type": "application/json"} + + payload = { + "method": "createTask", + "params": { + "title": "Python API test", + "project_id": 1 + }, + "jsonrpc": "2.0", + "id": 1, + } + + response = requests.post( + url, + data=json.dumps(payload), + headers=headers, + auth=("jsonrpc", api_key) + ) + + if response.status_code == 401: + print "Authentication failed" + else: + result = response.json() + + assert result["result"] == True + assert result["jsonrpc"] + assert result["id"] == 1 + + print "Task created successfully!" + +if __name__ == "__main__": + main() +``` + +Run this script from your terminal: + +```bash +python jsonrpc.py +Task created successfully! +``` + ### Example with a PHP client: I wrote a simple [Json-RPC Client/Server library in PHP](https://github.com/fguillot/JsonRPC), here an example: diff --git a/docs/automatic-actions.markdown b/docs/automatic-actions.markdown index c1dc3e10..631919ea 100644 --- a/docs/automatic-actions.markdown +++ b/docs/automatic-actions.markdown @@ -7,14 +7,20 @@ Each automatic action is defined like that: - An event to listen - An action linked to this event -- Eventually there is some parameters to define according to the chosen action +- Eventually there is some parameters to define Each project can have a different set of automatic actions, the configuration panel is located on the project listing page, just click on the link "Automatic actions". + + To add a new automatic action, choose the event with an action and click on the button "Next Step", then specify action parameters and finish the process by clicking on the button "Save this action". + + Each time an event occurs, the corresponding actions are executed. + + List of available events ------------------------ diff --git a/docs/editing-projects.markdown b/docs/editing-projects.markdown new file mode 100644 index 00000000..19827859 --- /dev/null +++ b/docs/editing-projects.markdown @@ -0,0 +1,8 @@ +Editing projects +================ + +Projects can be renamed and disabled at any time. + +To rename a project, just click on the link "Edit project" on the left. + + diff --git a/scripts/make-archive.sh b/scripts/make-archive.sh index 7edb90c7..2518f020 100755 --- a/scripts/make-archive.sh +++ b/scripts/make-archive.sh @@ -5,9 +5,25 @@ APP="kanboard" cd /tmp rm -rf /tmp/$APP /tmp/$APP-*.zip 2>/dev/null -git clone https://github.com/fguillot/$APP.git -rm -rf $APP/data/*.sqlite $APP/.git $APP/.gitignore $APP/scripts $APP/tests $APP/Vagrantfile $APP/.*.yml $APP/phpunit.xml $APP/README.markdown $APP/docs -sed -i.bak s/master/$VERSION/g $APP/app/common.php && rm -f $APP/app/*.bak + +git clone --depth 1 https://github.com/fguillot/$APP.git + +rm -rf $APP/data/*.sqlite \ + $APP/.git $APP/.gitignore \ + $APP/scripts \ + $APP/tests \ + $APP/Vagrantfile \ + $APP/.*.yml \ + $APP/README.markdown \ + $APP/docs + +sed -i.bak s/master/$VERSION/g $APP/app/constants.php && rm -f $APP/app/*.bak zip -r $APP-$VERSION.zip $APP -mv $APP-*.zip ~/Devel/websites/$APP + +mv $APP-$VERSION.zip ~/Devel/websites/$APP + +cd ~/Devel/websites/$APP/ +unlink $APP-latest.zip +ln -s $APP-$VERSION.zip $APP-latest.zip + rm -rf /tmp/$APP 2>/dev/null diff --git a/tests/units/ProjectTest.php b/tests/units/ProjectTest.php index 95894172..dc71d5ae 100644 --- a/tests/units/ProjectTest.php +++ b/tests/units/ProjectTest.php @@ -20,9 +20,54 @@ class ProjectTest extends Base $this->assertNotEmpty($project); $this->assertEquals(1, $project['is_active']); $this->assertEquals(0, $project['is_public']); + $this->assertEquals(time(), $project['last_modified']); $this->assertEmpty($project['token']); } + public function testUpdateLastModifiedDate() + { + $p = new Project($this->registry); + $this->assertEquals(1, $p->create(array('name' => 'UnitTest'))); + + $now = time(); + + $project = $p->getById(1); + $this->assertNotEmpty($project); + $this->assertEquals($now, $project['last_modified']); + + sleep(1); + $this->assertTrue($p->updateModificationDate(1)); + + $project = $p->getById(1); + $this->assertNotEmpty($project); + $this->assertEquals($now + 1, $project['last_modified']); + } + + public function testIsLastModified() + { + $p = new Project($this->registry); + $t = new Task($this->registry); + + $now = time(); + $p->attachEvents(); + + $this->assertEquals(1, $p->create(array('name' => 'UnitTest'))); + + $project = $p->getById(1); + $this->assertNotEmpty($project); + $this->assertEquals($now, $project['last_modified']); + + sleep(1); + + $this->assertEquals(1, $t->create(array('title' => 'Task #1', 'project_id' => 1))); + $this->assertTrue($this->registry->shared('event')->isEventTriggered(Task::EVENT_CREATE)); + $this->assertEquals('Event\ProjectModificationDate', $this->registry->shared('event')->getLastListenerExecuted()); + + $project = $p->getById(1); + $this->assertNotEmpty($project); + $this->assertTrue($p->isModifiedSince(1, $now)); + } + public function testRemove() { $p = new Project($this->registry); diff --git a/vendor/swiftmailer/classes/Swift/Encoding.php b/vendor/swiftmailer/classes/Swift/Encoding.php deleted file mode 100644 index 5cbb20fc..00000000 --- a/vendor/swiftmailer/classes/Swift/Encoding.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php - -/* - * This file is part of SwiftMailer. - * (c) 2004-2009 Chris Corbyn - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/** - * Provides quick access to each encoding type. - * - * @author Chris Corbyn - */ -class Swift_Encoding -{ - /** - * Get the Encoder that provides 7-bit encoding. - * - * @return Swift_Mime_ContentEncoder - */ - public static function get7BitEncoding() - { - return self::_lookup('mime.7bitcontentencoder'); - } - - /** - * Get the Encoder that provides 8-bit encoding. - * - * @return Swift_Mime_ContentEncoder - */ - public static function get8BitEncoding() - { - return self::_lookup('mime.8bitcontentencoder'); - } - - /** - * Get the Encoder that provides Quoted-Printable (QP) encoding. - * - * @return Swift_Mime_ContentEncoder - */ - public static function getQpEncoding() - { - return self::_lookup('mime.qpcontentencoder'); - } - - /** - * Get the Encoder that provides Base64 encoding. - * - * @return Swift_Mime_ContentEncoder - */ - public static function getBase64Encoding() - { - return self::_lookup('mime.base64contentencoder'); - } - - // -- Private Static Methods - - private static function _lookup($key) - { - return Swift_DependencyContainer::getInstance()->lookup($key); - } -} diff --git a/vendor/swiftmailer/classes/Swift/Plugins/RedirectingPlugin.php b/vendor/swiftmailer/classes/Swift/Plugins/RedirectingPlugin.php index 90f380bc..21c23829 100644 --- a/vendor/swiftmailer/classes/Swift/Plugins/RedirectingPlugin.php +++ b/vendor/swiftmailer/classes/Swift/Plugins/RedirectingPlugin.php @@ -111,8 +111,13 @@ class Swift_Plugins_RedirectingPlugin implements Swift_Events_SendListener $this->_filterHeaderSet($headers, 'Bcc'); // Add each hard coded recipient + $to = $message->getTo(); + if (null === $to) { + $to = array(); + } + foreach ( (array) $this->_recipient as $recipient) { - if (!array_key_exists($recipient, $message->getTo())) { + if (!array_key_exists($recipient, $to)) { $message->addTo($recipient); } } @@ -190,6 +195,8 @@ class Swift_Plugins_RedirectingPlugin implements Swift_Events_SendListener if ($headers->has('X-Swift-To')) { $message->setTo($headers->get('X-Swift-To')->getNameAddresses()); $headers->removeAll('X-Swift-To'); + } else { + $message->setTo(null); } if ($headers->has('X-Swift-Cc')) { diff --git a/vendor/swiftmailer/classes/Swift/Transport/AbstractSmtpTransport.php b/vendor/swiftmailer/classes/Swift/Transport/AbstractSmtpTransport.php index e5874d28..7771b6bd 100644 --- a/vendor/swiftmailer/classes/Swift/Transport/AbstractSmtpTransport.php +++ b/vendor/swiftmailer/classes/Swift/Transport/AbstractSmtpTransport.php @@ -166,13 +166,13 @@ abstract class Swift_Transport_AbstractSmtpTransport implements Swift_Transport $to = (array) $message->getTo(); $cc = (array) $message->getCc(); + $tos = array_merge($to, $cc); $bcc = (array) $message->getBcc(); $message->setBcc(array()); try { - $sent += $this->_sendTo($message, $reversePath, $to, $failedRecipients); - $sent += $this->_sendCc($message, $reversePath, $cc, $failedRecipients); + $sent += $this->_sendTo($message, $reversePath, $tos, $failedRecipients); $sent += $this->_sendBcc($message, $reversePath, $bcc, $failedRecipients); } catch (Exception $e) { $message->setBcc($bcc); @@ -444,17 +444,6 @@ abstract class Swift_Transport_AbstractSmtpTransport implements Swift_Transport $failedRecipients); } - /** Send a message to the given Cc: recipients */ - private function _sendCc(Swift_Mime_Message $message, $reversePath, array $cc, array &$failedRecipients) - { - if (empty($cc)) { - return 0; - } - - return $this->_doMailTransaction($message, $reversePath, array_keys($cc), - $failedRecipients); - } - /** Send a message to all Bcc: recipients */ private function _sendBcc(Swift_Mime_Message $message, $reversePath, array $bcc, array &$failedRecipients) { |
