summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.markdown3
-rw-r--r--app/Event/ProjectModificationDate.php3
-rw-r--r--app/Model/Project.php9
-rw-r--r--docs/api-json-rpc.markdown54
-rw-r--r--docs/automatic-actions.markdown8
-rw-r--r--docs/editing-projects.markdown8
-rwxr-xr-xscripts/make-archive.sh24
-rw-r--r--tests/units/ProjectTest.php45
-rw-r--r--vendor/swiftmailer/classes/Swift/Encoding.php64
-rw-r--r--vendor/swiftmailer/classes/Swift/Plugins/RedirectingPlugin.php9
-rw-r--r--vendor/swiftmailer/classes/Swift/Transport/AbstractSmtpTransport.php15
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".
+![Automatic action creation (step 1)](http://kanboard.net/screenshots/documentation/project-automatic-action-step1.png)
+
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".
+![Automatic action creation (step 2)](http://kanboard.net/screenshots/documentation/project-automatic-action-step2.png)
+
Each time an event occurs, the corresponding actions are executed.
+![Automatic actions](http://kanboard.net/screenshots/documentation/project-automatic-actions.png)
+
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.
+
+![Project edition](http://kanboard.net/screenshots/documentation/project-edition.png)
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)
{