Run unit tests across different database backends + fix bugs

This commit is contained in:
Frédéric Guillot 2014-09-15 22:35:56 +02:00
parent 5f962bf4cd
commit e1ddf7f012
28 changed files with 536 additions and 441 deletions

View File

@ -7,4 +7,4 @@ php:
- "5.3"
before_script: wget https://phar.phpunit.de/phpunit.phar
script: php phpunit.phar
script: php phpunit.phar -c tests/units.sqlite.xml

View File

@ -58,12 +58,12 @@ Documentation
#### Installation
- [Installation instructions](docs/installation.markdown)
- [Upgrade Kanboard to a new version](docs/update.markdown)
- [Installation on Ubuntu](docs/ubuntu-installation.markdown)
- [Installation on Debian](docs/debian-installation.markdown)
- [Installation on Centos](docs/centos-installation.markdown)
- [Installation on Windows Server with IIS](docs/windows-iis-installation.markdown)
- [Upgrade Kanboard to a new version](docs/update.markdown)
- [Secure connections (HTTPS)](docs/secure-connections.markdown)
- [Example with Nginx + HTTPS + SPDY + PHP-FPM](docs/secure-connections.markdown)
#### Database

View File

@ -10,18 +10,30 @@ namespace Core;
*/
class Loader
{
/**
* List of paths
*
* @access private
* @var array
*/
private $paths = array();
/**
* Load the missing class
*
* @access public
* @param string $class Class name
* @param string $class Class name with namespace
*/
public function load($class)
{
$filename = __DIR__.DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.str_replace('\\', DIRECTORY_SEPARATOR, $class).'.php';
foreach ($this->paths as $path) {
if (file_exists($filename)) {
require $filename;
$filename = $path.DIRECTORY_SEPARATOR.str_replace('\\', DIRECTORY_SEPARATOR, $class).'.php';
if (file_exists($filename)) {
require $filename;
break;
}
}
}
@ -34,4 +46,17 @@ class Loader
{
spl_autoload_register(array($this, 'load'));
}
/**
* Register a new path
*
* @access public
* @param string $path Path
* @return Core\Loader
*/
public function setPath($path)
{
$this->paths[] = $path;
return $this;
}
}

View File

@ -553,7 +553,8 @@ class Project extends Base
*/
public function update(array $values)
{
return $this->db->table(self::TABLE)->eq('id', $values['id'])->save($values);
return $this->exists($values['id']) &&
$this->db->table(self::TABLE)->eq('id', $values['id'])->save($values);
}
/**
@ -568,6 +569,18 @@ class Project extends Base
return $this->db->table(self::TABLE)->eq('id', $project_id)->remove();
}
/**
* Return true if the project exists
*
* @access public
* @param integer $project_id Project id
* @return boolean
*/
public function exists($project_id)
{
return $this->db->table(self::TABLE)->eq('id', $project_id)->count() === 1;
}
/**
* Enable a project
*
@ -577,10 +590,11 @@ class Project extends Base
*/
public function enable($project_id)
{
return $this->db
return $this->exists($project_id) &&
$this->db
->table(self::TABLE)
->eq('id', $project_id)
->save(array('is_active' => 1));
->update(array('is_active' => 1));
}
/**
@ -592,10 +606,11 @@ class Project extends Base
*/
public function disable($project_id)
{
return $this->db
return $this->exists($project_id) &&
$this->db
->table(self::TABLE)
->eq('id', $project_id)
->save(array('is_active' => 0));
->update(array('is_active' => 0));
}
/**
@ -607,7 +622,8 @@ class Project extends Base
*/
public function enablePublicAccess($project_id)
{
return $this->db
return $this->exists($project_id) &&
$this->db
->table(self::TABLE)
->eq('id', $project_id)
->save(array('is_public' => 1, 'token' => Security::generateToken()));
@ -622,7 +638,8 @@ class Project extends Base
*/
public function disablePublicAccess($project_id)
{
return $this->db
return $this->exists($project_id) &&
$this->db
->table(self::TABLE)
->eq('id', $project_id)
->save(array('is_public' => 0, 'token' => ''));

View File

@ -150,16 +150,16 @@ class Task extends Base
* Count all tasks for a given project and status
*
* @access public
* @param integer $project_id Project id
* @param array $status List of status id
* @param integer $project_id Project id
* @param integer $status_id Status id
* @return array
*/
public function getAll($project_id, array $status = array(self::STATUS_OPEN, self::STATUS_CLOSED))
public function getAll($project_id, $status_id = self::STATUS_OPEN)
{
return $this->db
->table(self::TABLE)
->eq('project_id', $project_id)
->in('is_active', $status)
->eq('is_active', $status_id)
->findAll();
}
@ -382,6 +382,10 @@ class Task extends Base
if (isset($values['score']) && empty($values['score'])) {
$values['score'] = 0;
}
if (isset($values['is_active'])) {
$values['is_active'] = (int) $values['is_active'];
}
}
/**
@ -487,6 +491,18 @@ class Task extends Base
}
}
/**
* Return true if the project exists
*
* @access public
* @param integer $task_id Task id
* @return boolean
*/
public function exists($task_id)
{
return $this->db->table(self::TABLE)->eq('id', $task_id)->count() === 1;
}
/**
* Mark a task closed
*
@ -496,6 +512,10 @@ class Task extends Base
*/
public function close($task_id)
{
if (! $this->exists($task_id)) {
return false;
}
$result = $this->db
->table(self::TABLE)
->eq('id', $task_id)
@ -520,12 +540,16 @@ class Task extends Base
*/
public function open($task_id)
{
if (! $this->exists($task_id)) {
return false;
}
$result = $this->db
->table(self::TABLE)
->eq('id', $task_id)
->update(array(
'is_active' => 1,
'date_completed' => ''
'date_completed' => 0
));
if ($result) {
@ -544,6 +568,10 @@ class Task extends Base
*/
public function remove($task_id)
{
if (! $this->exists($task_id)) {
return false;
}
$this->file->removeAll($task_id);
return $this->db->table(self::TABLE)->eq('id', $task_id)->remove();

View File

@ -33,8 +33,3 @@ if (! extension_loaded('mbstring')) {
if (! is_writable('data')) {
die('The directory "data" must be writeable by your web server user');
}
// Include password_compat for PHP < 5.5
if (version_compare(PHP_VERSION, '5.5.0', '<')) {
require __DIR__.'/../vendor/password.php';
}

View File

@ -1,183 +1,32 @@
<?php
// Common file between cli and web interface
require __DIR__.'/Core/Loader.php';
require __DIR__.'/helpers.php';
require __DIR__.'/translator.php';
require __DIR__.'/functions.php';
require __DIR__.'/../vendor/SimpleValidator/Validator.php';
require __DIR__.'/../vendor/SimpleValidator/Base.php';
require __DIR__.'/../vendor/SimpleValidator/Validators/Required.php';
require __DIR__.'/../vendor/SimpleValidator/Validators/Unique.php';
require __DIR__.'/../vendor/SimpleValidator/Validators/MaxLength.php';
require __DIR__.'/../vendor/SimpleValidator/Validators/MinLength.php';
require __DIR__.'/../vendor/SimpleValidator/Validators/Integer.php';
require __DIR__.'/../vendor/SimpleValidator/Validators/Equals.php';
require __DIR__.'/../vendor/SimpleValidator/Validators/AlphaNumeric.php';
require __DIR__.'/../vendor/SimpleValidator/Validators/GreaterThan.php';
require __DIR__.'/../vendor/SimpleValidator/Validators/Date.php';
require __DIR__.'/../vendor/SimpleValidator/Validators/Email.php';
require __DIR__.'/../vendor/SimpleValidator/Validators/Numeric.php';
use Core\Event;
use Core\Loader;
use Core\Registry;
// Include password_compat for PHP < 5.5
if (version_compare(PHP_VERSION, '5.5.0', '<')) {
require __DIR__.'/../vendor/password.php';
}
// Include custom config file
if (file_exists('config.php')) {
require 'config.php';
}
// Board refresh frequency in seconds for the public board view
defined('BOARD_PUBLIC_CHECK_INTERVAL') or define('BOARD_PUBLIC_CHECK_INTERVAL', 60);
// Board refresh frequency in seconds (the value 0 disable this feature)
defined('BOARD_CHECK_INTERVAL') or define('BOARD_CHECK_INTERVAL', 10);
// Period (in second) to consider a task was modified recently
defined('RECENT_TASK_PERIOD') or define('RECENT_TASK_PERIOD', 48*60*60);
// Custom session save path
defined('SESSION_SAVE_PATH') or define('SESSION_SAVE_PATH', '');
// Application version
defined('APP_VERSION') or define('APP_VERSION', 'master');
// Base directory
define('BASE_URL_DIRECTORY', dirname($_SERVER['PHP_SELF']));
// Database driver: sqlite or mysql
defined('DB_DRIVER') or define('DB_DRIVER', 'sqlite');
// Sqlite configuration
defined('DB_FILENAME') or define('DB_FILENAME', 'data/db.sqlite');
// Mysql configuration
defined('DB_USERNAME') or define('DB_USERNAME', 'root');
defined('DB_PASSWORD') or define('DB_PASSWORD', '');
defined('DB_HOSTNAME') or define('DB_HOSTNAME', 'localhost');
defined('DB_NAME') or define('DB_NAME', 'kanboard');
// LDAP configuration
defined('LDAP_AUTH') or define('LDAP_AUTH', false);
defined('LDAP_SERVER') or define('LDAP_SERVER', '');
defined('LDAP_PORT') or define('LDAP_PORT', 389);
defined('LDAP_SSL_VERIFY') or define('LDAP_SSL_VERIFY', true);
defined('LDAP_BIND_TYPE') or define('LDAP_BIND_TYPE', 'anonymous');
defined('LDAP_USERNAME') or define('LDAP_USERNAME', null);
defined('LDAP_PASSWORD') or define('LDAP_PASSWORD', null);
defined('LDAP_ACCOUNT_BASE') or define('LDAP_ACCOUNT_BASE', '');
defined('LDAP_USER_PATTERN') or define('LDAP_USER_PATTERN', '');
defined('LDAP_ACCOUNT_FULLNAME') or define('LDAP_ACCOUNT_FULLNAME', 'displayname');
defined('LDAP_ACCOUNT_EMAIL') or define('LDAP_ACCOUNT_EMAIL', 'mail');
// Google authentication
defined('GOOGLE_AUTH') or define('GOOGLE_AUTH', false);
defined('GOOGLE_CLIENT_ID') or define('GOOGLE_CLIENT_ID', '');
defined('GOOGLE_CLIENT_SECRET') or define('GOOGLE_CLIENT_SECRET', '');
// GitHub authentication
defined('GITHUB_AUTH') or define('GITHUB_AUTH', false);
defined('GITHUB_CLIENT_ID') or define('GITHUB_CLIENT_ID', '');
defined('GITHUB_CLIENT_SECRET') or define('GITHUB_CLIENT_SECRET', '');
// Proxy authentication
defined('REVERSE_PROXY_AUTH') or define('REVERSE_PROXY_AUTH', false);
defined('REVERSE_PROXY_USER_HEADER') or define('REVERSE_PROXY_USER_HEADER', 'REMOTE_USER');
defined('REVERSE_PROXY_DEFAULT_ADMIN') or define('REVERSE_PROXY_DEFAULT_ADMIN', '');
defined('REVERSE_PROXY_DEFAULT_DOMAIN') or define('REVERSE_PROXY_DEFAULT_DOMAIN', '');
// Mail configuration
defined('MAIL_FROM') or define('MAIL_FROM', 'notifications@kanboard.net');
defined('MAIL_TRANSPORT') or define('MAIL_TRANSPORT', 'mail');
defined('MAIL_SMTP_HOSTNAME') or define('MAIL_SMTP_HOSTNAME', '');
defined('MAIL_SMTP_PORT') or define('MAIL_SMTP_PORT', 25);
defined('MAIL_SMTP_USERNAME') or define('MAIL_SMTP_USERNAME', '');
defined('MAIL_SMTP_PASSWORD') or define('MAIL_SMTP_PASSWORD', '');
defined('MAIL_SMTP_ENCRYPTION') or define('MAIL_SMTP_ENCRYPTION', null);
defined('MAIL_SENDMAIL_COMMAND') or define('MAIL_SENDMAIL_COMMAND', '/usr/sbin/sendmail -bs');
require __DIR__.'/constants.php';
$loader = new Loader;
$loader->setPath('app');
$loader->setPath('vendor');
$loader->execute();
$registry = new Registry;
$registry->db = function() use ($registry) {
require __DIR__.'/../vendor/PicoDb/Database.php';
switch (DB_DRIVER) {
case 'sqlite':
require __DIR__.'/Schema/Sqlite.php';
$params = array(
'driver' => 'sqlite',
'filename' => DB_FILENAME
);
break;
case 'mysql':
require __DIR__.'/Schema/Mysql.php';
$params = array(
'driver' => 'mysql',
'hostname' => DB_HOSTNAME,
'username' => DB_USERNAME,
'password' => DB_PASSWORD,
'database' => DB_NAME,
'charset' => 'utf8',
);
break;
case 'postgres':
require __DIR__.'/Schema/Postgres.php';
$params = array(
'driver' => 'postgres',
'hostname' => DB_HOSTNAME,
'username' => DB_USERNAME,
'password' => DB_PASSWORD,
'database' => DB_NAME,
);
break;
default:
die('Database driver not supported');
}
$db = new \PicoDb\Database($params);
if ($db->schema()->check(Schema\VERSION)) {
return $db;
}
else {
$errors = $db->getLogMessages();
die('Unable to migrate database schema: <br/><br/><strong>'.(isset($errors[0]) ? $errors[0] : 'Unknown error').'</strong>');
}
};
$registry->event = function() use ($registry) {
return new Event;
};
$registry->mailer = function() use ($registry) {
require_once 'vendor/swiftmailer/swift_required.php';
switch (MAIL_TRANSPORT) {
case 'smtp':
$transport = Swift_SmtpTransport::newInstance(MAIL_SMTP_HOSTNAME, MAIL_SMTP_PORT);
$transport->setUsername(MAIL_SMTP_USERNAME);
$transport->setPassword(MAIL_SMTP_PASSWORD);
$transport->setEncryption(MAIL_SMTP_ENCRYPTION);
break;
case 'sendmail':
$transport = Swift_SendmailTransport::newInstance(MAIL_SENDMAIL_COMMAND);
break;
default:
$transport = Swift_MailTransport::newInstance();
}
return $transport;
};
$registry->db = setup_db();
$registry->event = setup_events();
$registry->mailer = setup_mailer();

70
app/constants.php Normal file
View File

@ -0,0 +1,70 @@
<?php
// Board refresh frequency in seconds for the public board view
defined('BOARD_PUBLIC_CHECK_INTERVAL') or define('BOARD_PUBLIC_CHECK_INTERVAL', 60);
// Board refresh frequency in seconds (the value 0 disable this feature)
defined('BOARD_CHECK_INTERVAL') or define('BOARD_CHECK_INTERVAL', 10);
// Period (in second) to consider a task was modified recently
defined('RECENT_TASK_PERIOD') or define('RECENT_TASK_PERIOD', 48*60*60);
// Custom session save path
defined('SESSION_SAVE_PATH') or define('SESSION_SAVE_PATH', '');
// Application version
defined('APP_VERSION') or define('APP_VERSION', 'master');
// Base directory
define('BASE_URL_DIRECTORY', dirname($_SERVER['PHP_SELF']));
// Database driver: sqlite or mysql
defined('DB_DRIVER') or define('DB_DRIVER', 'sqlite');
// Sqlite configuration
defined('DB_FILENAME') or define('DB_FILENAME', 'data/db.sqlite');
// Mysql configuration
defined('DB_USERNAME') or define('DB_USERNAME', 'root');
defined('DB_PASSWORD') or define('DB_PASSWORD', '');
defined('DB_HOSTNAME') or define('DB_HOSTNAME', 'localhost');
defined('DB_NAME') or define('DB_NAME', 'kanboard');
// LDAP configuration
defined('LDAP_AUTH') or define('LDAP_AUTH', false);
defined('LDAP_SERVER') or define('LDAP_SERVER', '');
defined('LDAP_PORT') or define('LDAP_PORT', 389);
defined('LDAP_SSL_VERIFY') or define('LDAP_SSL_VERIFY', true);
defined('LDAP_BIND_TYPE') or define('LDAP_BIND_TYPE', 'anonymous');
defined('LDAP_USERNAME') or define('LDAP_USERNAME', null);
defined('LDAP_PASSWORD') or define('LDAP_PASSWORD', null);
defined('LDAP_ACCOUNT_BASE') or define('LDAP_ACCOUNT_BASE', '');
defined('LDAP_USER_PATTERN') or define('LDAP_USER_PATTERN', '');
defined('LDAP_ACCOUNT_FULLNAME') or define('LDAP_ACCOUNT_FULLNAME', 'displayname');
defined('LDAP_ACCOUNT_EMAIL') or define('LDAP_ACCOUNT_EMAIL', 'mail');
// Google authentication
defined('GOOGLE_AUTH') or define('GOOGLE_AUTH', false);
defined('GOOGLE_CLIENT_ID') or define('GOOGLE_CLIENT_ID', '');
defined('GOOGLE_CLIENT_SECRET') or define('GOOGLE_CLIENT_SECRET', '');
// GitHub authentication
defined('GITHUB_AUTH') or define('GITHUB_AUTH', false);
defined('GITHUB_CLIENT_ID') or define('GITHUB_CLIENT_ID', '');
defined('GITHUB_CLIENT_SECRET') or define('GITHUB_CLIENT_SECRET', '');
// Proxy authentication
defined('REVERSE_PROXY_AUTH') or define('REVERSE_PROXY_AUTH', false);
defined('REVERSE_PROXY_USER_HEADER') or define('REVERSE_PROXY_USER_HEADER', 'REMOTE_USER');
defined('REVERSE_PROXY_DEFAULT_ADMIN') or define('REVERSE_PROXY_DEFAULT_ADMIN', '');
defined('REVERSE_PROXY_DEFAULT_DOMAIN') or define('REVERSE_PROXY_DEFAULT_DOMAIN', '');
// Mail configuration
defined('MAIL_FROM') or define('MAIL_FROM', 'notifications@kanboard.net');
defined('MAIL_TRANSPORT') or define('MAIL_TRANSPORT', 'mail');
defined('MAIL_SMTP_HOSTNAME') or define('MAIL_SMTP_HOSTNAME', '');
defined('MAIL_SMTP_PORT') or define('MAIL_SMTP_PORT', 25);
defined('MAIL_SMTP_USERNAME') or define('MAIL_SMTP_USERNAME', '');
defined('MAIL_SMTP_PASSWORD') or define('MAIL_SMTP_PASSWORD', '');
defined('MAIL_SMTP_ENCRYPTION') or define('MAIL_SMTP_ENCRYPTION', null);
defined('MAIL_SENDMAIL_COMMAND') or define('MAIL_SENDMAIL_COMMAND', '/usr/sbin/sendmail -bs');

131
app/functions.php Normal file
View File

@ -0,0 +1,131 @@
<?php
use Core\Event;
use Core\Translator;
use PicoDb\Database;
function debug($message)
{
error_log($message.PHP_EOL, 3, 'data/debug.log');
}
function setup_events()
{
return new Event;
}
function setup_mailer()
{
require_once __DIR__.'/../vendor/swiftmailer/swift_required.php';
switch (MAIL_TRANSPORT) {
case 'smtp':
$transport = Swift_SmtpTransport::newInstance(MAIL_SMTP_HOSTNAME, MAIL_SMTP_PORT);
$transport->setUsername(MAIL_SMTP_USERNAME);
$transport->setPassword(MAIL_SMTP_PASSWORD);
$transport->setEncryption(MAIL_SMTP_ENCRYPTION);
break;
case 'sendmail':
$transport = Swift_SendmailTransport::newInstance(MAIL_SENDMAIL_COMMAND);
break;
default:
$transport = Swift_MailTransport::newInstance();
}
return $transport;
}
function setup_db()
{
switch (DB_DRIVER) {
case 'sqlite':
require_once __DIR__.'/Schema/Sqlite.php';
$params = array(
'driver' => 'sqlite',
'filename' => DB_FILENAME
);
break;
case 'mysql':
require_once __DIR__.'/Schema/Mysql.php';
$params = array(
'driver' => 'mysql',
'hostname' => DB_HOSTNAME,
'username' => DB_USERNAME,
'password' => DB_PASSWORD,
'database' => DB_NAME,
'charset' => 'utf8',
);
break;
case 'postgres':
require_once __DIR__.'/Schema/Postgres.php';
$params = array(
'driver' => 'postgres',
'hostname' => DB_HOSTNAME,
'username' => DB_USERNAME,
'password' => DB_PASSWORD,
'database' => DB_NAME,
);
break;
default:
die('Database driver not supported');
}
$db = new Database($params);
if ($db->schema()->check(Schema\VERSION)) {
return $db;
}
else {
$errors = $db->getLogMessages();
die('Unable to migrate database schema: <br/><br/><strong>'.(isset($errors[0]) ? $errors[0] : 'Unknown error').'</strong>');
}
}
// Get a translation
function t()
{
$t = new Translator;
return call_user_func_array(array($t, 'translate'), func_get_args());
}
// translate with no html escaping
function e()
{
$t = new Translator;
return call_user_func_array(array($t, 'translateNoEscaping'), func_get_args());
}
// Get a locale currency
function c($value)
{
$t = new Translator;
return $t->currency($value);
}
// Get a formatted number
function n($value)
{
$t = new Translator;
return $t->number($value);
}
// Get a locale date
function dt($format, $timestamp)
{
$t = new Translator;
return $t->datetime($format, $timestamp);
}
// Plurals, return $t2 if $value > 1
function p($value, $t1, $t2) {
return $value > 1 ? $t2 : $t1;
}

View File

@ -1,43 +0,0 @@
<?php
use Core\Translator;
// Get a translation
function t()
{
$t = new Translator;
return call_user_func_array(array($t, 'translate'), func_get_args());
}
// translate with no html escaping
function e()
{
$t = new Translator;
return call_user_func_array(array($t, 'translateNoEscaping'), func_get_args());
}
// Get a locale currency
function c($value)
{
$t = new Translator;
return $t->currency($value);
}
// Get a formatted number
function n($value)
{
$t = new Translator;
return $t->number($value);
}
// Get a locale date
function dt($format, $timestamp)
{
$t = new Translator;
return $t->datetime($format, $timestamp);
}
// Plurals, return $t2 if $value > 1
function p($value, $t1, $t2) {
return $value > 1 ? $t2 : $t1;
}

View File

@ -608,7 +608,7 @@ Response example:
- Purpose: **Get all available tasks**
- Parameters:
- **project_id** (integer, required)
- **status**: List of status id, the value 1 for active tasks and 0 for inactive (list, required)
- **status**: The value 1 for active tasks and 0 for inactive (integer, required)
- Result on success: **List of tasks**
- Result on failure: **false**
@ -621,9 +621,7 @@ Request example to fetch all tasks on the board:
"id": 133280317,
"params": {
"project_id": 1,
"status": [
1
]
"status": 1
}
}
```

View File

@ -1,6 +1,11 @@
Centos Installation
===================
Centos 7
--------
Centos 6.5
----------

View File

@ -1,59 +0,0 @@
How to Enable Secure Connections
================================
If you are hosting Kanboard on a public server, and plan on accessing it via the internet, it is a good idea to enable SSL connections to encrypt your data. This is very simple to do with a self-signed certificate. The following instructions were created and tested on a server running Debian 7 (Wheezy) but they should work for any other Linux distribution.
OpenSSL Installation and Configuration
--------------------------------------
Install OpenSSL:
```bash
apt-get update
apt-get install openssl
```
Enable OpenSSL:
```bash
a2enmod ssl
```
Create a self-signed certificate:
```bash
mkdir /etc/apache2/ssl
openssl req -new -x509 -days 365 -nodes -out /etc/apache2/ssl/kanboard.pem -keyout /etc/apache2/ssl/kanboard.key
```
Apache Configuration
--------------------
Create an apache configuration file:
```bash
nano /etc/apache2/conf.d/kanboard.conf
```
The contents of this file should look like this:
```bash
<VirtualHost 127.0.0.1:443>
SSLEngine on
SSLCertificateFile /etc/apache2/ssl/kanboard.pem
SSLCertificateKeyFile /etc/apache2/ssl/kanboard.key
DocumentRoot /var/www
<Directory kanboard>
AllowOverride All
order allow, deny
Allow from all
</Directory>
</VirtualHost>
```
Be sure to replace 127.0.0.1 with the IP address of your server. If you are hosting kanboard in a location other than /var/www , be sure to update the DocumentRoot to match the location where you are hosting your Kanboard site.
Restart Apache:
```bash
service apache2 restart
```
You will now be able to access your Kanboard site securely by navigating to `https://www.example.com/kanboard`. Your browser will indicate that the certificate is not trusted. This is due to the fact that it is self signed. You can safely ignore this warning, although the certificate is not trusted, your data is still encrypted.

View File

@ -1,7 +1,6 @@
<?php
require __DIR__.'/app/common.php';
require __DIR__.'/vendor/JsonRPC/Server.php';
use Core\Translator;
use JsonRPC\Server;
@ -175,7 +174,7 @@ $server->register('getTask', function($task_id) use ($task) {
return $task->getById($task_id);
});
$server->register('getAllTasks', function($project_id, array $status) use ($task) {
$server->register('getAllTasks', function($project_id, $status) use ($task) {
return $task->getAll($project_id, $status);
});

View File

@ -1,7 +0,0 @@
<phpunit>
<testsuites>
<testsuite name="Kanboard">
<directory>tests/units</directory>
</testsuite>
</testsuites>
</phpunit>

View File

@ -0,0 +1,16 @@
<phpunit>
<testsuites>
<testsuite name="Kanboard">
<directory>functionals</directory>
</testsuite>
</testsuites>
<php>
<const name="API_URL" value="http://localhost:8000/jsonrpc.php" />
<const name="API_KEY" value="19ffd9709d03ce50675c3a43d1c49c1ac207f4bc45f06c5b2701fbdf8929" />
<const name="DB_DRIVER" value="mysql" />
<const name="DB_NAME" value="kanboard" />
<const name="DB_HOSTNAME" value="localhost" />
<const name="DB_USERNAME" value="root" />
<const name="DB_PASSWORD" value="" />
</php>
</phpunit>

View File

@ -0,0 +1,16 @@
<phpunit>
<testsuites>
<testsuite name="Kanboard">
<directory>functionals</directory>
</testsuite>
</testsuites>
<php>
<const name="API_URL" value="http://localhost:8000/jsonrpc.php" />
<const name="API_KEY" value="19ffd9709d03ce50675c3a43d1c49c1ac207f4bc45f06c5b2701fbdf8929" />
<const name="DB_DRIVER" value="postgres" />
<const name="DB_NAME" value="kanboard" />
<const name="DB_HOSTNAME" value="localhost" />
<const name="DB_USERNAME" value="postgres" />
<const name="DB_PASSWORD" value="postgres" />
</php>
</phpunit>

View File

@ -0,0 +1,13 @@
<phpunit>
<testsuites>
<testsuite name="Kanboard">
<directory>functionals</directory>
</testsuite>
</testsuites>
<php>
<const name="API_URL" value="http://localhost:8000/jsonrpc.php" />
<const name="API_KEY" value="19ffd9709d03ce50675c3a43d1c49c1ac207f4bc45f06c5b2701fbdf8929" />
<const name="DB_DRIVER" value="sqlite" />
<const name="DB_FILENAME" value="data/db.sqlite" />
</php>
</phpunit>

View File

@ -1,21 +1,52 @@
<?php
require_once __DIR__.'/../../vendor/PicoDb/Database.php';
require_once __DIR__.'/../../vendor/JsonRPC/Client.php';
require_once __DIR__.'/../../app/Core/Security.php';
require_once __DIR__.'/../../app/functions.php';
class Api extends PHPUnit_Framework_TestCase
{
const URL = 'http://localhost:8000/jsonrpc.php';
const KEY = '19ffd9709d03ce50675c3a43d1c49c1ac207f4bc45f06c5b2701fbdf8929';
private $client;
public static function setUpBeforeClass()
{
if (DB_DRIVER === 'sqlite') {
@unlink(DB_FILENAME);
$pdo = new PDO('sqlite:'.DB_FILENAME);
}
else if (DB_DRIVER === 'mysql') {
$pdo = new PDO('mysql:host='.DB_HOSTNAME, DB_USERNAME, DB_PASSWORD);
$pdo->exec('DROP DATABASE '.DB_NAME);
$pdo->exec('CREATE DATABASE '.DB_NAME);
$pdo = new PDO('mysql:host='.DB_HOSTNAME.';dbname='.DB_NAME, DB_USERNAME, DB_PASSWORD);
}
else if (DB_DRIVER === 'postgres') {
$pdo = new PDO('pgsql:host='.DB_HOSTNAME, DB_USERNAME, DB_PASSWORD);
$pdo->exec('DROP DATABASE '.DB_NAME);
$pdo->exec('CREATE DATABASE '.DB_NAME.' WITH OWNER '.DB_USERNAME);
$pdo = new PDO('pgsql:host='.DB_HOSTNAME.';dbname='.DB_NAME, DB_USERNAME, DB_PASSWORD);
}
setup_db();
$pdo->exec("UPDATE config SET api_token='".API_KEY."'");
$pdo = null;
}
public function setUp()
{
$this->client = new JsonRPC\Client(self::URL);
$this->client->authentication('jsonrpc', self::KEY);
$this->client = new JsonRPC\Client(API_URL);
$this->client->authentication('jsonrpc', API_KEY);
}
$pdo = new PDO('sqlite:data/db.sqlite');
$pdo->exec('UPDATE config SET api_token="'.self::KEY.'"');
private function getTaskId()
{
$tasks = $this->client->getAllTasks(1, 1);
$this->assertNotEmpty($tasks);
$this->assertEquals(1, count($tasks));
return $tasks[0]['id'];
}
public function testRemoveAll()
@ -154,13 +185,13 @@ class Api extends PHPUnit_Framework_TestCase
public function testGetAllTasks()
{
$tasks = $this->client->getAllTasks(1, array(1));
$tasks = $this->client->getAllTasks(1, 1);
$this->assertNotFalse($tasks);
$this->assertTrue(is_array($tasks));
$this->assertEquals('Task #1', $tasks[0]['title']);
$tasks = $this->client->getAllTasks(2, array(1, 2));
$tasks = $this->client->getAllTasks(2, 0);
$this->assertNotFalse($tasks);
$this->assertTrue(is_array($tasks));
@ -228,10 +259,10 @@ class Api extends PHPUnit_Framework_TestCase
public function testUpdateUser()
{
$user = $this->client->getUser(2);
$user = array();
$user['id'] = 2;
$user['username'] = 'titi';
$user['name'] = 'Titi';
unset($user['password']);
$this->assertTrue($this->client->updateUser($user));
@ -280,8 +311,12 @@ class Api extends PHPUnit_Framework_TestCase
$this->assertTrue($this->client->execute('createTask', $task));
$tasks = $this->client->getAllTasks(1, 1);
$this->assertNotEmpty($tasks);
$this->assertEquals(1, count($tasks));
$comment = array(
'task_id' => 1,
'task_id' => $tasks[0]['id'],
'user_id' => 2,
'comment' => 'boo',
);
@ -294,7 +329,6 @@ class Api extends PHPUnit_Framework_TestCase
$comment = $this->client->getComment(1);
$this->assertNotFalse($comment);
$this->assertNotEmpty($comment);
$this->assertEquals(1, $comment['task_id']);
$this->assertEquals(2, $comment['user_id']);
$this->assertEquals('boo', $comment['comment']);
}
@ -312,15 +346,17 @@ class Api extends PHPUnit_Framework_TestCase
public function testGetAllComments()
{
$task_id = $this->getTaskId();
$comment = array(
'task_id' => 1,
'task_id' => $task_id,
'user_id' => 1,
'comment' => 'blabla',
);
$this->assertTrue($this->client->createComment($comment));
$comments = $this->client->getAllComments(1);
$comments = $this->client->getAllComments($task_id);
$this->assertNotFalse($comments);
$this->assertNotEmpty($comments);
$this->assertTrue(is_array($comments));
@ -329,9 +365,10 @@ class Api extends PHPUnit_Framework_TestCase
public function testRemoveComment()
{
$this->assertTrue($this->client->removeComment(1));
$task_id = $this->getTaskId();
$this->assertTrue($this->client->removeComment($task_id));
$comments = $this->client->getAllComments(1);
$comments = $this->client->getAllComments($task_id);
$this->assertNotFalse($comments);
$this->assertNotEmpty($comments);
$this->assertTrue(is_array($comments));
@ -341,7 +378,7 @@ class Api extends PHPUnit_Framework_TestCase
public function testCreateSubtask()
{
$subtask = array(
'task_id' => 1,
'task_id' => $this->getTaskId(),
'title' => 'subtask #1',
);
@ -353,7 +390,7 @@ class Api extends PHPUnit_Framework_TestCase
$subtask = $this->client->getSubtask(1);
$this->assertNotFalse($subtask);
$this->assertNotEmpty($subtask);
$this->assertEquals(1, $subtask['task_id']);
$this->assertEquals($this->getTaskId(), $subtask['task_id']);
$this->assertEquals(0, $subtask['user_id']);
$this->assertEquals('subtask #1', $subtask['title']);
}
@ -362,7 +399,7 @@ class Api extends PHPUnit_Framework_TestCase
{
$subtask = array();
$subtask['id'] = 1;
$subtask['task_id'] = 1;
$subtask['task_id'] = $this->getTaskId();
$subtask['title'] = 'test';
$this->assertTrue($this->client->execute('updateSubtask', $subtask));
@ -374,14 +411,14 @@ class Api extends PHPUnit_Framework_TestCase
public function testGetAllSubtasks()
{
$subtask = array(
'task_id' => 1,
'task_id' => $this->getTaskId(),
'user_id' => 2,
'title' => 'Subtask #2',
);
$this->assertTrue($this->client->execute('createSubtask', $subtask));
$subtasks = $this->client->getAllSubtasks(1);
$subtasks = $this->client->getAllSubtasks($this->getTaskId());
$this->assertNotFalse($subtasks);
$this->assertNotEmpty($subtasks);
$this->assertTrue(is_array($subtasks));
@ -392,7 +429,7 @@ class Api extends PHPUnit_Framework_TestCase
{
$this->assertTrue($this->client->removeSubtask(1));
$subtasks = $this->client->getAllSubtasks(1);
$subtasks = $this->client->getAllSubtasks($this->getTaskId());
$this->assertNotFalse($subtasks);
$this->assertNotEmpty($subtasks);
$this->assertTrue(is_array($subtasks));
@ -401,20 +438,10 @@ class Api extends PHPUnit_Framework_TestCase
public function testMoveTaskPosition()
{
$task = array(
'title' => 'Task to move',
'color_id' => 'blue',
'owner_id' => 1,
'project_id' => 1,
'column_id' => 1,
);
$this->assertTrue($this->client->execute('createTask', $task));
$this->assertTrue($this->client->moveTaskPosition(1, 1, 3, 1));
$task = $this->client->getTask(1);
$task_id = $this->getTaskId();
$this->assertTrue($this->client->moveTaskPosition(1, $task_id, 3, 1));
$task = $this->client->getTask($task_id);
$this->assertNotFalse($task);
$this->assertTrue(is_array($task));
$this->assertEquals(1, $task['position']);

11
tests/units.mysql.xml Normal file
View File

@ -0,0 +1,11 @@
<phpunit>
<testsuites>
<testsuite name="Kanboard">
<directory>units</directory>
</testsuite>
</testsuites>
<php>
<const name="DB_DRIVER" value="mysql" />
<const name="DB_NAME" value="kanboard_unit_test" />
</php>
</phpunit>

12
tests/units.postgres.xml Normal file
View File

@ -0,0 +1,12 @@
<phpunit>
<testsuites>
<testsuite name="Kanboard">
<directory>units</directory>
</testsuite>
</testsuites>
<php>
<const name="DB_DRIVER" value="postgres" />
<const name="DB_USERNAME" value="postgres" />
<const name="DB_NAME" value="kanboard_unit_test" />
</php>
</phpunit>

11
tests/units.sqlite.xml Normal file
View File

@ -0,0 +1,11 @@
<phpunit>
<testsuites>
<testsuite name="Kanboard">
<directory>units</directory>
</testsuite>
</testsuites>
<php>
<const name="DB_DRIVER" value="sqlite" />
<const name="DB_FILENAME" value=":memory:" />
</php>
</phpunit>

View File

@ -9,7 +9,7 @@ use Model\Task;
use Model\Category;
class ActionTest extends Base
{/*
{
public function testFetchActions()
{
$action = new Action($this->registry);
@ -86,15 +86,15 @@ class ActionTest extends Base
// We move our task
$task->movePosition(1, 1, 4, 1);
$this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_MOVE_COLUMN));
$this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_UPDATE));
$this->assertTrue($this->registry->shared('event')->isEventTriggered(Task::EVENT_MOVE_COLUMN));
$this->assertFalse($this->registry->shared('event')->isEventTriggered(Task::EVENT_UPDATE));
// Our task should be closed
$t1 = $task->getById(1);
$this->assertEquals(4, $t1['column_id']);
$this->assertEquals(0, $t1['is_active']);
}
*/
public function testEventMovePosition()
{
$task = new Task($this->registry);
@ -138,7 +138,7 @@ class ActionTest extends Base
// We bind events
$action->attachEvents();
$this->assertTrue($this->registry->event->hasListener(Task::EVENT_MOVE_POSITION, 'Action\TaskAssignColorCategory'));
$this->assertTrue($this->registry->shared('event')->hasListener(Task::EVENT_MOVE_POSITION, 'Action\TaskAssignColorCategory'));
// Our task should have the color red and position=1
$t1 = $task->getById(1);
@ -153,7 +153,7 @@ class ActionTest extends Base
// We move our tasks
$this->assertTrue($task->movePosition(1, 1, 1, 10)); // task #1 to the end of the column
$this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_MOVE_POSITION));
$this->assertTrue($this->registry->shared('event')->isEventTriggered(Task::EVENT_MOVE_POSITION));
$t1 = $task->getById(1);
$this->assertEquals(2, $t1['position']);
@ -165,10 +165,10 @@ class ActionTest extends Base
$this->assertEquals(1, $t1['is_active']);
$this->assertEquals('yellow', $t1['color_id']);
$this->registry->event->clearTriggeredEvents();
$this->registry->shared('event')->clearTriggeredEvents();
$this->assertTrue($task->movePosition(1, 2, 1, 44)); // task #2 to position 1
$this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_MOVE_POSITION));
$this->assertEquals('Action\TaskAssignColorCategory', $this->registry->event->getLastListenerExecuted());
$this->assertTrue($this->registry->shared('event')->isEventTriggered(Task::EVENT_MOVE_POSITION));
$this->assertEquals('Action\TaskAssignColorCategory', $this->registry->shared('event')->getLastListenerExecuted());
$t1 = $task->getById(1);
$this->assertEquals(1, $t1['position']);
@ -180,7 +180,7 @@ class ActionTest extends Base
$this->assertEquals(1, $t1['is_active']);
$this->assertEquals('green', $t1['color_id']);
}
/*
public function testExecuteMultipleActions()
{
$task = new Task($this->registry);
@ -225,8 +225,8 @@ class ActionTest extends Base
$action->attachEvents();
// Events should be attached
$this->assertTrue($this->registry->event->hasListener(Task::EVENT_CLOSE, 'Action\TaskDuplicateAnotherProject'));
$this->assertTrue($this->registry->event->hasListener(Task::EVENT_MOVE_COLUMN, 'Action\TaskClose'));
$this->assertTrue($this->registry->shared('event')->hasListener(Task::EVENT_CLOSE, 'Action\TaskDuplicateAnotherProject'));
$this->assertTrue($this->registry->shared('event')->hasListener(Task::EVENT_MOVE_COLUMN, 'Action\TaskClose'));
// Our task should be open, linked to the first project and in the first column
$t1 = $task->getById(1);
@ -237,8 +237,8 @@ class ActionTest extends Base
// We move our task
$task->movePosition(1, 1, 4, 1);
$this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_CLOSE));
$this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_MOVE_COLUMN));
$this->assertTrue($this->registry->shared('event')->isEventTriggered(Task::EVENT_CLOSE));
$this->assertTrue($this->registry->shared('event')->isEventTriggered(Task::EVENT_MOVE_COLUMN));
// Our task should be closed
$t1 = $task->getById(1);
@ -252,5 +252,5 @@ class ActionTest extends Base
$this->assertEquals(1, $t2['is_active']);
$this->assertEquals(2, $t2['project_id']);
$this->assertEquals('unit_test', $t2['title']);
}*/
}
}

View File

@ -1,86 +1,48 @@
<?php
require __DIR__.'/../../app/Core/Loader.php';
require __DIR__.'/../../app/helpers.php';
require __DIR__.'/../../app/functions.php';
require __DIR__.'/../../app/constants.php';
use Core\Loader;
use Core\Registry;
if (version_compare(PHP_VERSION, '5.5.0', '<')) {
require __DIR__.'/../../vendor/password.php';
}
require __DIR__.'/../../vendor/SimpleValidator/Validator.php';
require __DIR__.'/../../vendor/SimpleValidator/Base.php';
require __DIR__.'/../../vendor/SimpleValidator/Validators/Required.php';
require __DIR__.'/../../vendor/SimpleValidator/Validators/Unique.php';
require __DIR__.'/../../vendor/SimpleValidator/Validators/MaxLength.php';
require __DIR__.'/../../vendor/SimpleValidator/Validators/MinLength.php';
require __DIR__.'/../../vendor/SimpleValidator/Validators/Integer.php';
require __DIR__.'/../../vendor/SimpleValidator/Validators/Equals.php';
require __DIR__.'/../../vendor/SimpleValidator/Validators/AlphaNumeric.php';
require __DIR__.'/../../vendor/SimpleValidator/Validators/GreaterThan.php';
require __DIR__.'/../../vendor/SimpleValidator/Validators/Date.php';
require __DIR__.'/../../vendor/SimpleValidator/Validators/Email.php';
require __DIR__.'/../../vendor/SimpleValidator/Validators/Numeric.php';
date_default_timezone_set('UTC');
require_once __DIR__.'/../../app/Core/Security.php';
require_once __DIR__.'/../../vendor/PicoDb/Database.php';
require_once __DIR__.'/../../app/Schema/Sqlite.php';
require_once __DIR__.'/../../app/Core/Registry.php';
require_once __DIR__.'/../../app/Core/Tool.php';
require_once __DIR__.'/../../app/Core/Listener.php';
require_once __DIR__.'/../../app/Core/Event.php';
require_once __DIR__.'/../../app/Core/Translator.php';
require_once __DIR__.'/../../app/Core/Template.php';
require_once __DIR__.'/../../app/translator.php';
require_once __DIR__.'/../../app/helpers.php';
require_once __DIR__.'/../../app/Model/Base.php';
require_once __DIR__.'/../../app/Model/Config.php';
require_once __DIR__.'/../../app/Model/Task.php';
require_once __DIR__.'/../../app/Model/Acl.php';
require_once __DIR__.'/../../app/Model/Comment.php';
require_once __DIR__.'/../../app/Model/Project.php';
require_once __DIR__.'/../../app/Model/User.php';
require_once __DIR__.'/../../app/Model/Board.php';
require_once __DIR__.'/../../app/Model/Action.php';
require_once __DIR__.'/../../app/Model/Category.php';
require_once __DIR__.'/../../app/Model/SubTask.php';
require_once __DIR__.'/../../app/Model/File.php';
require_once __DIR__.'/../../app/Model/BaseHistory.php';
require_once __DIR__.'/../../app/Model/TaskHistory.php';
require_once __DIR__.'/../../app/Model/SubtaskHistory.php';
require_once __DIR__.'/../../app/Model/CommentHistory.php';
require_once __DIR__.'/../../app/Action/Base.php';
require_once __DIR__.'/../../app/Action/TaskClose.php';
require_once __DIR__.'/../../app/Action/TaskAssignSpecificUser.php';
require_once __DIR__.'/../../app/Action/TaskAssignColorUser.php';
require_once __DIR__.'/../../app/Action/TaskAssignColorCategory.php';
require_once __DIR__.'/../../app/Action/TaskAssignCurrentUser.php';
require_once __DIR__.'/../../app/Action/TaskDuplicateAnotherProject.php';
require_once __DIR__.'/../../app/Action/TaskMoveAnotherProject.php';
$loader = new Loader;
$loader->setPath('app');
$loader->setPath('vendor');
$loader->execute();
abstract class Base extends PHPUnit_Framework_TestCase
{
public function setUp()
{
date_default_timezone_set('UTC');
$this->registry = new Registry;
$this->registry->db = function() { return setup_db(); };
$this->registry->event = function() { return setup_events(); };
$this->registry = new \Core\Registry;
$this->registry->db = $this->getDbConnection();
$this->registry->event = new \Core\Event;
if (DB_DRIVER === 'mysql') {
$pdo = new PDO('mysql:host='.DB_HOSTNAME, DB_USERNAME, DB_PASSWORD);
$pdo->exec('DROP DATABASE '.DB_NAME);
$pdo->exec('CREATE DATABASE '.DB_NAME);
$pdo = null;
}
else if (DB_DRIVER === 'postgres') {
$pdo = new PDO('pgsql:host='.DB_HOSTNAME, DB_USERNAME, DB_PASSWORD);
$pdo->exec('DROP DATABASE '.DB_NAME);
$pdo->exec('CREATE DATABASE '.DB_NAME.' WITH OWNER '.DB_USERNAME);
$pdo = null;
}
}
public function getDbConnection()
public function tearDown()
{
$db = new \PicoDb\Database(array(
'driver' => 'sqlite',
'filename' => ':memory:'
));
if ($db->schema()->check(\Schema\VERSION)) {
return $db;
}
else {
die('Unable to migrate database schema!');
}
$this->registry->shared('db')->closeConnection();
}
}

View File

@ -73,7 +73,7 @@ class TaskHistoryTest extends Base
$this->assertTrue($e->create(1, 1, 1, Task::EVENT_CLOSE));
}
$this->assertEquals($nb_events, $this->registry->db->table('task_has_events')->count());
$this->assertEquals($nb_events, $this->registry->shared('db')->table('task_has_events')->count());
$e->cleanup($max);
$events = $e->getAllByProjectId(1);
@ -93,6 +93,6 @@ class TaskHistoryTest extends Base
$this->assertTrue($e->create(1, 1, 1, Task::EVENT_CLOSE));
}
$this->assertEquals(TaskHistory::MAX_EVENTS, $this->registry->db->table('task_has_events')->count());
$this->assertEquals(TaskHistory::MAX_EVENTS, $this->registry->shared('db')->table('task_has_events')->count());
}
}

View File

@ -33,6 +33,15 @@ class TaskTest extends Base
$this->assertEquals(2, $task['position']);
$this->assertEquals(time(), $task['date_creation']);
$this->assertEquals(time(), $task['date_modification']);
$tasks = $t->getAll(1, 1);
$this->assertNotEmpty($tasks);
$this->assertTrue(is_array($tasks));
$this->assertEquals(1, $tasks[0]['id']);
$this->assertEquals(2, $tasks[1]['id']);
$tasks = $t->getAll(1, 0);
$this->assertEmpty($tasks);
}
public function testRemove()
@ -53,11 +62,11 @@ class TaskTest extends Base
$p = new Project($this->registry);
$this->assertEquals(1, $p->create(array('name' => 'Project #1')));
$this->assertEquals(1, $this->registry->db->table('tasks')->insert(array('title' => 'A', 'column_id' => 1, 'project_id' => 1, 'position' => 1)));
$this->assertEquals(1, $this->registry->shared('db')->table('tasks')->insert(array('title' => 'A', 'column_id' => 1, 'project_id' => 1, 'position' => 1)));
// Both tasks have the same position
$this->assertEquals(2, $this->registry->db->table('tasks')->insert(array('title' => 'B', 'column_id' => 2, 'project_id' => 1, 'position' => 1)));
$this->assertEquals(3, $this->registry->db->table('tasks')->insert(array('title' => 'C', 'column_id' => 2, 'project_id' => 1, 'position' => 1)));
$this->assertEquals(2, $this->registry->shared('db')->table('tasks')->insert(array('title' => 'B', 'column_id' => 2, 'project_id' => 1, 'position' => 1)));
$this->assertEquals(3, $this->registry->shared('db')->table('tasks')->insert(array('title' => 'C', 'column_id' => 2, 'project_id' => 1, 'position' => 1)));
// Move the first column to the last position of the 2nd column
$this->assertTrue($t->movePosition(1, 1, 2, 3));
@ -451,7 +460,7 @@ class TaskTest extends Base
// We duplicate our task
$this->assertEquals(2, $t->duplicateSameProject($task));
$this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_CREATE));
$this->assertTrue($this->registry->shared('event')->isEventTriggered(Task::EVENT_CREATE));
// Check the values of the duplicated task
$task = $t->getById(2);
@ -483,7 +492,7 @@ class TaskTest extends Base
// We duplicate our task to the 2nd project
$this->assertEquals(2, $t->duplicateToAnotherProject(2, $task));
$this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_CREATE));
$this->assertTrue($this->registry->shared('event')->isEventTriggered(Task::EVENT_CREATE));
// Check the values of the duplicated task
$task = $t->getById(2);
@ -517,7 +526,7 @@ class TaskTest extends Base
// We duplicate our task to the 2nd project
$task = $t->getById(1);
$this->assertEquals(1, $t->moveToAnotherProject(2, $task));
//$this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_CREATE));
//$this->assertTrue($this->registry->shared('event')->isEventTriggered(Task::EVENT_CREATE));
// Check the values of the duplicated task
$task = $t->getById(1);
@ -551,32 +560,32 @@ class TaskTest extends Base
// We create task
$this->assertEquals(1, $t->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 1)));
$this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_CREATE));
$this->assertTrue($this->registry->shared('event')->isEventTriggered(Task::EVENT_CREATE));
// We update a task
$this->assertTrue($t->update(array('title' => 'test2', 'id' => 1)));
$this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_UPDATE));
$this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_CREATE_UPDATE));
$this->assertTrue($this->registry->shared('event')->isEventTriggered(Task::EVENT_UPDATE));
$this->assertTrue($this->registry->shared('event')->isEventTriggered(Task::EVENT_CREATE_UPDATE));
// We close our task
$this->assertTrue($t->close(1));
$this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_CLOSE));
$this->assertTrue($this->registry->shared('event')->isEventTriggered(Task::EVENT_CLOSE));
// We open our task
$this->assertTrue($t->open(1));
$this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_OPEN));
$this->assertTrue($this->registry->shared('event')->isEventTriggered(Task::EVENT_OPEN));
// We change the column of our task
$this->assertTrue($t->movePosition(1, 1, 2, 1));
$this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_MOVE_COLUMN));
$this->assertTrue($this->registry->shared('event')->isEventTriggered(Task::EVENT_MOVE_COLUMN));
// We change the position of our task
$this->assertEquals(2, $t->create(array('title' => 'test 2', 'project_id' => 1, 'column_id' => 2)));
$this->assertTrue($t->movePosition(1, 1, 2, 2));
$this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_MOVE_POSITION));
$this->assertTrue($this->registry->shared('event')->isEventTriggered(Task::EVENT_MOVE_POSITION));
// We change the column and the position of our task
$this->assertTrue($t->movePosition(1, 1, 1, 1));
$this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_MOVE_COLUMN));
$this->assertTrue($this->registry->shared('event')->isEventTriggered(Task::EVENT_MOVE_COLUMN));
}
}

View File

@ -78,6 +78,12 @@ class Database
}
public function closeConnection()
{
$this->pdo = null;
}
public function escapeIdentifier($value)
{
return $this->pdo->escapeIdentifier($value);

View File

@ -44,7 +44,11 @@ class Table
}
}
/**
* Update
*
* Note: Do not use `rowCount()` the behaviour is different across drivers
*/
public function update(array $data)
{
$columns = array();
@ -70,7 +74,7 @@ class Table
$result = $this->db->execute($sql, $values);
return $result !== false && $result->rowCount() > 0;
return $result !== false;
}