summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/Core/Loader.php33
-rw-r--r--app/Model/Project.php31
-rw-r--r--app/Model/Task.php38
-rw-r--r--app/check_setup.php5
-rw-r--r--app/common.php179
-rw-r--r--app/constants.php70
-rw-r--r--app/functions.php131
-rw-r--r--app/translator.php43
8 files changed, 301 insertions, 229 deletions
diff --git a/app/Core/Loader.php b/app/Core/Loader.php
index 7c437654..151081c1 100644
--- a/app/Core/Loader.php
+++ b/app/Core/Loader.php
@@ -11,17 +11,29 @@ 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) {
+
+ $filename = $path.DIRECTORY_SEPARATOR.str_replace('\\', DIRECTORY_SEPARATOR, $class).'.php';
- if (file_exists($filename)) {
- require $filename;
+ 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;
+ }
}
diff --git a/app/Model/Project.php b/app/Model/Project.php
index 0ba18498..f8df1ae1 100644
--- a/app/Model/Project.php
+++ b/app/Model/Project.php
@@ -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);
}
/**
@@ -569,6 +570,18 @@ class Project extends Base
}
/**
+ * 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
*
* @access public
@@ -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' => ''));
diff --git a/app/Model/Task.php b/app/Model/Task.php
index 6f62c3d2..fcee67f7 100644
--- a/app/Model/Task.php
+++ b/app/Model/Task.php
@@ -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'];
+ }
}
/**
@@ -488,6 +492,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
*
* @access public
@@ -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();
diff --git a/app/check_setup.php b/app/check_setup.php
index 9ed16967..c4359d7a 100644
--- a/app/check_setup.php
+++ b/app/check_setup.php
@@ -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';
-}
diff --git a/app/common.php b/app/common.php
index f46e3c6b..0ba7df9d 100644
--- a/app/common.php
+++ b/app/common.php
@@ -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__.'/../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';
+require __DIR__.'/functions.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();
diff --git a/app/constants.php b/app/constants.php
new file mode 100644
index 00000000..d52997d7
--- /dev/null
+++ b/app/constants.php
@@ -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');
diff --git a/app/functions.php b/app/functions.php
new file mode 100644
index 00000000..4cbbbbfe
--- /dev/null
+++ b/app/functions.php
@@ -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;
+}
diff --git a/app/translator.php b/app/translator.php
deleted file mode 100644
index ac4d72e2..00000000
--- a/app/translator.php
+++ /dev/null
@@ -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;
-}