From 5a6cd48df19e1d5daf3f70d06052271a8340b147 Mon Sep 17 00:00:00 2001
From: Frederic Guillot
Date: Sat, 16 Jan 2016 22:03:59 -0500
Subject: Remove global
---
app/Model/File.php | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
(limited to 'app/Model/File.php')
diff --git a/app/Model/File.php b/app/Model/File.php
index daade517..be62cdb3 100644
--- a/app/Model/File.php
+++ b/app/Model/File.php
@@ -263,14 +263,16 @@ class File extends Base
public function uploadFiles($project_id, $task_id, $form_name)
{
try {
- if (empty($_FILES[$form_name])) {
+ $file = $this->request->getFileInfo($form_name);
+
+ if (empty($file)) {
return false;
}
- foreach ($_FILES[$form_name]['error'] as $key => $error) {
- if ($error == UPLOAD_ERR_OK && $_FILES[$form_name]['size'][$key] > 0) {
- $original_filename = $_FILES[$form_name]['name'][$key];
- $uploaded_filename = $_FILES[$form_name]['tmp_name'][$key];
+ foreach ($file['error'] as $key => $error) {
+ if ($error == UPLOAD_ERR_OK && $file['size'][$key] > 0) {
+ $original_filename = $file['name'][$key];
+ $uploaded_filename = $file['tmp_name'][$key];
$destination_filename = $this->generatePath($project_id, $task_id, $original_filename);
if ($this->isImage($original_filename)) {
@@ -283,7 +285,7 @@ class File extends Base
$task_id,
$original_filename,
$destination_filename,
- $_FILES[$form_name]['size'][$key]
+ $file['size'][$key]
);
}
}
--
cgit v1.2.3
From 58cef289674717027b6b470044504a661f3bd9ad Mon Sep 17 00:00:00 2001
From: Frederic Guillot
Date: Sat, 6 Feb 2016 18:08:41 -0500
Subject: The date time format can be chosen in application settings
---
ChangeLog | 1 +
app/Controller/Analytic.php | 4 +-
app/Controller/Config.php | 4 +-
app/Controller/Export.php | 2 +-
app/Controller/Task.php | 4 +-
app/Controller/Taskmodification.php | 6 +-
app/Core/DateParser.php | 215 ++++++++++++++++------------
app/Core/Translator.php | 28 ----
app/Helper/Dt.php | 46 +++++-
app/Helper/Task.php | 5 +-
app/Locale/bs_BA/translations.php | 19 +--
app/Locale/cs_CZ/translations.php | 19 +--
app/Locale/da_DK/translations.php | 19 +--
app/Locale/de_DE/translations.php | 19 +--
app/Locale/el_GR/translations.php | 19 +--
app/Locale/es_ES/translations.php | 19 +--
app/Locale/fi_FI/translations.php | 19 +--
app/Locale/fr_FR/translations.php | 19 +--
app/Locale/hu_HU/translations.php | 19 +--
app/Locale/id_ID/translations.php | 19 +--
app/Locale/it_IT/translations.php | 19 +--
app/Locale/ja_JP/translations.php | 19 +--
app/Locale/my_MY/translations.php | 19 +--
app/Locale/nb_NO/translations.php | 19 +--
app/Locale/nl_NL/translations.php | 19 +--
app/Locale/pl_PL/translations.php | 19 +--
app/Locale/pt_BR/translations.php | 19 +--
app/Locale/pt_PT/translations.php | 19 +--
app/Locale/ru_RU/translations.php | 19 +--
app/Locale/sr_Latn_RS/translations.php | 19 +--
app/Locale/sv_SE/translations.php | 19 +--
app/Locale/th_TH/translations.php | 19 +--
app/Locale/tr_TR/translations.php | 19 +--
app/Locale/zh_CN/translations.php | 19 +--
app/Model/File.php | 2 +-
app/Model/TaskCreation.php | 5 +-
app/Model/TaskExport.php | 2 +-
app/Model/TaskModification.php | 5 +-
app/Template/app/notifications.php | 2 +-
app/Template/app/tasks.php | 2 +-
app/Template/board/task_footer.php | 2 +-
app/Template/board/tooltip_comments.php | 2 +-
app/Template/comment/show.php | 2 +-
app/Template/config/application.php | 6 +
app/Template/event/events.php | 2 +-
app/Template/file/show.php | 4 +-
app/Template/listing/show.php | 2 +-
app/Template/notification/task_create.php | 4 +-
app/Template/notification/task_overdue.php | 2 +-
app/Template/project/index.php | 4 +-
app/Template/project/show.php | 6 +-
app/Template/project_user/tasks.php | 4 +-
app/Template/search/results.php | 2 +-
app/Template/task/changes.php | 4 +-
app/Template/task/details.php | 12 +-
app/Template/task/time_tracking_details.php | 4 +-
app/Template/task/transitions.php | 2 +-
app/Template/task_external_link/show.php | 2 +-
app/Template/user/last.php | 2 +-
app/Template/user/password_reset.php | 4 +-
app/Template/user/sessions.php | 4 +-
app/Template/user/timesheet.php | 4 +-
app/Validator/TaskValidator.php | 4 +-
app/functions.php | 10 --
doc/translations.markdown | 13 +-
tests/units/Core/DateParserTest.php | 182 +++++++++++++++++------
tests/units/Helper/DatetimeHelperTest.php | 52 +++++--
tests/units/Model/TaskCreationTest.php | 4 +-
tests/units/Model/TaskDuplicationTest.php | 6 +-
69 files changed, 557 insertions(+), 583 deletions(-)
(limited to 'app/Model/File.php')
diff --git a/ChangeLog b/ChangeLog
index ef58e0ac..6b9d17fd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -23,6 +23,7 @@ New features:
Improvements:
+* The date time format can be chosen in application settings
* Export only open tasks in iCal feed
* Remove time form on task summary page and move that to task edit form
* Replace box shadow by a larger border width when a task is recently modified
diff --git a/app/Controller/Analytic.php b/app/Controller/Analytic.php
index e7ab9ebc..6ce062c4 100644
--- a/app/Controller/Analytic.php
+++ b/app/Controller/Analytic.php
@@ -31,7 +31,7 @@ class Analytic extends Base
'average' => $this->averageLeadCycleTimeAnalytic->build($project['id']),
'metrics' => $this->projectDailyStats->getRawMetrics($project['id'], $from, $to),
'date_format' => $this->config->get('application_date_format'),
- 'date_formats' => $this->dateParser->getAvailableFormats(),
+ 'date_formats' => $this->dateParser->getAvailableFormats($this->dateParser->getDateFormats()),
'title' => t('Lead and Cycle time for "%s"', $project['name']),
)));
}
@@ -154,7 +154,7 @@ class Analytic extends Base
'metrics' => $display_graph ? $this->projectDailyColumnStats->getAggregatedMetrics($project['id'], $from, $to, $column) : array(),
'project' => $project,
'date_format' => $this->config->get('application_date_format'),
- 'date_formats' => $this->dateParser->getAvailableFormats(),
+ 'date_formats' => $this->dateParser->getAvailableFormats($this->dateParser->getDateFormats()),
'title' => t($title, $project['name']),
)));
}
diff --git a/app/Controller/Config.php b/app/Controller/Config.php
index 53f7cdb6..80522bbe 100644
--- a/app/Controller/Config.php
+++ b/app/Controller/Config.php
@@ -85,7 +85,9 @@ class Config extends Base
$this->response->html($this->helper->layout->config('config/application', array(
'languages' => $this->config->getLanguages(),
'timezones' => $this->config->getTimezones(),
- 'date_formats' => $this->dateParser->getAvailableFormats(),
+ 'date_formats' => $this->dateParser->getAvailableFormats($this->dateParser->getDateFormats()),
+ 'datetime_formats' => $this->dateParser->getAvailableFormats($this->dateParser->getDateTimeFormats()),
+ 'time_formats' => $this->dateParser->getAvailableFormats($this->dateParser->getTimeFormats()),
'title' => t('Settings').' > '.t('Application settings'),
)));
}
diff --git a/app/Controller/Export.php b/app/Controller/Export.php
index 977a4107..726edd42 100644
--- a/app/Controller/Export.php
+++ b/app/Controller/Export.php
@@ -37,7 +37,7 @@ class Export extends Base
),
'errors' => array(),
'date_format' => $this->config->get('application_date_format'),
- 'date_formats' => $this->dateParser->getAvailableFormats(),
+ 'date_formats' => $this->dateParser->getAvailableFormats($this->dateParser->getDateFormats()),
'project' => $project,
'title' => $page_title,
), 'export/sidebar'));
diff --git a/app/Controller/Task.php b/app/Controller/Task.php
index 40ff8448..4db8f86e 100644
--- a/app/Controller/Task.php
+++ b/app/Controller/Task.php
@@ -62,7 +62,7 @@ class Task extends Base
'time_spent' => $task['time_spent'] ?: '',
);
- $this->dateParser->format($values, array('date_started'), 'Y-m-d H:i');
+ $values = $this->dateParser->format($values, array('date_started'), $this->config->get('application_datetime_format', 'm/d/Y H:i'));
$this->response->html($this->helper->layout->task('task/show', array(
'project' => $this->project->getById($task['project_id']),
@@ -77,8 +77,6 @@ class Task extends Base
'columns_list' => $this->board->getColumnsList($task['project_id']),
'colors_list' => $this->color->getList(),
'users_list' => $this->projectUserRole->getAssignableUsersList($task['project_id'], true, false, false),
- 'date_format' => $this->config->get('application_date_format'),
- 'date_formats' => $this->dateParser->getAvailableFormats(),
'title' => $task['project_name'].' > '.$task['title'],
'recurrence_trigger_list' => $this->task->getRecurrenceTriggerList(),
'recurrence_timeframe_list' => $this->task->getRecurrenceTimeframeList(),
diff --git a/app/Controller/Taskmodification.php b/app/Controller/Taskmodification.php
index 54b4b23a..a321322d 100644
--- a/app/Controller/Taskmodification.php
+++ b/app/Controller/Taskmodification.php
@@ -82,8 +82,8 @@ class Taskmodification extends Base
$values = $this->hook->merge('controller:task:form:default', $values, array('default_values' => $values));
}
- $this->dateParser->format($values, array('date_due'));
- $this->dateParser->format($values, array('date_started'), 'Y-m-d H:i');
+ $values = $this->dateParser->format($values, array('date_due'), $this->config->get('application_date_format', 'm/d/Y'));
+ $values = $this->dateParser->format($values, array('date_started'), $this->config->get('application_datetime_format', 'm/d/Y H:i'));
$this->response->html($this->helper->layout->task('task_modification/edit_task', array(
'project' => $project,
@@ -93,8 +93,6 @@ class Taskmodification extends Base
'users_list' => $this->projectUserRole->getAssignableUsersList($task['project_id']),
'colors_list' => $this->color->getList(),
'categories_list' => $this->category->getList($task['project_id']),
- 'date_format' => $this->config->get('application_date_format'),
- 'date_formats' => $this->dateParser->getAvailableFormats(),
)));
}
diff --git a/app/Core/DateParser.php b/app/Core/DateParser.php
index 6577af0f..20e79ff9 100644
--- a/app/Core/DateParser.php
+++ b/app/Core/DateParser.php
@@ -13,67 +13,91 @@ use DateTime;
class DateParser extends Base
{
/**
- * Return true if the date is within the date range
+ * List of time formats
*
* @access public
- * @param DateTime $date
- * @param DateTime $start
- * @param DateTime $end
- * @return boolean
+ * @return string[]
*/
- public function withinDateRange(DateTime $date, DateTime $start, DateTime $end)
+ public function getTimeFormats()
{
- return $date >= $start && $date <= $end;
+ return array(
+ 'H:i',
+ 'g:i a',
+ );
}
/**
- * Get the total number of hours between 2 datetime objects
- * Minutes are rounded to the nearest quarter
+ * List of date formats
*
* @access public
- * @param DateTime $d1
- * @param DateTime $d2
- * @return float
+ * @param boolean $iso
+ * @return string[]
*/
- public function getHours(DateTime $d1, DateTime $d2)
+ public function getDateFormats($iso = false)
{
- $seconds = $this->getRoundedSeconds(abs($d1->getTimestamp() - $d2->getTimestamp()));
- return round($seconds / 3600, 2);
+ $iso_formats = array(
+ 'Y-m-d',
+ 'Y_m_d',
+ );
+
+ $user_formats = array(
+ 'm/d/Y',
+ 'd/m/Y',
+ 'Y/m/d',
+ 'd.m.Y',
+ );
+
+ return $iso ? array_merge($iso_formats, $user_formats) : $user_formats;
}
/**
- * Round the timestamp to the nearest quarter
+ * List of datetime formats
*
* @access public
- * @param integer $seconds Timestamp
- * @return integer
+ * @param boolean $iso
+ * @return string[]
*/
- public function getRoundedSeconds($seconds)
+ public function getDateTimeFormats($iso = false)
{
- return (int) round($seconds / (15 * 60)) * (15 * 60);
+ $formats = array();
+
+ foreach ($this->getDateFormats($iso) as $date) {
+ foreach ($this->getTimeFormats() as $time) {
+ $formats[] = $date.' '.$time;
+ }
+ }
+
+ return $formats;
}
/**
- * Return a timestamp if the given date format is correct otherwise return 0
+ * List of all date formats
*
* @access public
- * @param string $value Date to parse
- * @param string $format Date format
- * @return integer
+ * @param boolean $iso
+ * @return string[]
*/
- public function getValidDate($value, $format)
+ public function getAllDateFormats($iso = false)
{
- $date = DateTime::createFromFormat($format, $value);
+ return array_merge($this->getDateFormats($iso), $this->getDateTimeFormats($iso));
+ }
- if ($date !== false) {
- $errors = DateTime::getLastErrors();
- if ($errors['error_count'] === 0 && $errors['warning_count'] === 0) {
- $timestamp = $date->getTimestamp();
- return $timestamp > 0 ? $timestamp : 0;
- }
+ /**
+ * Get available formats (visible in settings)
+ *
+ * @access public
+ * @param array $formats
+ * @return array
+ */
+ public function getAvailableFormats(array $formats)
+ {
+ $values = array();
+
+ foreach ($formats as $format) {
+ $values[$format] = date($format);
}
- return 0;
+ return $values;
}
/**
@@ -85,7 +109,11 @@ class DateParser extends Base
*/
public function getTimestamp($value)
{
- foreach ($this->getAllFormats() as $format) {
+ if (ctype_digit($value)) {
+ return (int) $value;
+ }
+
+ foreach ($this->getAllDateFormats(true) as $format) {
$timestamp = $this->getValidDate($value, $format);
if ($timestamp !== 0) {
@@ -97,104 +125,103 @@ class DateParser extends Base
}
/**
- * Get ISO8601 date from user input
+ * Return a timestamp if the given date format is correct otherwise return 0
*
- * @access public
- * @param string $value Date to parse
- * @return string
+ * @access private
+ * @param string $value Date to parse
+ * @param string $format Date format
+ * @return integer
*/
- public function getIsoDate($value)
+ private function getValidDate($value, $format)
{
- return date('Y-m-d', ctype_digit($value) ? $value : $this->getTimestamp($value));
+ $date = DateTime::createFromFormat($format, $value);
+
+ if ($date !== false) {
+ $errors = DateTime::getLastErrors();
+ if ($errors['error_count'] === 0 && $errors['warning_count'] === 0) {
+ $timestamp = $date->getTimestamp();
+ return $timestamp > 0 ? $timestamp : 0;
+ }
+ }
+
+ return 0;
}
/**
- * Get all combinations of date/time formats
+ * Return true if the date is within the date range
*
* @access public
- * @return string[]
+ * @param DateTime $date
+ * @param DateTime $start
+ * @param DateTime $end
+ * @return boolean
*/
- public function getAllFormats()
+ public function withinDateRange(DateTime $date, DateTime $start, DateTime $end)
{
- $formats = array();
-
- foreach ($this->getDateFormats() as $date) {
- foreach ($this->getTimeFormats() as $time) {
- $formats[] = $date.' '.$time;
- }
- }
-
- return array_merge($formats, $this->getDateFormats());
+ return $date >= $start && $date <= $end;
}
/**
- * Return the list of supported date formats (for the parser)
+ * Get the total number of hours between 2 datetime objects
+ * Minutes are rounded to the nearest quarter
*
* @access public
- * @return string[]
+ * @param DateTime $d1
+ * @param DateTime $d2
+ * @return float
*/
- public function getDateFormats()
+ public function getHours(DateTime $d1, DateTime $d2)
{
- return array(
- $this->config->get('application_date_format', 'm/d/Y'),
- 'Y-m-d',
- 'Y_m_d',
- );
+ $seconds = $this->getRoundedSeconds(abs($d1->getTimestamp() - $d2->getTimestamp()));
+ return round($seconds / 3600, 2);
}
/**
- * Return the list of supported time formats (for the parser)
+ * Round the timestamp to the nearest quarter
*
* @access public
- * @return string[]
+ * @param integer $seconds Timestamp
+ * @return integer
*/
- public function getTimeFormats()
+ public function getRoundedSeconds($seconds)
{
- return array(
- 'H:i',
- 'g:i A',
- 'g:iA',
- );
+ return (int) round($seconds / (15 * 60)) * (15 * 60);
}
/**
- * Return the list of available date formats (for the config page)
+ * Get ISO-8601 date from user input
*
* @access public
- * @return array
+ * @param string $value Date to parse
+ * @return string
*/
- public function getAvailableFormats()
+ public function getIsoDate($value)
{
- return array(
- 'm/d/Y' => date('m/d/Y'),
- 'd/m/Y' => date('d/m/Y'),
- 'Y/m/d' => date('Y/m/d'),
- 'd.m.Y' => date('d.m.Y'),
- );
+ return date('Y-m-d', $this->getTimestamp($value));
}
/**
- * Remove the time from a timestamp
+ * Get a timetstamp from an ISO date format
*
* @access public
- * @param integer $timestamp Timestamp
+ * @param string $value
* @return integer
*/
- public function removeTimeFromTimestamp($timestamp)
+ public function getTimestampFromIsoFormat($value)
{
- return mktime(0, 0, 0, date('m', $timestamp), date('d', $timestamp), date('Y', $timestamp));
+ return $this->removeTimeFromTimestamp(ctype_digit($value) ? $value : strtotime($value));
}
/**
- * Get a timetstamp from an ISO date format
+ * Remove the time from a timestamp
*
* @access public
- * @param string $date
+ * @param integer $timestamp
* @return integer
*/
- public function getTimestampFromIsoFormat($date)
+ public function removeTimeFromTimestamp($timestamp)
{
- return $this->removeTimeFromTimestamp(ctype_digit($date) ? $date : strtotime($date));
+ return mktime(0, 0, 0, date('m', $timestamp), date('d', $timestamp), date('Y', $timestamp));
}
/**
@@ -204,13 +231,10 @@ class DateParser extends Base
* @param array $values Database values
* @param string[] $fields Date fields
* @param string $format Date format
+ * @return array
*/
- public function format(array &$values, array $fields, $format = '')
+ public function format(array $values, array $fields, $format)
{
- if ($format === '') {
- $format = $this->config->get('application_date_format');
- }
-
foreach ($fields as $field) {
if (! empty($values[$field])) {
$values[$field] = date($format, $values[$field]);
@@ -218,23 +242,28 @@ class DateParser extends Base
$values[$field] = '';
}
}
+
+ return $values;
}
/**
- * Convert date (form input data)
+ * Convert date to timestamp
*
* @access public
* @param array $values Database values
* @param string[] $fields Date fields
* @param boolean $keep_time Keep time or not
+ * @return array
*/
- public function convert(array &$values, array $fields, $keep_time = false)
+ public function convert(array $values, array $fields, $keep_time = false)
{
foreach ($fields as $field) {
- if (! empty($values[$field]) && ! is_numeric($values[$field])) {
+ if (! empty($values[$field])) {
$timestamp = $this->getTimestamp($values[$field]);
$values[$field] = $keep_time ? $timestamp : $this->removeTimeFromTimestamp($timestamp);
}
}
+
+ return $values;
}
}
diff --git a/app/Core/Translator.php b/app/Core/Translator.php
index 96a481f6..113c0dc6 100644
--- a/app/Core/Translator.php
+++ b/app/Core/Translator.php
@@ -146,32 +146,6 @@ class Translator
return $str;
}
- /**
- * Get a formatted datetime
- *
- * $translator->datetime('%Y-%m-%d', time());
- *
- * @access public
- * @param string $format Format defined by the strftime function
- * @param integer $timestamp Unix timestamp
- * @return string
- */
- public function datetime($format, $timestamp)
- {
- if (! $timestamp) {
- return '';
- }
-
- $format = $this->get($format, $format);
-
- if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
- $format = str_replace('%e', '%d', $format);
- $format = str_replace('%k', '%H', $format);
- }
-
- return strftime($format, (int) $timestamp);
- }
-
/**
* Get an identifier from the translations or return the default
*
@@ -199,8 +173,6 @@ class Translator
*/
public static function load($language, $path = self::PATH)
{
- setlocale(LC_TIME, $language.'.UTF-8', $language);
-
$filename = $path.DIRECTORY_SEPARATOR.$language.DIRECTORY_SEPARATOR.'translations.php';
if (file_exists($filename)) {
diff --git a/app/Helper/Dt.php b/app/Helper/Dt.php
index 78002b1b..eb3f93b3 100644
--- a/app/Helper/Dt.php
+++ b/app/Helper/Dt.php
@@ -12,6 +12,50 @@ use DateTime;
*/
class Dt extends \Kanboard\Core\Base
{
+ /**
+ * Get formatted time
+ *
+ * @access public
+ * @param integer $value
+ * @return string
+ */
+ public function time($value)
+ {
+ return date($this->config->get('application_time_format', 'H:i'), $value);
+ }
+
+ /**
+ * Get formatted date
+ *
+ * @access public
+ * @param integer $value
+ * @return string
+ */
+ public function date($value)
+ {
+ if (empty($value)) {
+ return '';
+ }
+
+ if (! ctype_digit($value)) {
+ $value = strtotime($value);
+ }
+
+ return date($this->config->get('application_date_format', 'm/d/Y'), $value);
+ }
+
+ /**
+ * Get formatted datetime
+ *
+ * @access public
+ * @param integer $value
+ * @return string
+ */
+ public function datetime($value)
+ {
+ return date($this->config->get('application_datetime_format', 'm/d/Y H:i'), $value);
+ }
+
/**
* Get duration in seconds into human format
*
@@ -107,6 +151,6 @@ class Dt extends \Kanboard\Core\Base
*/
public function getWeekDay($day)
{
- return dt('%A', strtotime('next Monday +'.($day - 1).' days'));
+ return date('l', strtotime('next Monday +'.($day - 1).' days'));
}
}
diff --git a/app/Helper/Task.php b/app/Helper/Task.php
index 0ef3da2c..e85d6e30 100644
--- a/app/Helper/Task.php
+++ b/app/Helper/Task.php
@@ -142,7 +142,7 @@ class Task extends Base
public function selectStartDate(array $values, array $errors = array(), array $attributes = array())
{
- $placeholder = $this->helper->text->in($this->config->get('application_date_format'), $this->dateParser->getAvailableFormats());
+ $placeholder = date($this->config->get('application_date_format', 'm/d/Y H:i'));
$attributes = array_merge(array('tabindex="11"', 'placeholder="'.$placeholder.'"'), $attributes);
$html = $this->helper->form->label(t('Start Date'), 'date_started');
@@ -153,12 +153,11 @@ class Task extends Base
public function selectDueDate(array $values, array $errors = array(), array $attributes = array())
{
- $placeholder = $this->helper->text->in($this->config->get('application_date_format'), $this->dateParser->getAvailableFormats());
+ $placeholder = date($this->config->get('application_date_format', 'm/d/Y'));
$attributes = array_merge(array('tabindex="12"', 'placeholder="'.$placeholder.'"'), $attributes);
$html = $this->helper->form->label(t('Due Date'), 'date_due');
$html .= $this->helper->form->text('date_due', $values, $errors, $attributes, 'form-date');
- $html .= ''.t('Others formats accepted: %s and %s', date('Y-m-d'), date('Y_m_d')).'
';
return $html;
}
diff --git a/app/Locale/bs_BA/translations.php b/app/Locale/bs_BA/translations.php
index b8b6a10f..e331d4a1 100644
--- a/app/Locale/bs_BA/translations.php
+++ b/app/Locale/bs_BA/translations.php
@@ -102,7 +102,6 @@ return array(
'Open a task' => 'Otvori zadatak',
'Do you really want to open this task: "%s"?' => 'Da li zaista želiš da otvoriš zadatak: "%s"?',
'Back to the board' => 'Nazad na tablu',
- 'Created on %B %e, %Y at %k:%M %p' => 'Kreiran %e %B %Y o %k:%M',
'There is nobody assigned' => 'Niko nije dodijeljen!',
'Column on the board:' => 'Kolona na tabli:',
'Close this task' => 'Zatvori ovaj zadatak',
@@ -156,7 +155,6 @@ return array(
'Work in progress' => 'U izradi',
'Done' => 'Gotovo',
'Application version:' => 'Verzija aplikacije:',
- '%B %e, %Y at %k:%M %p' => '%e %B %Y o %k:%M',
'Id' => 'Id',
'%d closed tasks' => '%d zatvorenih zadataka',
'No task for this project' => 'Nema dodijeljenih zadataka ovom projektu',
@@ -180,8 +178,6 @@ return array(
'Edit this task' => 'Uredi ovaj zadatak',
'Due Date' => 'Treba biti gotovo do dana',
'Invalid date' => 'Pogrešan datum',
- 'Must be done before %B %e, %Y' => 'Mora biti gotovo prije %e %B %Y',
- '%B %e, %Y' => '%e %B %Y',
'Automatic actions' => 'Automatske akcije',
'Your automatic action have been created successfully.' => 'Uspješno kreirana automatska akcija',
'Unable to create your automatic action.' => 'Nemoguće kreiranje automatske akcije',
@@ -317,7 +313,6 @@ return array(
'Unable to upload the file.' => 'Nije moguće snimiti fajl.',
'Display another project' => 'Prikaži drugi projekat',
'Created by %s' => 'Kreirao %s',
- 'Last modified on %B %e, %Y at %k:%M %p' => 'Posljednja izmjena %e %B %Y o %k:%M',
'Tasks Export' => 'Izvoz zadataka',
'Tasks exportation for "%s"' => 'Izvoz zadataka za "%s"',
'Start Date' => 'Početni datum',
@@ -589,7 +584,6 @@ return array(
'This task' => 'Ovaj zadatak',
'<1h' => '<1h',
'%dh' => '%dh',
- '%b %e' => '%b %e',
'Expand tasks' => 'Proširi zadatke',
'Collapse tasks' => 'Skupi zadatke',
'Expand/collapse tasks' => 'Proširi/skupi zadatke',
@@ -758,10 +752,6 @@ return array(
'Only for tasks assigned to me' => 'Samo za zadatke na kojima sam izvršilac',
'Only for tasks created by me' => 'Samo za zadatke koje sam ja napravio',
'Only for tasks created by me and assigned to me' => 'Samo za zadatke koje sam ja napravio i na kojima sam izvršilac',
- '%A' => '%A',
- '%b %e, %Y, %k:%M %p' => '%b %e, %Y, %k:%M %p',
- 'New due date: %B %e, %Y' => 'Novi datum završetka: %B %e, %Y',
- 'Start date changed: %B %e, %Y' => 'Početni datum promijenjen: %B %e, %Y',
'%%Y-%%m-%%d' => '%%Y-%%m-%%d',
'Total for all columns' => 'Ukupno za sve kolone',
'You need at least 2 days of data to show the chart.' => 'Da bi se prikazao ovaj grafik potrebni su podaci iz najmanje posljednja dva dana.',
@@ -786,7 +776,6 @@ return array(
'Not assigned' => 'Bez izvršioca',
'View advanced search syntax' => 'Vidi naprednu sintaksu pretrage',
'Overview' => 'Opšti pregled',
- '%b %e %Y' => '%b %e %Y',
'Board/Calendar/List view' => 'Pregle Table/Kalendara/Liste',
'Switch to the board view' => 'Promijeni da vidim tablu',
'Switch to the calendar view' => 'Promijeni da vidim kalendar',
@@ -876,8 +865,6 @@ return array(
'End date:' => 'Datum završetka:',
'There is no start date or end date for this project.' => 'Nema početnog ili krajnjeg datuma za ovaj projekat.',
'Projects Gantt chart' => 'Gantogram projekata',
- 'Start date: %s' => 'Početni datum: %s',
- 'End date: %s' => 'Datum završetka: %s',
'Link type' => 'Tip veze',
'Change task color when using a specific task link' => 'Promijeni boju zadatka kada se koristi određena veza na zadatku',
'Task link creation or modification' => 'Veza na zadatku je napravljena ili izmijenjena',
@@ -1125,4 +1112,10 @@ return array(
// 'Moved:' => '',
// 'Task #%d' => '',
// 'Sub-tasks' => '',
+ // 'Date and time format' => '',
+ // 'Time format' => '',
+ // 'Start date: ' => '',
+ // 'End date: ' => '',
+ // 'New due date: ' => '',
+ // 'Start date changed: ' => '',
);
diff --git a/app/Locale/cs_CZ/translations.php b/app/Locale/cs_CZ/translations.php
index cb99e404..a495f01e 100644
--- a/app/Locale/cs_CZ/translations.php
+++ b/app/Locale/cs_CZ/translations.php
@@ -102,7 +102,6 @@ return array(
'Open a task' => 'Otevřít úkol',
'Do you really want to open this task: "%s"?' => 'Opravdu chcete znovuotevřít tento úkol: "%s"?',
'Back to the board' => 'Zpět na nástěnku',
- 'Created on %B %e, %Y at %k:%M %p' => 'Vytvořeno dne %d.%m.%Y v čase %H:%M',
'There is nobody assigned' => 'Není přiřazeno žádnému uživateli',
'Column on the board:' => 'Sloupec:',
'Close this task' => 'Uzavřít úkol',
@@ -156,7 +155,6 @@ return array(
'Work in progress' => 'V řešení',
'Done' => 'Dokončeno',
'Application version:' => 'Verze:',
- '%B %e, %Y at %k:%M %p' => '%d.%m.%Y v %H:%M',
'Id' => 'ID',
'%d closed tasks' => '%d dokončených úkolů',
'No task for this project' => 'Tento projekt nemá žádné úkoly',
@@ -180,8 +178,6 @@ return array(
'Edit this task' => 'Editace úkolu',
'Due Date' => 'Datum splnění',
'Invalid date' => 'Neplatné datum',
- 'Must be done before %B %e, %Y' => 'Musí být dokončeno do %d.%m.%Y ',
- '%B %e, %Y' => '%d.%m.%Y',
'Automatic actions' => 'Automaticky vykonávané akce',
'Your automatic action have been created successfully.' => 'Vaše akce byla úspěšně vytvořena.',
'Unable to create your automatic action.' => 'Vaší akci nebylo možné vytvořit.',
@@ -317,7 +313,6 @@ return array(
'Unable to upload the file.' => 'Soubor nelze nahrát.',
'Display another project' => 'Zobrazit jiný projekt',
'Created by %s' => 'Vytvořeno uživatelem %s',
- 'Last modified on %B %e, %Y at %k:%M %p' => 'Poslední úprava dne %d.%m.%Y v čase %H:%M',
'Tasks Export' => 'Export úkolů',
'Tasks exportation for "%s"' => 'Export úkolů pro "%s"',
'Start Date' => 'Počáteční datum',
@@ -589,7 +584,6 @@ return array(
'This task' => 'Tento úkol',
'<1h' => '<1h',
'%dh' => '%dh',
- // '%b %e' => '',
'Expand tasks' => 'Rozpbalit úkoly',
'Collapse tasks' => 'Sbalit úkoly',
'Expand/collapse tasks' => 'Rozbalit / sbalit úkoly',
@@ -758,10 +752,6 @@ return array(
'Only for tasks assigned to me' => 'pouze pro moje úkoly',
'Only for tasks created by me' => 'pouze pro mnou vytvořené úkoly',
'Only for tasks created by me and assigned to me' => 'pouze pro mnou vytvořené a mě přiřazené úkoly',
- // '%A' => '',
- // '%b %e, %Y, %k:%M %p' => '',
- 'New due date: %B %e, %Y' => 'Neues Ablaufdatum: %B %e, %Y',
- 'Start date changed: %B %e, %Y' => 'Neues Beginndatum: %B %e, %Y',
// '%%Y-%%m-%%d' => '',
'Total for all columns' => 'S',
'You need at least 2 days of data to show the chart.' => 'Potřebujete nejméně data ze dvou dnů pro zobrazení grafu',
@@ -786,7 +776,6 @@ return array(
'Not assigned' => 'Nepřiřazené',
'View advanced search syntax' => 'Zobrazit syntaxi rozšířeného vyhledávání',
'Overview' => 'Přehled',
- '%b %e %Y' => '%b %e %Y',
'Board/Calendar/List view' => 'Nástěnka/Kalendář/Zobrazení seznamu',
'Switch to the board view' => 'Přepnout na nástěnku',
'Switch to the calendar view' => 'Přepnout na kalendář',
@@ -876,8 +865,6 @@ return array(
// 'End date:' => '',
// 'There is no start date or end date for this project.' => '',
// 'Projects Gantt chart' => '',
- // 'Start date: %s' => '',
- // 'End date: %s' => '',
// 'Link type' => '',
// 'Change task color when using a specific task link' => '',
// 'Task link creation or modification' => '',
@@ -1125,4 +1112,10 @@ return array(
// 'Moved:' => '',
// 'Task #%d' => '',
// 'Sub-tasks' => '',
+ // 'Date and time format' => '',
+ // 'Time format' => '',
+ // 'Start date: ' => '',
+ // 'End date: ' => '',
+ // 'New due date: ' => '',
+ // 'Start date changed: ' => '',
);
diff --git a/app/Locale/da_DK/translations.php b/app/Locale/da_DK/translations.php
index b61fcd4a..537b6349 100644
--- a/app/Locale/da_DK/translations.php
+++ b/app/Locale/da_DK/translations.php
@@ -102,7 +102,6 @@ return array(
'Open a task' => 'Åben en opgave',
'Do you really want to open this task: "%s"?' => 'Vil du virkelig åbne denne opgave: "%s"?',
'Back to the board' => 'Tilbage til boardet',
- 'Created on %B %e, %Y at %k:%M %p' => 'Oprettet %d.%m.%Y - %H:%M',
'There is nobody assigned' => 'Der er ingen tilføjet',
'Column on the board:' => 'Kolonne:',
'Close this task' => 'Luk denne opgave',
@@ -156,7 +155,6 @@ return array(
'Work in progress' => 'Igangværende',
'Done' => 'Færdig',
'Application version:' => 'Version:',
- '%B %e, %Y at %k:%M %p' => '%d.%m.%Y - %H:%M',
'Id' => 'ID',
'%d closed tasks' => '%d lukket opgavet',
'No task for this project' => 'Ingen opgaver i dette projekt',
@@ -180,8 +178,6 @@ return array(
'Edit this task' => 'Rediger denne opgave',
'Due Date' => 'Forfaldsdato',
'Invalid date' => 'Ugyldig dato',
- 'Must be done before %B %e, %Y' => 'Skal være fuldført inden %d.%m.%Y',
- '%B %e, %Y' => '%d.%m.%Y',
'Automatic actions' => 'Automatiske handlinger',
'Your automatic action have been created successfully.' => 'Din automatiske handling er oprettet.',
'Unable to create your automatic action.' => 'Din automatiske handling kunne ikke oprettes.',
@@ -317,7 +313,6 @@ return array(
'Unable to upload the file.' => 'Filen kunne ikke uploades.',
'Display another project' => 'Vis et andet projekt...',
'Created by %s' => 'Oprettet af %s',
- 'Last modified on %B %e, %Y at %k:%M %p' => 'Sidst redigeret %d.%m.%Y - %H:%M',
'Tasks Export' => 'Opgave eksport',
'Tasks exportation for "%s"' => 'Opgave eksport for "%s"',
'Start Date' => 'Start-dato',
@@ -589,7 +584,6 @@ return array(
// 'This task' => '',
// '<1h' => '',
// '%dh' => '',
- // '%b %e' => '',
// 'Expand tasks' => '',
// 'Collapse tasks' => '',
// 'Expand/collapse tasks' => '',
@@ -758,10 +752,6 @@ return array(
// 'Only for tasks assigned to me' => '',
// 'Only for tasks created by me' => '',
// 'Only for tasks created by me and assigned to me' => '',
- // '%A' => '',
- // '%b %e, %Y, %k:%M %p' => '',
- // 'New due date: %B %e, %Y' => '',
- // 'Start date changed: %B %e, %Y' => '',
// '%%Y-%%m-%%d' => '',
// 'Total for all columns' => '',
// 'You need at least 2 days of data to show the chart.' => '',
@@ -786,7 +776,6 @@ return array(
// 'Not assigned' => '',
// 'View advanced search syntax' => '',
// 'Overview' => '',
- // '%b %e %Y' => '',
// 'Board/Calendar/List view' => '',
// 'Switch to the board view' => '',
// 'Switch to the calendar view' => '',
@@ -876,8 +865,6 @@ return array(
// 'End date:' => '',
// 'There is no start date or end date for this project.' => '',
// 'Projects Gantt chart' => '',
- // 'Start date: %s' => '',
- // 'End date: %s' => '',
// 'Link type' => '',
// 'Change task color when using a specific task link' => '',
// 'Task link creation or modification' => '',
@@ -1125,4 +1112,10 @@ return array(
// 'Moved:' => '',
// 'Task #%d' => '',
// 'Sub-tasks' => '',
+ // 'Date and time format' => '',
+ // 'Time format' => '',
+ // 'Start date: ' => '',
+ // 'End date: ' => '',
+ // 'New due date: ' => '',
+ // 'Start date changed: ' => '',
);
diff --git a/app/Locale/de_DE/translations.php b/app/Locale/de_DE/translations.php
index a15b96d7..ba6a1fd4 100644
--- a/app/Locale/de_DE/translations.php
+++ b/app/Locale/de_DE/translations.php
@@ -102,7 +102,6 @@ return array(
'Open a task' => 'Öffne eine Aufgabe',
'Do you really want to open this task: "%s"?' => 'Soll diese Aufgabe wirklich wieder geöffnet werden: "%s"?',
'Back to the board' => 'Zurück zur Pinnwand',
- 'Created on %B %e, %Y at %k:%M %p' => 'Erstellt am %d.%m.%Y um %H:%M',
'There is nobody assigned' => 'Die Aufgabe wurde niemandem zugewiesen',
'Column on the board:' => 'Spalte:',
'Close this task' => 'Aufgabe schließen',
@@ -156,7 +155,6 @@ return array(
'Work in progress' => 'In Arbeit',
'Done' => 'Erledigt',
'Application version:' => 'Version:',
- '%B %e, %Y at %k:%M %p' => '%d.%m.%Y um %H:%M',
'Id' => 'ID',
'%d closed tasks' => '%d abgeschlossene Aufgaben',
'No task for this project' => 'Keine Aufgaben in diesem Projekt',
@@ -180,8 +178,6 @@ return array(
'Edit this task' => 'Aufgabe bearbeiten',
'Due Date' => 'Fällig am',
'Invalid date' => 'Ungültiges Datum',
- 'Must be done before %B %e, %Y' => 'Muss vor dem %d.%m.%Y erledigt werden',
- '%B %e, %Y' => '%d.%m.%Y',
'Automatic actions' => 'Automatische Aktionen',
'Your automatic action have been created successfully.' => 'Die automatische Aktion wurde erfolgreich erstellt.',
'Unable to create your automatic action.' => 'Erstellen der automatischen Aktion nicht möglich.',
@@ -317,7 +313,6 @@ return array(
'Unable to upload the file.' => 'Hochladen der Datei nicht möglich.',
'Display another project' => 'Zu Projekt wechseln',
'Created by %s' => 'Erstellt durch %s',
- 'Last modified on %B %e, %Y at %k:%M %p' => 'Letzte Änderung am %d.%m.%Y um %H:%M',
'Tasks Export' => 'Aufgaben exportieren',
'Tasks exportation for "%s"' => 'Aufgaben exportieren für "%s"',
'Start Date' => 'Anfangsdatum',
@@ -589,7 +584,6 @@ return array(
'This task' => 'Diese Aufgabe',
'<1h' => '<1Std',
'%dh' => '%dStd',
- // '%b %e' => '',
'Expand tasks' => 'Aufgaben aufklappen',
'Collapse tasks' => 'Aufgaben zusammenklappen',
'Expand/collapse tasks' => 'Aufgaben auf/zuklappen',
@@ -758,10 +752,6 @@ return array(
'Only for tasks assigned to me' => 'nur mir zugeordnete Aufgane',
'Only for tasks created by me' => 'nur von mir erstellte Aufgaben',
'Only for tasks created by me and assigned to me' => 'nur mir zugeordnete und von mir erstellte Aufgaben',
- '%A' => '%A',
- '%b %e, %Y, %k:%M %p' => '%b %e, %Y, %k:%M %p',
- 'New due date: %B %e, %Y' => 'Neues Ablaufdatum: %B %e, %Y',
- 'Start date changed: %B %e, %Y' => 'Neues Beginndatum: %B %e, %Y',
'%%Y-%%m-%%d' => '%%d.%%m.%%Y',
'Total for all columns' => 'Gesamt für alle Spalten',
'You need at least 2 days of data to show the chart.' => 'Es werden mindestens 2 Tage zur Darstellung benötigt',
@@ -786,7 +776,6 @@ return array(
'Not assigned' => 'Nicht zugewiesen',
'View advanced search syntax' => 'Zur erweiterten Suchsyntax',
'Overview' => 'Überblick',
- '%b %e %Y' => '%b %e %Y',
'Board/Calendar/List view' => 'Board-/Kalender-/Listen-Ansicht',
'Switch to the board view' => 'Zur Board-Ansicht',
'Switch to the calendar view' => 'Zur Kalender-Ansicht',
@@ -876,8 +865,6 @@ return array(
'End date:' => 'Endedatum:',
'There is no start date or end date for this project.' => 'Es gibt kein Startdatum oder Endedatum für dieses Projekt',
'Projects Gantt chart' => 'Projekt Gantt Diagramm',
- 'Start date: %s' => 'Beginndatum: %s',
- 'End date: %s' => 'Enddatum: %s',
'Link type' => 'Verbindungstyp',
'Change task color when using a specific task link' => 'Aufgabefarbe ändern bei bestimmter Aufgabenverbindung',
'Task link creation or modification' => 'Aufgabenverbindung erstellen oder bearbeiten',
@@ -1125,4 +1112,10 @@ return array(
// 'Moved:' => '',
// 'Task #%d' => '',
// 'Sub-tasks' => '',
+ // 'Date and time format' => '',
+ // 'Time format' => '',
+ // 'Start date: ' => '',
+ // 'End date: ' => '',
+ // 'New due date: ' => '',
+ // 'Start date changed: ' => '',
);
diff --git a/app/Locale/el_GR/translations.php b/app/Locale/el_GR/translations.php
index 9fb1e0bf..01b31819 100644
--- a/app/Locale/el_GR/translations.php
+++ b/app/Locale/el_GR/translations.php
@@ -102,7 +102,6 @@ return array(
'Open a task' => 'Άνοιγμα εργασίας',
'Do you really want to open this task: "%s"?' => 'Άνοιγμα της εργασίας : « %s » ?',
'Back to the board' => 'Επιστροφή στον κεντρικό πίνακα έργου',
- 'Created on %B %e, %Y at %k:%M %p' => 'Δημιουργήθηκε στις %d/%m/%Y και ώρα %H:%M',
'There is nobody assigned' => 'Δεν έχει ανατεθεί σε κανένα',
'Column on the board:' => 'Στήλη στον κεντρικό πίνακα : ',
'Close this task' => 'Κλείσιμο εργασίας',
@@ -156,7 +155,6 @@ return array(
'Work in progress' => 'Σε πρόοδο',
'Done' => 'Ολοκληρωμένα',
'Application version:' => 'Version εφαρμογής :',
- '%B %e, %Y at %k:%M %p' => '%d/%m/%Y και ώρα %H:%M',
'Id' => 'Αναγνωριστικό.',
'%d closed tasks' => '%d κλειστές εργασίες',
'No task for this project' => 'Αριθμός εργασιών για το έργο',
@@ -180,8 +178,6 @@ return array(
'Edit this task' => 'Διόρθωση εργασίας',
'Due Date' => 'Μέχρι την ημερομηνία',
'Invalid date' => 'Μη ορθή ημερομηνία',
- 'Must be done before %B %e, %Y' => 'Πρέπει να ολοκληρωθεί πριν τις %d/%m/%Y',
- '%B %e, %Y' => '%d %B %Y',
'Automatic actions' => 'Αυτόματες ενέργειες',
'Your automatic action have been created successfully.' => 'Η αυτόματη ενέργεια δημιουργήθηκε με επιτυχία.',
'Unable to create your automatic action.' => 'Impossible de créer votre action automatisée.',
@@ -317,7 +313,6 @@ return array(
'Unable to upload the file.' => 'Δεν είναι δυνατή η μεταφόρτωση του αρχείου.',
'Display another project' => 'Εμφάνιση άλλου έργου',
'Created by %s' => 'Δημιουργήθηκε από %s',
- 'Last modified on %B %e, %Y at %k:%M %p' => 'Τελευταία ενημέρωση: %d/%m/%Y à %H:%M',
'Tasks Export' => 'Εξαγωγή εργασιών',
'Tasks exportation for "%s"' => 'Εξαγωγή εργασιών για το έργο « %s »',
'Start Date' => 'Ημερομηνία έναρξης',
@@ -589,7 +584,6 @@ return array(
'This task' => 'Αυτή η εργασία',
'<1h' => '<1ωρ',
'%dh' => '%dωρ',
- '%b %e' => '%e %b',
'Expand tasks' => 'Ανάπτυξη εργασιών',
'Collapse tasks' => 'Σύμπτυξη εργασιών',
'Expand/collapse tasks' => 'Ανάπτυξη/σύμπτυξη εργασιών',
@@ -758,10 +752,6 @@ return array(
'Only for tasks assigned to me' => 'Μόνο σε εργασίες που μου έχουν ανατεθεί',
'Only for tasks created by me' => 'Μόνο σε εργασίες που έχουν δημιουργηθεί από εμένα',
'Only for tasks created by me and assigned to me' => 'Μόνο σε εργασίες που έχουν δημιουργηθεί από εμένα και μου έχουν ανατεθεί',
- '%A' => '%A',
- '%b %e, %Y, %k:%M %p' => '%d/%m/%Y %H:%M',
- 'New due date: %B %e, %Y' => 'Νέα ημέρα καθηκόντων : %d/%m/%Y',
- 'Start date changed: %B %e, %Y' => 'Ημέρα εκκίνησης άλλαξε : %d/%m/%Y',
'%%Y-%%m-%%d' => '%%d/%%m/%%Y',
'Total for all columns' => 'Σύνολο για όλες τις στήλες',
'You need at least 2 days of data to show the chart.' => 'Έχετε τουλάχιστον 2 ημέρες δεδομένων για να εμφανιστούν στο διάγραμμα.',
@@ -786,7 +776,6 @@ return array(
'Not assigned' => 'Δεν έχουν εκχωρηθεί',
'View advanced search syntax' => 'Δείτε τη σύνταξη "αναζήτησης για προχωρημένους"',
'Overview' => 'Επισκόπηση',
- '%b %e %Y' => '%b %e %Y',
'Board/Calendar/List view' => 'Πίνακας / Ημερολόγιο / Προβολή λίστας',
'Switch to the board view' => 'Εναλλαγή στην προβολή του πίνακα',
'Switch to the calendar view' => 'Εναλλαγή στην προβολή ημερολογίου',
@@ -876,8 +865,6 @@ return array(
'End date:' => 'Ημερομηνία λήξης :',
'There is no start date or end date for this project.' => 'Δεν υπάρχει ημερομηνία έναρξης ή λήξης για το έργο αυτό.',
'Projects Gantt chart' => 'Διάγραμμα Gantt έργων',
- 'Start date: %s' => 'Ημερομηνία αρχής : %s',
- 'End date: %s' => 'Ημερομηνία τέλους : %s',
'Link type' => 'Τύπος συνδέσμου',
'Change task color when using a specific task link' => 'Αλλαγή χρώματος εργασίας χρησιμοποιώντας συγκεκριμένο σύνδεσμο εργασίας',
'Task link creation or modification' => 'Σύνδεσμος δημιουργίας ή τροποποίησης εργασίας',
@@ -1125,4 +1112,10 @@ return array(
// 'Moved:' => '',
// 'Task #%d' => '',
// 'Sub-tasks' => '',
+ // 'Date and time format' => '',
+ // 'Time format' => '',
+ // 'Start date: ' => '',
+ // 'End date: ' => '',
+ // 'New due date: ' => '',
+ // 'Start date changed: ' => '',
);
diff --git a/app/Locale/es_ES/translations.php b/app/Locale/es_ES/translations.php
index e2bdd0da..9c7c6e41 100644
--- a/app/Locale/es_ES/translations.php
+++ b/app/Locale/es_ES/translations.php
@@ -102,7 +102,6 @@ return array(
'Open a task' => 'Abrir una tarea',
'Do you really want to open this task: "%s"?' => '¿Realmente desea abrir esta tarea: « %s » ?',
'Back to the board' => 'Volver al tablero',
- 'Created on %B %e, %Y at %k:%M %p' => 'Creado el %e de %B de %Y a las %k:%M %p',
'There is nobody assigned' => 'No hay nadie asignado a esta tarea',
'Column on the board:' => 'Columna en el tablero: ',
'Close this task' => 'Cerrar esta tarea',
@@ -156,7 +155,6 @@ return array(
'Work in progress' => 'En curso',
'Done' => 'Hecho',
'Application version:' => 'Versión de la aplicación:',
- '%B %e, %Y at %k:%M %p' => '%e de %B de %Y a las %k:%M %p',
'Id' => 'Identificador',
'%d closed tasks' => '%d tareas completadas',
'No task for this project' => 'Ninguna tarea para este proyecto',
@@ -180,8 +178,6 @@ return array(
'Edit this task' => 'Editar esta tarea',
'Due Date' => 'Fecha límite',
'Invalid date' => 'Fecha no válida',
- 'Must be done before %B %e, %Y' => 'Debe de estar hecho antes del %e de %B de %Y',
- '%B %e, %Y' => '%e de %B de %Y',
'Automatic actions' => 'Acciones automatizadas',
'Your automatic action have been created successfully.' => 'La acción automatizada ha sido creada correctamente.',
'Unable to create your automatic action.' => 'No se puede crear esta acción automatizada.',
@@ -317,7 +313,6 @@ return array(
'Unable to upload the file.' => 'No pude cargar el fichero.',
'Display another project' => 'Mostrar otro proyecto',
'Created by %s' => 'Creado por %s',
- 'Last modified on %B %e, %Y at %k:%M %p' => 'Última modificación %e de %B de %Y a las %k:%M %p',
'Tasks Export' => 'Exportar tareas',
'Tasks exportation for "%s"' => 'Exportación de tareas para "%s"',
'Start Date' => 'Fecha de inicio',
@@ -589,7 +584,6 @@ return array(
'This task' => 'Esta tarea',
'<1h' => '<1h',
'%dh' => '%dh',
- '%b %e' => '%e de %b',
'Expand tasks' => 'Espande tareas',
'Collapse tasks' => 'Colapsa tareas',
'Expand/collapse tasks' => 'Expande/colapasa tareas',
@@ -758,10 +752,6 @@ return array(
'Only for tasks assigned to me' => 'Sólo para las tareas que me han sido asignadas',
'Only for tasks created by me' => 'Sólo para las taread creadas por mí',
'Only for tasks created by me and assigned to me' => 'Sólo para las tareas credas por mí y que me han sido asignadas',
- '%A' => '%A',
- '%b %e, %Y, %k:%M %p' => '%e de %B de %Y a las %k:%M %p',
- 'New due date: %B %e, %Y' => 'Nueva fecha de entrega: %B %e, %Y',
- 'Start date changed: %B %e, %Y' => 'Cambiadad fecha de inicio: %B %e, %Y',
'%%Y-%%m-%%d' => '%%d/%%M/%%Y',
'Total for all columns' => 'Total para todas las columnas',
'You need at least 2 days of data to show the chart.' => 'Necesitas al menos 2 días de datos para mostrar el gráfico.',
@@ -786,7 +776,6 @@ return array(
'Not assigned' => 'No asignada',
'View advanced search syntax' => 'Ver sintáxis avanzada de búsqueda',
'Overview' => 'Resumen',
- '%b %e %Y' => '%e de %B de %Y',
'Board/Calendar/List view' => 'Vista de Tablero/Calendario/Lista',
'Switch to the board view' => 'Cambiar a vista de tablero',
'Switch to the calendar view' => 'Cambiar a vista de calendario',
@@ -876,8 +865,6 @@ return array(
'End date:' => 'Fecha final',
'There is no start date or end date for this project.' => 'No existe fecha de inicio o de fin para este proyecto.',
'Projects Gantt chart' => 'Diagramas de Gantt de los proyectos',
- 'Start date: %s' => 'Fecha inicial: %s',
- 'End date: %s' => 'Fecha final: %s',
'Link type' => 'Tipo de enlace',
'Change task color when using a specific task link' => 'Cambiar colo de la tarea al usar un enlace específico a tarea',
'Task link creation or modification' => 'Creación o modificación de enlace a tarea',
@@ -1125,4 +1112,10 @@ return array(
// 'Moved:' => '',
// 'Task #%d' => '',
// 'Sub-tasks' => '',
+ // 'Date and time format' => '',
+ // 'Time format' => '',
+ // 'Start date: ' => '',
+ // 'End date: ' => '',
+ // 'New due date: ' => '',
+ // 'Start date changed: ' => '',
);
diff --git a/app/Locale/fi_FI/translations.php b/app/Locale/fi_FI/translations.php
index f8b846bb..d50765b6 100644
--- a/app/Locale/fi_FI/translations.php
+++ b/app/Locale/fi_FI/translations.php
@@ -102,7 +102,6 @@ return array(
'Open a task' => 'Avaa tehtävä',
'Do you really want to open this task: "%s"?' => 'Haluatko varmasti avata tehtävän: "%s"?',
'Back to the board' => 'Takaisin tauluun',
- 'Created on %B %e, %Y at %k:%M %p' => 'Luotu %d.%m.%Y kello %H:%M',
'There is nobody assigned' => 'Ei suorittajaa',
'Column on the board:' => 'Sarake taululla: ',
'Close this task' => 'Sulje tämä tehtävä',
@@ -156,7 +155,6 @@ return array(
'Work in progress' => 'Työnalla',
'Done' => 'Tehty',
'Application version:' => 'Ohjelman versio:',
- '%B %e, %Y at %k:%M %p' => '%d.%m.%Y kello %H:%M',
'Id' => 'Id',
'%d closed tasks' => '%d suljettua tehtävää',
'No task for this project' => 'Ei tehtävää tälle projektille',
@@ -180,8 +178,6 @@ return array(
'Edit this task' => 'Muokkaa tehtävää',
'Due Date' => 'Deadline',
'Invalid date' => 'Virheellinen päiväys',
- 'Must be done before %B %e, %Y' => 'Täytyy suorittaa ennen %d.%m.%Y',
- '%B %e, %Y' => '%d.%m.%Y',
'Automatic actions' => 'Automaattiset toiminnot',
'Your automatic action have been created successfully.' => 'Toiminto suoritettiin onnistuneesti.',
'Unable to create your automatic action.' => 'Automaattisen toiminnon luominen epäonnistui.',
@@ -317,7 +313,6 @@ return array(
'Unable to upload the file.' => 'Tiedoston lataus epäonnistui.',
'Display another project' => 'Näytä toinen projekti',
'Created by %s' => 'Luonut: %s',
- 'Last modified on %B %e, %Y at %k:%M %p' => 'Viimeksi muokattu %B %e, %Y kello %H:%M',
'Tasks Export' => 'Tehtävien vienti',
'Tasks exportation for "%s"' => 'Tehtävien vienti projektilta "%s"',
'Start Date' => 'Aloituspäivä',
@@ -589,7 +584,6 @@ return array(
// 'This task' => '',
// '<1h' => '',
// '%dh' => '',
- // '%b %e' => '',
// 'Expand tasks' => '',
// 'Collapse tasks' => '',
// 'Expand/collapse tasks' => '',
@@ -758,10 +752,6 @@ return array(
// 'Only for tasks assigned to me' => '',
// 'Only for tasks created by me' => '',
// 'Only for tasks created by me and assigned to me' => '',
- // '%A' => '',
- // '%b %e, %Y, %k:%M %p' => '',
- // 'New due date: %B %e, %Y' => '',
- // 'Start date changed: %B %e, %Y' => '',
// '%%Y-%%m-%%d' => '',
// 'Total for all columns' => '',
// 'You need at least 2 days of data to show the chart.' => '',
@@ -786,7 +776,6 @@ return array(
// 'Not assigned' => '',
// 'View advanced search syntax' => '',
// 'Overview' => '',
- // '%b %e %Y' => '',
// 'Board/Calendar/List view' => '',
// 'Switch to the board view' => '',
// 'Switch to the calendar view' => '',
@@ -876,8 +865,6 @@ return array(
// 'End date:' => '',
// 'There is no start date or end date for this project.' => '',
// 'Projects Gantt chart' => '',
- // 'Start date: %s' => '',
- // 'End date: %s' => '',
// 'Link type' => '',
// 'Change task color when using a specific task link' => '',
// 'Task link creation or modification' => '',
@@ -1125,4 +1112,10 @@ return array(
// 'Moved:' => '',
// 'Task #%d' => '',
// 'Sub-tasks' => '',
+ // 'Date and time format' => '',
+ // 'Time format' => '',
+ // 'Start date: ' => '',
+ // 'End date: ' => '',
+ // 'New due date: ' => '',
+ // 'Start date changed: ' => '',
);
diff --git a/app/Locale/fr_FR/translations.php b/app/Locale/fr_FR/translations.php
index 1beef993..90d6dc3d 100644
--- a/app/Locale/fr_FR/translations.php
+++ b/app/Locale/fr_FR/translations.php
@@ -102,7 +102,6 @@ return array(
'Open a task' => 'Ouvrir une tâche',
'Do you really want to open this task: "%s"?' => 'Voulez-vous vraiment ouvrir cette tâche : « %s » ?',
'Back to the board' => 'Retour au tableau',
- 'Created on %B %e, %Y at %k:%M %p' => 'Créé le %d/%m/%Y à %H:%M',
'There is nobody assigned' => 'Il n\'y a personne d\'assigné à cette tâche',
'Column on the board:' => 'Colonne sur le tableau : ',
'Close this task' => 'Fermer cette tâche',
@@ -156,7 +155,6 @@ return array(
'Work in progress' => 'En cours',
'Done' => 'Terminé',
'Application version:' => 'Version de l\'application :',
- '%B %e, %Y at %k:%M %p' => '%d/%m/%Y à %H:%M',
'Id' => 'Id.',
'%d closed tasks' => '%d tâches terminées',
'No task for this project' => 'Aucune tâche pour ce projet',
@@ -180,8 +178,6 @@ return array(
'Edit this task' => 'Modifier cette tâche',
'Due Date' => 'Date d\'échéance',
'Invalid date' => 'Date invalide',
- 'Must be done before %B %e, %Y' => 'Doit être fait avant le %d/%m/%Y',
- '%B %e, %Y' => '%d %B %Y',
'Automatic actions' => 'Actions automatisées',
'Your automatic action have been created successfully.' => 'Votre action automatisée a été ajoutée avec succès.',
'Unable to create your automatic action.' => 'Impossible de créer votre action automatisée.',
@@ -317,7 +313,6 @@ return array(
'Unable to upload the file.' => 'Impossible de transférer le fichier.',
'Display another project' => 'Afficher un autre projet',
'Created by %s' => 'Créé par %s',
- 'Last modified on %B %e, %Y at %k:%M %p' => 'Modifié le %d/%m/%Y à %H:%M',
'Tasks Export' => 'Exportation des tâches',
'Tasks exportation for "%s"' => 'Exportation des tâches pour « %s »',
'Start Date' => 'Date de début',
@@ -591,7 +586,6 @@ return array(
'This task' => 'Cette tâche',
'<1h' => '<1h',
'%dh' => '%dh',
- '%b %e' => '%e %b',
'Expand tasks' => 'Déplier les tâches',
'Collapse tasks' => 'Replier les tâches',
'Expand/collapse tasks' => 'Plier/déplier les tâches',
@@ -760,10 +754,6 @@ return array(
'Only for tasks assigned to me' => 'Seulement les tâches qui me sont assignées',
'Only for tasks created by me' => 'Seulement les tâches que j\'ai créées',
'Only for tasks created by me and assigned to me' => 'Seulement les tâches créées par moi-même et celles qui me sont assignées',
- '%A' => '%A',
- '%b %e, %Y, %k:%M %p' => '%d/%m/%Y %H:%M',
- 'New due date: %B %e, %Y' => 'Nouvelle date d\'échéance : %d/%m/%Y',
- 'Start date changed: %B %e, %Y' => 'Date de début modifiée : %d/%m/%Y',
'%%Y-%%m-%%d' => '%%d/%%m/%%Y',
'Total for all columns' => 'Total pour toutes les colonnes',
'You need at least 2 days of data to show the chart.' => 'Vous avez besoin d\'au minimum 2 jours de données pour afficher le graphique.',
@@ -788,7 +778,6 @@ return array(
'Not assigned' => 'Non assignées',
'View advanced search syntax' => 'Voir la syntaxe pour la recherche avancée',
'Overview' => 'Vue d\'ensemble',
- '%b %e %Y' => '%b %e %Y',
'Board/Calendar/List view' => 'Vue Tableau/Calendrier/Liste',
'Switch to the board view' => 'Basculer vers le tableau',
'Switch to the calendar view' => 'Basculer vers le calendrier',
@@ -878,8 +867,6 @@ return array(
'End date:' => 'Date de fin :',
'There is no start date or end date for this project.' => 'Il n\'y a pas de date de début ou de date de fin pour ce projet.',
'Projects Gantt chart' => 'Diagramme de Gantt des projets',
- 'Start date: %s' => 'Date de début : %s',
- 'End date: %s' => 'Date de fin : %s',
'Link type' => 'Type de lien',
'Change task color when using a specific task link' => 'Changer la couleur de la tâche lorsqu\'un lien spécifique est utilisé',
'Task link creation or modification' => 'Création ou modification d\'un lien sur une tâche',
@@ -1128,4 +1115,10 @@ return array(
'Moved:' => 'Déplacé le : ',
'Task #%d' => 'Tâche n°%d',
'Sub-tasks' => 'Sous-tâches',
+ 'Date and time format' => 'Format de la date et de l\'heure',
+ 'Time format' => 'Format de l\'heure',
+ 'Start date: ' => 'Date de début : ',
+ 'End date: ' => 'Date de fin : ',
+ 'New due date: ' => 'Nouvelle date d\'échéance : ',
+ 'Start date changed: ' => 'Date de début modifiée : ',
);
diff --git a/app/Locale/hu_HU/translations.php b/app/Locale/hu_HU/translations.php
index f9113270..447dafc9 100644
--- a/app/Locale/hu_HU/translations.php
+++ b/app/Locale/hu_HU/translations.php
@@ -102,7 +102,6 @@ return array(
'Open a task' => 'Feladat felnyitás',
'Do you really want to open this task: "%s"?' => 'Tényleg meg akarja nyitni ezt a feladatot: "%s"?',
'Back to the board' => 'Vissza a táblához',
- 'Created on %B %e, %Y at %k:%M %p' => 'Létrehozva: %Y. %m. %d. %H:%M',
'There is nobody assigned' => 'Nincs felelős',
'Column on the board:' => 'Tábla oszlopa: ',
'Close this task' => 'Feladat lezárása',
@@ -156,7 +155,6 @@ return array(
'Work in progress' => 'Folyamatban',
'Done' => 'Kész',
'Application version:' => 'Alkalmazás verzió:',
- '%B %e, %Y at %k:%M %p' => '%Y. %m. %d. %H:%M',
'Id' => 'ID',
'%d closed tasks' => '%d lezárt feladat',
'No task for this project' => 'Nincs feladat ebben a projektben',
@@ -180,8 +178,6 @@ return array(
'Edit this task' => 'Feladat módosítása',
'Due Date' => 'Határidő',
'Invalid date' => 'Érvénytelen dátum',
- 'Must be done before %B %e, %Y' => 'Kész kell lennie %Y. %m. %d. előtt',
- '%B %e, %Y' => '%Y. %m. %d.',
'Automatic actions' => 'Automatikus intézkedések',
'Your automatic action have been created successfully.' => 'Az automatikus intézkedés sikeresen elkészült.',
'Unable to create your automatic action.' => 'Automatikus intézkedés létrehozása nem lehetséges.',
@@ -317,7 +313,6 @@ return array(
'Unable to upload the file.' => 'Fájl feltöltése nem lehetséges.',
'Display another project' => 'Másik projekt megjelenítése',
'Created by %s' => 'Készítette: %s',
- 'Last modified on %B %e, %Y at %k:%M %p' => 'Utolsó módosítás: %Y. %m. %d. %H:%M',
'Tasks Export' => 'Feladatok exportálása',
'Tasks exportation for "%s"' => 'Feladatok exportálása: "%s"',
'Start Date' => 'Kezdés dátuma',
@@ -589,7 +584,6 @@ return array(
'This task' => 'Ez a feladat',
'<1h' => '<1ó',
'%dh' => '%dó',
- '%b %e' => '%b %e',
'Expand tasks' => 'Feladatok lenyitása',
'Collapse tasks' => 'Feladatok összecsukása',
'Expand/collapse tasks' => 'Feladatok lenyitása/összecsukása',
@@ -758,10 +752,6 @@ return array(
// 'Only for tasks assigned to me' => '',
// 'Only for tasks created by me' => '',
// 'Only for tasks created by me and assigned to me' => '',
- // '%A' => '',
- // '%b %e, %Y, %k:%M %p' => '',
- // 'New due date: %B %e, %Y' => '',
- // 'Start date changed: %B %e, %Y' => '',
// '%%Y-%%m-%%d' => '',
// 'Total for all columns' => '',
// 'You need at least 2 days of data to show the chart.' => '',
@@ -786,7 +776,6 @@ return array(
// 'Not assigned' => '',
// 'View advanced search syntax' => '',
// 'Overview' => '',
- // '%b %e %Y' => '',
// 'Board/Calendar/List view' => '',
// 'Switch to the board view' => '',
// 'Switch to the calendar view' => '',
@@ -876,8 +865,6 @@ return array(
// 'End date:' => '',
// 'There is no start date or end date for this project.' => '',
// 'Projects Gantt chart' => '',
- // 'Start date: %s' => '',
- // 'End date: %s' => '',
// 'Link type' => '',
// 'Change task color when using a specific task link' => '',
// 'Task link creation or modification' => '',
@@ -1125,4 +1112,10 @@ return array(
// 'Moved:' => '',
// 'Task #%d' => '',
// 'Sub-tasks' => '',
+ // 'Date and time format' => '',
+ // 'Time format' => '',
+ // 'Start date: ' => '',
+ // 'End date: ' => '',
+ // 'New due date: ' => '',
+ // 'Start date changed: ' => '',
);
diff --git a/app/Locale/id_ID/translations.php b/app/Locale/id_ID/translations.php
index 0bbdd686..8c6db849 100644
--- a/app/Locale/id_ID/translations.php
+++ b/app/Locale/id_ID/translations.php
@@ -102,7 +102,6 @@ return array(
'Open a task' => 'Buka tugas',
'Do you really want to open this task: "%s"?' => 'Apakah anda yakin akan membuka tugas ini : « %s » ?',
'Back to the board' => 'Kembali ke papan',
- 'Created on %B %e, %Y at %k:%M %p' => 'Dibuat pada tanggal %d/%m/%Y à %H:%M',
'There is nobody assigned' => 'Tidak ada orang yand ditugaskan',
'Column on the board:' => 'Kolom di dalam papan : ',
'Close this task' => 'Tutup tugas ini',
@@ -156,7 +155,6 @@ return array(
'Work in progress' => 'Sedang dalam pengerjaan',
'Done' => 'Selesai',
'Application version:' => 'Versi aplikasi :',
- '%B %e, %Y at %k:%M %p' => '%d/%m/%Y à %H:%M',
'Id' => 'Id.',
'%d closed tasks' => '%d tugas yang ditutup',
'No task for this project' => 'Tidak ada tugas dalam proyek ini',
@@ -180,8 +178,6 @@ return array(
'Edit this task' => 'Modifikasi tugas ini',
'Due Date' => 'Batas Tanggal Terakhir',
'Invalid date' => 'Tanggal tidak valid',
- 'Must be done before %B %e, %Y' => 'Harus diselesaikan sebelum tanggal %d/%m/%Y',
- '%B %e, %Y' => '%d %B %Y',
'Automatic actions' => 'Tindakan otomatis',
'Your automatic action have been created successfully.' => 'Tindakan otomatis anda berhasil dibuat.',
'Unable to create your automatic action.' => 'Tidak dapat membuat tindakan otomatis anda.',
@@ -317,7 +313,6 @@ return array(
'Unable to upload the file.' => 'Tidak dapat mengunggah berkas.',
'Display another project' => 'Lihat proyek lain',
'Created by %s' => 'Dibuat oleh %s',
- 'Last modified on %B %e, %Y at %k:%M %p' => 'Modifikasi terakhir pada tanggal %d/%m/%Y à %H:%M',
'Tasks Export' => 'Ekspor Tugas',
'Tasks exportation for "%s"' => 'Tugas di ekspor untuk « %s »',
'Start Date' => 'Tanggal Mulai',
@@ -589,7 +584,6 @@ return array(
'This task' => 'Tugas ini',
'<1h' => '<1h',
'%dh' => '%dh',
- '%b %e' => '%e %b',
'Expand tasks' => 'Perluas tugas',
'Collapse tasks' => 'Lipat tugas',
'Expand/collapse tasks' => 'Perluas/lipat tugas',
@@ -758,10 +752,6 @@ return array(
'Only for tasks assigned to me' => 'Hanya untuk tugas yang ditugaskan ke saya',
'Only for tasks created by me' => 'Hanya untuk tugas yang dibuat oleh saya',
'Only for tasks created by me and assigned to me' => 'Hanya untuk tugas yang dibuat oleh saya dan ditugaskan ke saya',
- '%A' => '%A',
- '%b %e, %Y, %k:%M %p' => '%d/%m/%Y %H:%M',
- 'New due date: %B %e, %Y' => 'Tanggal jatuh tempo baru : %d/%m/%Y',
- 'Start date changed: %B %e, %Y' => 'Tanggal mulai berubah : %d/%m/%Y',
'%%Y-%%m-%%d' => '%%d/%%m/%%Y',
'Total for all columns' => 'Total untuk semua kolom',
'You need at least 2 days of data to show the chart.' => 'Anda memerlukan setidaknya 2 hari dari data yang menunjukkan grafik.',
@@ -786,7 +776,6 @@ return array(
'Not assigned' => 'Tidak ditugaskan',
'View advanced search syntax' => 'Lihat sintaks pencarian lanjutan',
'Overview' => 'Ikhtisar',
- '%b %e %Y' => '%b %e %Y',
'Board/Calendar/List view' => 'Tampilan Papan/Kalender/Daftar',
'Switch to the board view' => 'Beralih ke tampilan papan',
'Switch to the calendar view' => 'Beralih ke tampilan kalender',
@@ -876,8 +865,6 @@ return array(
'End date:' => 'Waktu berakhir :',
'There is no start date or end date for this project.' => 'Tidak ada waktu mulai atau waktu berakhir untuk proyek ini',
'Projects Gantt chart' => 'Proyek grafik Gantt',
- 'Start date: %s' => 'Waktu mulai : %s',
- 'End date: %s' => 'Waktu berakhir : %s',
'Link type' => 'Tipe tautan',
'Change task color when using a specific task link' => 'Rubah warna tugas ketika menggunakan tautan tugas yang spesifik',
'Task link creation or modification' => 'Tautan pembuatan atau modifikasi tugas ',
@@ -1125,4 +1112,10 @@ return array(
// 'Moved:' => '',
// 'Task #%d' => '',
// 'Sub-tasks' => '',
+ // 'Date and time format' => '',
+ // 'Time format' => '',
+ // 'Start date: ' => '',
+ // 'End date: ' => '',
+ // 'New due date: ' => '',
+ // 'Start date changed: ' => '',
);
diff --git a/app/Locale/it_IT/translations.php b/app/Locale/it_IT/translations.php
index 3957319e..661e6c86 100644
--- a/app/Locale/it_IT/translations.php
+++ b/app/Locale/it_IT/translations.php
@@ -102,7 +102,6 @@ return array(
'Open a task' => 'Apri un task',
'Do you really want to open this task: "%s"?' => 'Veramente desideri aprire questo task: "%s" ?',
'Back to the board' => 'Torna alla bacheca',
- 'Created on %B %e, %Y at %k:%M %p' => 'Creato il %B %e, %Y alle %k:%M %p',
'There is nobody assigned' => 'Nessuno è assegnato a questo task',
'Column on the board:' => 'Colonna sulla bacheca: ',
'Close this task' => 'Chiudi questo task',
@@ -156,7 +155,6 @@ return array(
'Work in progress' => 'In corso',
'Done' => 'Fatto',
'Application version:' => 'Versione dell\'applicazione:',
- // '%B %e, %Y at %k:%M %p' => '',
// 'Id' => '',
'%d closed tasks' => '%d task chiusi',
'No task for this project' => 'Nessun task per questo progetto',
@@ -180,8 +178,6 @@ return array(
'Edit this task' => 'Modifica questo task',
'Due Date' => 'Data di scadenza',
'Invalid date' => 'Data non valida',
- 'Must be done before %B %e, %Y' => 'Deve essere completato prima del %B %e, %Y',
- // '%B %e, %Y' => '',
'Automatic actions' => 'Azioni automatiche',
'Your automatic action have been created successfully.' => 'l\'azione automatica è stata creata correttamente.',
'Unable to create your automatic action.' => 'Impossibile creare quest\'azione automatica.',
@@ -317,7 +313,6 @@ return array(
'Unable to upload the file.' => 'Impossibile caricare il file.',
'Display another project' => 'Mostra un altro progetto',
'Created by %s' => 'Creato da %s',
- 'Last modified on %B %e, %Y at %k:%M %p' => 'Ultima modifica il %d/%m/%Y alle %H:%M',
'Tasks Export' => 'Export dei task',
'Tasks exportation for "%s"' => 'Export dei task per "%s"',
'Start Date' => 'Data d\'inizio',
@@ -589,7 +584,6 @@ return array(
'This task' => 'Questo task',
// '<1h' => '',
// '%dh' => '',
- // '%b %e' => '',
'Expand tasks' => 'Espandi i task',
'Collapse tasks' => 'Minimizza i task',
'Expand/collapse tasks' => 'Espandi/minimizza i task',
@@ -758,10 +752,6 @@ return array(
'Only for tasks assigned to me' => 'Solo per i task assegnati a me',
'Only for tasks created by me' => 'Solo per i task creati da me',
'Only for tasks created by me and assigned to me' => 'Solo per i task creati da me e assegnati a me',
- // '%A' => '',
- // '%b %e, %Y, %k:%M %p' => '',
- 'New due date: %B %e, %Y' => 'Nuova data di scadenza: %B %e, %Y',
- 'Start date changed: %B %e, %Y' => 'Data di inizio cambiata: %B %e, %Y',
// '%%Y-%%m-%%d' => '',
'Total for all columns' => 'Totale per tutte le colonne',
'You need at least 2 days of data to show the chart.' => 'Hai bisogno di almeno 2 giorni di dati per mostrare il grafico.',
@@ -786,7 +776,6 @@ return array(
'Not assigned' => 'Non assegnato',
'View advanced search syntax' => 'Visualizza la sintassi di ricerca avanzata',
'Overview' => 'Panoramica',
- // '%b %e %Y' => '',
// 'Board/Calendar/List view' => '',
'Switch to the board view' => 'Passa alla vista "bacheca"',
'Switch to the calendar view' => 'Passa alla vista "calendario"',
@@ -876,8 +865,6 @@ return array(
'End date:' => 'Data di fine:',
'There is no start date or end date for this project.' => 'Non è prevista una data di inzio o fine per questo progetto.',
'Projects Gantt chart' => 'Grafico Gantt dei progetti',
- 'Start date: %s' => 'Data di inizio: %s',
- 'End date: %s' => 'Data di fine: %s',
'Link type' => 'Tipo di link',
'Change task color when using a specific task link' => 'Cambia colore del task quando si un utilizza una determinata relazione di task',
'Task link creation or modification' => 'Creazione o modifica di relazione di task',
@@ -1125,4 +1112,10 @@ return array(
// 'Moved:' => '',
// 'Task #%d' => '',
// 'Sub-tasks' => '',
+ // 'Date and time format' => '',
+ // 'Time format' => '',
+ // 'Start date: ' => '',
+ // 'End date: ' => '',
+ // 'New due date: ' => '',
+ // 'Start date changed: ' => '',
);
diff --git a/app/Locale/ja_JP/translations.php b/app/Locale/ja_JP/translations.php
index 4ecf039b..3609836b 100644
--- a/app/Locale/ja_JP/translations.php
+++ b/app/Locale/ja_JP/translations.php
@@ -102,7 +102,6 @@ return array(
'Open a task' => 'タスクをオープンする',
'Do you really want to open this task: "%s"?' => 'タスク「%s」をオープンしますか?',
'Back to the board' => 'ボードに戻る',
- 'Created on %B %e, %Y at %k:%M %p' => '%Y/%m/%d %H:%M に作成',
'There is nobody assigned' => '担当者がいません',
'Column on the board:' => 'カラム: ',
'Close this task' => 'タスクをクローズする',
@@ -156,7 +155,6 @@ return array(
'Work in progress' => 'Work in progress',
'Done' => 'Done',
'Application version:' => 'アプリケーションのバージョン:',
- '%B %e, %Y at %k:%M %p' => '%Y/%m/%d %H:%M',
'Id' => 'ID',
'%d closed tasks' => '%d 個のクローズしたタスク',
'No task for this project' => 'このプロジェクトにタスクがありません',
@@ -180,8 +178,6 @@ return array(
'Edit this task' => 'タスクを変更する',
'Due Date' => '期限',
'Invalid date' => '日付が無効です',
- 'Must be done before %B %e, %Y' => '%Y/%m/%d までに完了',
- '%B %e, %Y' => '%Y %B %e',
'Automatic actions' => '自動アクションを管理する',
'Your automatic action have been created successfully.' => '自動アクションを作成しました。',
'Unable to create your automatic action.' => '自動アクションの作成に失敗しました。',
@@ -317,7 +313,6 @@ return array(
'Unable to upload the file.' => 'ファイルのアップロードに失敗しました。',
'Display another project' => '別のプロジェクトを表示',
'Created by %s' => '%s が作成',
- 'Last modified on %B %e, %Y at %k:%M %p' => ' %Y/%m/%d %H:%M に変更',
'Tasks Export' => 'タスクの出力',
'Tasks exportation for "%s"' => '「%s」のタスク出力',
'Start Date' => '開始日',
@@ -589,7 +584,6 @@ return array(
'This task' => 'このタスクは',
'<1h' => '<1時間',
'%dh' => '%d 時間',
- '%b %e' => '%b/%e',
'Expand tasks' => 'タスクを展開する',
'Collapse tasks' => 'タスクを閉じる',
'Expand/collapse tasks' => 'タスクの展開/閉じる',
@@ -758,10 +752,6 @@ return array(
// 'Only for tasks assigned to me' => '',
// 'Only for tasks created by me' => '',
// 'Only for tasks created by me and assigned to me' => '',
- // '%A' => '',
- // '%b %e, %Y, %k:%M %p' => '',
- // 'New due date: %B %e, %Y' => '',
- // 'Start date changed: %B %e, %Y' => '',
// '%%Y-%%m-%%d' => '',
// 'Total for all columns' => '',
// 'You need at least 2 days of data to show the chart.' => '',
@@ -786,7 +776,6 @@ return array(
// 'Not assigned' => '',
// 'View advanced search syntax' => '',
// 'Overview' => '',
- // '%b %e %Y' => '',
// 'Board/Calendar/List view' => '',
// 'Switch to the board view' => '',
// 'Switch to the calendar view' => '',
@@ -876,8 +865,6 @@ return array(
// 'End date:' => '',
// 'There is no start date or end date for this project.' => '',
// 'Projects Gantt chart' => '',
- // 'Start date: %s' => '',
- // 'End date: %s' => '',
// 'Link type' => '',
// 'Change task color when using a specific task link' => '',
// 'Task link creation or modification' => '',
@@ -1125,4 +1112,10 @@ return array(
// 'Moved:' => '',
// 'Task #%d' => '',
// 'Sub-tasks' => '',
+ // 'Date and time format' => '',
+ // 'Time format' => '',
+ // 'Start date: ' => '',
+ // 'End date: ' => '',
+ // 'New due date: ' => '',
+ // 'Start date changed: ' => '',
);
diff --git a/app/Locale/my_MY/translations.php b/app/Locale/my_MY/translations.php
index 36b15495..5b1da7cd 100644
--- a/app/Locale/my_MY/translations.php
+++ b/app/Locale/my_MY/translations.php
@@ -102,7 +102,6 @@ return array(
'Open a task' => 'Buka tugas',
'Do you really want to open this task: "%s"?' => 'Anda yakin untuk buka tugas ini : « %s » ?',
'Back to the board' => 'Kembali ke papan',
- 'Created on %B %e, %Y at %k:%M %p' => 'Dicipta pada tanggal %d/%m/%Y à %H:%M',
'There is nobody assigned' => 'Tidak ada orang yand ditugaskan',
'Column on the board:' => 'Kolom di dalam papan : ',
'Close this task' => 'Tutup tugas ini',
@@ -156,7 +155,6 @@ return array(
'Work in progress' => 'Sedang dalam pengerjaan',
'Done' => 'Selesai',
'Application version:' => 'Versi aplikasi :',
- '%B %e, %Y at %k:%M %p' => '%d/%m/%Y à %H:%M',
'Id' => 'Id.',
'%d closed tasks' => '%d tugas yang ditutup',
'No task for this project' => 'Tidak ada tugas dalam projek ini',
@@ -180,8 +178,6 @@ return array(
'Edit this task' => 'Modifikasi tugas ini',
'Due Date' => 'Batas Tanggal Terakhir',
'Invalid date' => 'Tanggal tidak valid',
- 'Must be done before %B %e, %Y' => 'Harus diselesaikan sebelum tanggal %d/%m/%Y',
- '%B %e, %Y' => '%d %B %Y',
'Automatic actions' => 'Tindakan otomatis',
'Your automatic action have been created successfully.' => 'Tindakan otomatis anda berhasil dibuat.',
'Unable to create your automatic action.' => 'Tidak dapat membuat tindakan otomatis anda.',
@@ -317,7 +313,6 @@ return array(
'Unable to upload the file.' => 'Tidak dapat mengunggah berkas.',
'Display another project' => 'Lihat projek lain',
'Created by %s' => 'Dibuat oleh %s',
- 'Last modified on %B %e, %Y at %k:%M %p' => 'Modifikasi terakhir pada tanggal %d/%m/%Y à %H:%M',
'Tasks Export' => 'Ekspor Tugas',
'Tasks exportation for "%s"' => 'Tugas di ekspor untuk « %s »',
'Start Date' => 'Tanggal Mulai',
@@ -589,7 +584,6 @@ return array(
'This task' => 'Tugas ini',
'<1h' => '<1h',
'%dh' => '%dh',
- '%b %e' => '%e %b',
'Expand tasks' => 'Perluas tugas',
'Collapse tasks' => 'Lipat tugas',
'Expand/collapse tasks' => 'Perluas/lipat tugas',
@@ -758,10 +752,6 @@ return array(
'Only for tasks assigned to me' => 'Hanya untuk tugas yang ditugaskan ke saya',
'Only for tasks created by me' => 'Hanya untuk tugas yang dibuat oleh saya',
'Only for tasks created by me and assigned to me' => 'Hanya untuk tugas yang dibuat oleh saya dan ditugaskan ke saya',
- '%A' => '%A',
- '%b %e, %Y, %k:%M %p' => '%d/%m/%Y %H:%M',
- 'New due date: %B %e, %Y' => 'Tanggal jatuh tempo baru : %d/%m/%Y',
- 'Start date changed: %B %e, %Y' => 'Tanggal mulai berubah : %d/%m/%Y',
'%%Y-%%m-%%d' => '%%d/%%m/%%Y',
'Total for all columns' => 'Total untuk semua kolom',
'You need at least 2 days of data to show the chart.' => 'Anda memerlukan setidaknya 2 hari dari data yang menunjukkan grafik.',
@@ -786,7 +776,6 @@ return array(
'Not assigned' => 'Tidak ditugaskan',
'View advanced search syntax' => 'Lihat sintaks pencarian lanjutan',
'Overview' => 'Ikhtisar',
- '%b %e %Y' => '%b %e %Y',
'Board/Calendar/List view' => 'Tampilan Papan/Kalender/Daftar',
'Switch to the board view' => 'Beralih ke tampilan papan',
'Switch to the calendar view' => 'Beralih ke tampilan kalender',
@@ -876,8 +865,6 @@ return array(
'End date:' => 'Waktu berakhir :',
'There is no start date or end date for this project.' => 'Tidak ada waktu mula atau waktu berakhir pada projek ini',
'Projects Gantt chart' => 'projekkan carta Gantt',
- 'Start date: %s' => 'Waktu mulai: %s',
- 'End date: %s' => 'Waktu berakhir: %s',
'Link type' => 'Jenis pautan',
'Change task color when using a specific task link' => 'Rubah warna tugas ketika menggunakan Pautan tugas yang spesifik',
'Task link creation or modification' => 'Pautan tugas pada penciptaan atau penyuntingan',
@@ -1125,4 +1112,10 @@ return array(
// 'Moved:' => '',
// 'Task #%d' => '',
// 'Sub-tasks' => '',
+ // 'Date and time format' => '',
+ // 'Time format' => '',
+ // 'Start date: ' => '',
+ // 'End date: ' => '',
+ // 'New due date: ' => '',
+ // 'Start date changed: ' => '',
);
diff --git a/app/Locale/nb_NO/translations.php b/app/Locale/nb_NO/translations.php
index 6048107d..335c699b 100644
--- a/app/Locale/nb_NO/translations.php
+++ b/app/Locale/nb_NO/translations.php
@@ -102,7 +102,6 @@ return array(
'Open a task' => 'Åpne en oppgave',
'Do you really want to open this task: "%s"?' => 'Vil du åpne denne oppgaven: "%s"?',
'Back to the board' => 'Tilbake til prosjektsiden',
- 'Created on %B %e, %Y at %k:%M %p' => 'Opprettet %d.%m.%Y - %H:%M',
'There is nobody assigned' => 'Mangler tildeling',
'Column on the board:' => 'Kolonne:',
'Close this task' => 'Lukk oppgaven',
@@ -156,7 +155,6 @@ return array(
'Work in progress' => 'Under arbeid',
'Done' => 'Utført',
'Application version:' => 'Versjon:',
- '%B %e, %Y at %k:%M %p' => '%d.%m.%Y - %H:%M',
'Id' => 'ID',
'%d closed tasks' => '%d lukkede oppgaver',
'No task for this project' => 'Ingen oppgaver i dette prosjektet',
@@ -180,8 +178,6 @@ return array(
'Edit this task' => 'Rediger oppgaven',
'Due Date' => 'Forfallsdato',
'Invalid date' => 'Ugyldig dato',
- 'Must be done before %B %e, %Y' => 'Skal være utført innen %d.%m.%Y',
- '%B %e, %Y' => '%d.%m.%Y',
'Automatic actions' => 'Automatiske handlinger',
'Your automatic action have been created successfully.' => 'Din automatiske handling er opprettet.',
'Unable to create your automatic action.' => 'Din automatiske handling kunne ikke opprettes.',
@@ -317,7 +313,6 @@ return array(
'Unable to upload the file.' => 'Filen kunne ikke lastes opp.',
'Display another project' => 'Vis annet prosjekt...',
'Created by %s' => 'Opprettet av %s',
- 'Last modified on %B %e, %Y at %k:%M %p' => 'Sist endret %d.%m.%Y - %H:%M',
'Tasks Export' => 'Oppgave eksport',
'Tasks exportation for "%s"' => 'Oppgaveeksportering for "%s"',
'Start Date' => 'Start-dato',
@@ -589,7 +584,6 @@ return array(
'This task' => 'Denne oppgaven',
// '<1h' => '',
// '%dh' => '',
- // '%b %e' => '',
'Expand tasks' => 'Utvid oppgavevisning',
'Collapse tasks' => 'Komprimer oppgavevisning',
'Expand/collapse tasks' => 'Utvide/komprimere oppgavevisning',
@@ -758,10 +752,6 @@ return array(
'Only for tasks assigned to me' => 'Kun oppgaver som er tildelt meg',
'Only for tasks created by me' => 'Kun oppgaver som er opprettet av meg',
'Only for tasks created by me and assigned to me' => 'Kun oppgaver som er opprettet av meg og tildelt meg',
- // '%A' => '',
- // '%b %e, %Y, %k:%M %p' => '',
- // 'New due date: %B %e, %Y' => '',
- // 'Start date changed: %B %e, %Y' => '',
// '%%Y-%%m-%%d' => '',
'Total for all columns' => 'Totalt for alle kolonner',
// 'You need at least 2 days of data to show the chart.' => '',
@@ -786,7 +776,6 @@ return array(
'Not assigned' => 'Ikke tildelt',
'View advanced search syntax' => 'Vis hjelp for avansert søk ',
'Overview' => 'Oversikt',
- // '%b %e %Y' => '',
'Board/Calendar/List view' => 'Oversikt/kalender/listevisning',
'Switch to the board view' => 'Oversiktsvisning',
'Switch to the calendar view' => 'Kalendevisning',
@@ -876,8 +865,6 @@ return array(
'End date:' => 'Sluttdato:',
// 'There is no start date or end date for this project.' => '',
'Projects Gantt chart' => 'Gantt skjema for prosjekter',
- 'Start date: %s' => 'Startdato: %s',
- 'End date: %s' => 'Sluttdato: %s',
'Link type' => 'Relasjonstype',
// 'Change task color when using a specific task link' => '',
// 'Task link creation or modification' => '',
@@ -1125,4 +1112,10 @@ return array(
// 'Moved:' => '',
// 'Task #%d' => '',
// 'Sub-tasks' => '',
+ // 'Date and time format' => '',
+ // 'Time format' => '',
+ // 'Start date: ' => '',
+ // 'End date: ' => '',
+ // 'New due date: ' => '',
+ // 'Start date changed: ' => '',
);
diff --git a/app/Locale/nl_NL/translations.php b/app/Locale/nl_NL/translations.php
index 57fcae4e..0d9d9608 100644
--- a/app/Locale/nl_NL/translations.php
+++ b/app/Locale/nl_NL/translations.php
@@ -102,7 +102,6 @@ return array(
'Open a task' => 'Een taak openen',
'Do you really want to open this task: "%s"?' => 'Weet u zeker dat u deze taak wil openen : « %s » ?',
'Back to the board' => 'Terug naar het bord',
- 'Created on %B %e, %Y at %k:%M %p' => 'Aangemaakt op %d/%m/%Y à %H:%M',
'There is nobody assigned' => 'Er is niemand toegewezen',
'Column on the board:' => 'Kolom op het bord : ',
'Close this task' => 'Deze taak sluiten',
@@ -156,7 +155,6 @@ return array(
'Work in progress' => 'In behandeling',
'Done' => 'Afgewerkt',
'Application version:' => 'Applicatie versie :',
- '%B %e, %Y at %k:%M %p' => '%d/%m/%Y op %H:%M',
'Id' => 'Id',
'%d closed tasks' => '%d gesloten taken',
'No task for this project' => 'Geen taken voor dit project',
@@ -180,8 +178,6 @@ return array(
'Edit this task' => 'Deze taak aanpassen',
'Due Date' => 'Vervaldag',
'Invalid date' => 'Ongeldige datum',
- 'Must be done before %B %e, %Y' => 'Moet voltooid zijn voor %d/%m/%Y',
- '%B %e, %Y' => '%d %B %Y',
'Automatic actions' => 'Geautomatiseerd acties',
'Your automatic action have been created successfully.' => 'Geautomatiseerde actie succesvol aangemaakt.',
'Unable to create your automatic action.' => 'Geautomatiseerde actie aanmaken niet gelukt.',
@@ -317,7 +313,6 @@ return array(
'Unable to upload the file.' => 'Uploaden van bestand niet gelukt.',
'Display another project' => 'Een ander project weergeven',
'Created by %s' => 'Aangemaakt door %s',
- 'Last modified on %B %e, %Y at %k:%M %p' => 'Laatst gewijzigd op %d/%m/%Y à %H:%M',
'Tasks Export' => 'Taken exporteren',
'Tasks exportation for "%s"' => 'Taken exporteren voor « %s »',
'Start Date' => 'Startdatum',
@@ -589,7 +584,6 @@ return array(
'This task' => 'Deze taal',
'<1h' => '<1h',
'%dh' => '%dh',
- '%b %e' => '%e %b',
'Expand tasks' => 'Taken uitklappen',
'Collapse tasks' => 'Taken inklappen',
'Expand/collapse tasks' => 'Taken in/uiklappen',
@@ -758,10 +752,6 @@ return array(
// 'Only for tasks assigned to me' => '',
// 'Only for tasks created by me' => '',
// 'Only for tasks created by me and assigned to me' => '',
- // '%A' => '',
- // '%b %e, %Y, %k:%M %p' => '',
- // 'New due date: %B %e, %Y' => '',
- // 'Start date changed: %B %e, %Y' => '',
// '%%Y-%%m-%%d' => '',
// 'Total for all columns' => '',
// 'You need at least 2 days of data to show the chart.' => '',
@@ -786,7 +776,6 @@ return array(
// 'Not assigned' => '',
// 'View advanced search syntax' => '',
// 'Overview' => '',
- // '%b %e %Y' => '',
// 'Board/Calendar/List view' => '',
// 'Switch to the board view' => '',
// 'Switch to the calendar view' => '',
@@ -876,8 +865,6 @@ return array(
// 'End date:' => '',
// 'There is no start date or end date for this project.' => '',
// 'Projects Gantt chart' => '',
- // 'Start date: %s' => '',
- // 'End date: %s' => '',
// 'Link type' => '',
// 'Change task color when using a specific task link' => '',
// 'Task link creation or modification' => '',
@@ -1125,4 +1112,10 @@ return array(
// 'Moved:' => '',
// 'Task #%d' => '',
// 'Sub-tasks' => '',
+ // 'Date and time format' => '',
+ // 'Time format' => '',
+ // 'Start date: ' => '',
+ // 'End date: ' => '',
+ // 'New due date: ' => '',
+ // 'Start date changed: ' => '',
);
diff --git a/app/Locale/pl_PL/translations.php b/app/Locale/pl_PL/translations.php
index 6d0a0b93..28ed2b3a 100644
--- a/app/Locale/pl_PL/translations.php
+++ b/app/Locale/pl_PL/translations.php
@@ -102,7 +102,6 @@ return array(
'Open a task' => 'Otwórz zadanie',
'Do you really want to open this task: "%s"?' => 'Na pewno chcesz otworzyć zadanie: "%s"?',
'Back to the board' => 'Powrót do tablicy',
- 'Created on %B %e, %Y at %k:%M %p' => 'Utworzono dnia %e %B %Y o %k:%M',
'There is nobody assigned' => 'Nikt nie jest przypisany',
'Column on the board:' => 'Kolumna na tablicy:',
'Close this task' => 'Zamknij zadanie',
@@ -156,7 +155,6 @@ return array(
'Work in progress' => 'W trakcie',
'Done' => 'Zakończone',
'Application version:' => 'Wersja aplikacji:',
- '%B %e, %Y at %k:%M %p' => '%e %B %Y o %k:%M',
'Id' => 'Id',
'%d closed tasks' => '%d zamkniętych zadań',
'No task for this project' => 'Brak zadań dla tego projektu',
@@ -180,8 +178,6 @@ return array(
'Edit this task' => 'Edytuj zadanie',
'Due Date' => 'Termin',
'Invalid date' => 'Błędna data',
- 'Must be done before %B %e, %Y' => 'Termin do %e %B %Y',
- '%B %e, %Y' => '%e %B %Y',
'Automatic actions' => 'Akcje automatyczne',
'Your automatic action have been created successfully.' => 'Twoja akcja została dodana',
'Unable to create your automatic action.' => 'Nie udało się utworzyć akcji',
@@ -317,7 +313,6 @@ return array(
'Unable to upload the file.' => 'Nie można wczytać pliku.',
'Display another project' => 'Wyświetl inny projekt',
'Created by %s' => 'Utworzone przez %s',
- 'Last modified on %B %e, %Y at %k:%M %p' => 'Ostatnio zmienione %e %B %Y o %k:%M',
'Tasks Export' => 'Eksport zadań',
'Tasks exportation for "%s"' => 'Eksport zadań dla "%s"',
'Start Date' => 'Data początkowa',
@@ -589,7 +584,6 @@ return array(
'This task' => 'To zadanie',
// '<1h' => '',
// '%dh' => '',
- '%b %e' => '%e %b',
'Expand tasks' => 'Rozwiń zadania',
'Collapse tasks' => 'Zwiń zadania',
'Expand/collapse tasks' => 'Zwiń/Rozwiń zadania',
@@ -758,10 +752,6 @@ return array(
'Only for tasks assigned to me' => 'Tylko zadań przypisanych do mnie',
'Only for tasks created by me' => 'Tylko zadań utworzonych przeze mnie',
'Only for tasks created by me and assigned to me' => 'Tylko zadań przypisanych lub utworzonych przeze mnie',
- // '%A' => '',
- // '%b %e, %Y, %k:%M %p' => '',
- 'New due date: %B %e, %Y' => 'Nowy termin: %B %e, %Y',
- 'Start date changed: %B %e, %Y' => 'Zmiana daty rozpoczęcia: %B %e, %Y',
// '%%Y-%%m-%%d' => '',
// 'Total for all columns' => '',
// 'You need at least 2 days of data to show the chart.' => '',
@@ -786,7 +776,6 @@ return array(
'Not assigned' => 'Nieprzypisane zadania',
'View advanced search syntax' => 'Pomoc dotycząca budowania filtrów',
'Overview' => 'Przegląd',
- // '%b %e %Y' => '',
'Board/Calendar/List view' => 'Widok: Tablica/Kalendarz/Lista',
'Switch to the board view' => 'Przełącz na tablicę',
'Switch to the calendar view' => 'Przełącz na kalendarz',
@@ -876,8 +865,6 @@ return array(
'End date:' => 'Data zakończenia:',
'There is no start date or end date for this project.' => 'Nie zdefiniowano czasu trwania projektu',
'Projects Gantt chart' => 'Wykres Gantta dla projektów',
- 'Start date: %s' => 'Data rozpoczęcia: %s',
- 'End date: %s' => 'Data zakończenia: %s',
'Link type' => 'Typ adresu URL',
'Change task color when using a specific task link' => 'Zmień kolor zadania używając specjalnego adresu URL',
'Task link creation or modification' => 'Adres URL do utworzenia zadania lub modyfikacji',
@@ -1125,4 +1112,10 @@ return array(
// 'Moved:' => '',
// 'Task #%d' => '',
// 'Sub-tasks' => '',
+ // 'Date and time format' => '',
+ // 'Time format' => '',
+ // 'Start date: ' => '',
+ // 'End date: ' => '',
+ // 'New due date: ' => '',
+ // 'Start date changed: ' => '',
);
diff --git a/app/Locale/pt_BR/translations.php b/app/Locale/pt_BR/translations.php
index eef52d48..d29f9f88 100644
--- a/app/Locale/pt_BR/translations.php
+++ b/app/Locale/pt_BR/translations.php
@@ -102,7 +102,6 @@ return array(
'Open a task' => 'Abrir uma tarefa',
'Do you really want to open this task: "%s"?' => 'Você realmente deseja abrir esta tarefa: "%s"?',
'Back to the board' => 'Voltar ao board',
- 'Created on %B %e, %Y at %k:%M %p' => 'Criado em %d %B %Y às %H:%M',
'There is nobody assigned' => 'Não há ninguém designado',
'Column on the board:' => 'Coluna no board:',
'Close this task' => 'Finalizar esta tarefa',
@@ -156,7 +155,6 @@ return array(
'Work in progress' => 'Em andamento',
'Done' => 'Finalizado',
'Application version:' => 'Versão da aplicação:',
- '%B %e, %Y at %k:%M %p' => '%d %B %Y às %H:%M',
'Id' => 'Id',
'%d closed tasks' => '%d tarefas finalizadas',
'No task for this project' => 'Não há tarefa para este projeto',
@@ -180,8 +178,6 @@ return array(
'Edit this task' => 'Editar esta tarefa',
'Due Date' => 'Data de vencimento',
'Invalid date' => 'Data inválida',
- 'Must be done before %B %e, %Y' => 'Deve ser finalizado antes de %d %B %Y',
- '%B %e, %Y' => '%d %B %Y',
'Automatic actions' => 'Ações automáticas',
'Your automatic action have been created successfully.' => 'Sua ação automética foi criada com sucesso.',
'Unable to create your automatic action.' => 'Não é possível criar sua ação automática.',
@@ -317,7 +313,6 @@ return array(
'Unable to upload the file.' => 'Não foi possível carregar o arquivo.',
'Display another project' => 'Exibir outro projeto',
'Created by %s' => 'Criado por %s',
- 'Last modified on %B %e, %Y at %k:%M %p' => 'Última modificação em %B %e, %Y às %k: %M %p',
'Tasks Export' => 'Exportar Tarefas',
'Tasks exportation for "%s"' => 'As tarefas foram exportadas para "%s"',
'Start Date' => 'Data inicial',
@@ -589,7 +584,6 @@ return array(
'This task' => 'Esta tarefa',
'<1h' => '<1h',
'%dh' => '%dh',
- '%b %e' => '%e %b',
'Expand tasks' => 'Expandir tarefas',
'Collapse tasks' => 'Contrair tarefas',
'Expand/collapse tasks' => 'Expandir/Contrair tarefas',
@@ -758,10 +752,6 @@ return array(
'Only for tasks assigned to me' => 'Somente as tarefas atribuídas a mim',
'Only for tasks created by me' => 'Apenas as tarefas que eu criei',
'Only for tasks created by me and assigned to me' => 'Apenas as tarefas que eu criei e aquelas atribuídas a mim',
- '%A' => '%A',
- '%b %e, %Y, %k:%M %p' => '%d/%m/%Y %H:%M',
- 'New due date: %B %e, %Y' => 'Nova data limite: %d/%m/%Y',
- 'Start date changed: %B %e, %Y' => 'Data de início alterada: %d/%m/%Y',
'%%Y-%%m-%%d' => '%%d/%%m/%%Y',
'Total for all columns' => 'Total para todas as colunas',
'You need at least 2 days of data to show the chart.' => 'Você precisa de pelo menos 2 dias de dados para visualizar o gráfico.',
@@ -786,7 +776,6 @@ return array(
'Not assigned' => 'Não designada',
'View advanced search syntax' => 'Ver a sintaxe para pesquisa avançada',
'Overview' => 'Visão global',
- '%b %e %Y' => '%b %e %Y',
'Board/Calendar/List view' => 'Vista Painel/Calendário/Lista',
'Switch to the board view' => 'Mudar para o modo Painel',
'Switch to the calendar view' => 'Mudar par o modo Calendário',
@@ -876,8 +865,6 @@ return array(
'End date:' => 'Data de término:',
'There is no start date or end date for this project.' => 'Não há data de início ou data de término para este projeto.',
'Projects Gantt chart' => 'Gráfico de Gantt dos projetos',
- 'Start date: %s' => 'Data de início: %s',
- 'End date: %s' => 'Data de término: %s',
'Link type' => 'Tipo de link',
'Change task color when using a specific task link' => 'Mudar a cor da tarefa quando um link específico é utilizado',
'Task link creation or modification' => 'Criação ou modificação de um link em uma tarefa',
@@ -1125,4 +1112,10 @@ return array(
// 'Moved:' => '',
// 'Task #%d' => '',
// 'Sub-tasks' => '',
+ // 'Date and time format' => '',
+ // 'Time format' => '',
+ // 'Start date: ' => '',
+ // 'End date: ' => '',
+ // 'New due date: ' => '',
+ // 'Start date changed: ' => '',
);
diff --git a/app/Locale/pt_PT/translations.php b/app/Locale/pt_PT/translations.php
index e952df35..3ffaba0e 100644
--- a/app/Locale/pt_PT/translations.php
+++ b/app/Locale/pt_PT/translations.php
@@ -102,7 +102,6 @@ return array(
'Open a task' => 'Abrir uma tarefa',
'Do you really want to open this task: "%s"?' => 'Tem a certeza que quer abrir esta tarefa: "%s"?',
'Back to the board' => 'Voltar ao quadro',
- 'Created on %B %e, %Y at %k:%M %p' => 'Criado em %d %B %Y às %H:%M',
'There is nobody assigned' => 'Não há ninguém assignado',
'Column on the board:' => 'Coluna no quadro:',
'Close this task' => 'Finalizar esta tarefa',
@@ -156,7 +155,6 @@ return array(
'Work in progress' => 'Em andamento',
'Done' => 'Finalizado',
'Application version:' => 'Versão da aplicação:',
- '%B %e, %Y at %k:%M %p' => '%d %B %Y às %H:%M',
'Id' => 'Id',
'%d closed tasks' => '%d tarefas finalizadas',
'No task for this project' => 'Não há tarefa para este projecto',
@@ -180,8 +178,6 @@ return array(
'Edit this task' => 'Editar esta tarefa',
'Due Date' => 'Data de vencimento',
'Invalid date' => 'Data inválida',
- 'Must be done before %B %e, %Y' => 'Deve ser finalizado antes de %d %B %Y',
- '%B %e, %Y' => '%d %B %Y',
'Automatic actions' => 'Acções automáticas',
'Your automatic action have been created successfully.' => 'A sua acção automática foi criada com sucesso.',
'Unable to create your automatic action.' => 'Não é possível criar a sua acção automática.',
@@ -317,7 +313,6 @@ return array(
'Unable to upload the file.' => 'Não foi possível carregar o arquivo.',
'Display another project' => 'Mostrar outro projecto',
'Created by %s' => 'Criado por %s',
- 'Last modified on %B %e, %Y at %k:%M %p' => 'Última modificação em %B %e, %Y às %k: %M %p',
'Tasks Export' => 'Exportar Tarefas',
'Tasks exportation for "%s"' => 'As tarefas foram exportadas para "%s"',
'Start Date' => 'Data inicial',
@@ -589,7 +584,6 @@ return array(
'This task' => 'Esta tarefa',
'<1h' => '<1h',
'%dh' => '%dh',
- '%b %e' => '%e %b',
'Expand tasks' => 'Expandir tarefas',
'Collapse tasks' => 'Contrair tarefas',
'Expand/collapse tasks' => 'Expandir/Contrair tarefas',
@@ -758,10 +752,6 @@ return array(
'Only for tasks assigned to me' => 'Somente as tarefas atribuídas a mim',
'Only for tasks created by me' => 'Apenas as tarefas que eu criei',
'Only for tasks created by me and assigned to me' => 'Apenas as tarefas que eu criei e aquelas atribuídas a mim',
- '%A' => '%A',
- '%b %e, %Y, %k:%M %p' => '%d/%m/%Y %H:%M',
- 'New due date: %B %e, %Y' => 'Nova data de vencimento: %d/%m/%Y',
- 'Start date changed: %B %e, %Y' => 'Data de início alterada: %d/%m/%Y',
'%%Y-%%m-%%d' => '%%d/%%m/%%Y',
'Total for all columns' => 'Total para todas as colunas',
'You need at least 2 days of data to show the chart.' => 'Precisa de pelo menos 2 dias de dados para visualizar o gráfico.',
@@ -786,7 +776,6 @@ return array(
'Not assigned' => 'Não assignada',
'View advanced search syntax' => 'Ver sintaxe avançada de pesquisa',
'Overview' => 'Visão global',
- '%b %e %Y' => '%b %e %Y',
'Board/Calendar/List view' => 'Vista Painel/Calendário/Lista',
'Switch to the board view' => 'Mudar para o modo Painel',
'Switch to the calendar view' => 'Mudar para o modo Calendário',
@@ -876,8 +865,6 @@ return array(
'End date:' => 'Data de fim:',
'There is no start date or end date for this project.' => 'Não existe data de inicio ou fim para este projecto.',
'Projects Gantt chart' => 'Gráfico de Gantt dos projectos',
- 'Start date: %s' => 'Data de inicio: %s',
- 'End date: %s' => 'Data de fim: %s',
'Link type' => 'Tipo de ligação',
'Change task color when using a specific task link' => 'Alterar cor da tarefa quando se usar um tipo especifico de ligação de tarefa',
'Task link creation or modification' => 'Criação ou modificação de ligação de tarefa',
@@ -1125,4 +1112,10 @@ return array(
// 'Moved:' => '',
// 'Task #%d' => '',
// 'Sub-tasks' => '',
+ // 'Date and time format' => '',
+ // 'Time format' => '',
+ // 'Start date: ' => '',
+ // 'End date: ' => '',
+ // 'New due date: ' => '',
+ // 'Start date changed: ' => '',
);
diff --git a/app/Locale/ru_RU/translations.php b/app/Locale/ru_RU/translations.php
index 1708dcba..f971acc1 100755
--- a/app/Locale/ru_RU/translations.php
+++ b/app/Locale/ru_RU/translations.php
@@ -102,7 +102,6 @@ return array(
'Open a task' => 'Открыть задачу',
'Do you really want to open this task: "%s"?' => 'Вы уверены что хотите открыть задачу: "%s" ?',
'Back to the board' => 'Вернуться на доску',
- 'Created on %B %e, %Y at %k:%M %p' => 'Создано %B /%e /%Y в %k:%M %p',
'There is nobody assigned' => 'Никто не назначен',
'Column on the board:' => 'Колонка на доске: ',
'Close this task' => 'Закрыть задачу',
@@ -156,7 +155,6 @@ return array(
'Work in progress' => 'В процессе',
'Done' => 'Выполнено',
'Application version:' => 'Версия приложения:',
- '%B %e, %Y at %k:%M %p' => '%d/%m/%Y в %H:%M',
'Id' => 'ID',
'%d closed tasks' => '%d завершенных задач',
'No task for this project' => 'Нет задач для этого проекта',
@@ -180,8 +178,6 @@ return array(
'Edit this task' => 'Изменить задачу',
'Due Date' => 'Сделать до',
'Invalid date' => 'Неверная дата',
- 'Must be done before %B %e, %Y' => 'Должно быть сделано до %B %e %Y',
- '%B %e, %Y' => '%B, %e, %Y',
'Automatic actions' => 'Автоматические действия',
'Your automatic action have been created successfully.' => 'Автоматизированное действие успешно настроено.',
'Unable to create your automatic action.' => 'Не удалось создать автоматизированное действие.',
@@ -317,7 +313,6 @@ return array(
'Unable to upload the file.' => 'Не удалось загрузить файл.',
'Display another project' => 'Показать другой проект',
'Created by %s' => 'Создано %s',
- 'Last modified on %B %e, %Y at %k:%M %p' => 'Последнее изменение %d/%m/%Y в %H:%M',
'Tasks Export' => 'Экспорт задач',
'Tasks exportation for "%s"' => 'Задача экспортирована для « %s »',
'Start Date' => 'Дата начала',
@@ -589,7 +584,6 @@ return array(
'This task' => 'Эта задача',
'<1h' => '<1ч',
'%dh' => '%dh',
- '%b %e' => '%b %e',
'Expand tasks' => 'Развернуть задачи',
'Collapse tasks' => 'Свернуть задачи',
'Expand/collapse tasks' => 'Развернуть/свернуть задачи',
@@ -758,10 +752,6 @@ return array(
'Only for tasks assigned to me' => 'Только для задач, назначенных на меня',
'Only for tasks created by me' => 'Только для задач, созданных мной',
'Only for tasks created by me and assigned to me' => 'Только для задач, созданных мной и назначенных мной',
- '%A' => '%A',
- '%b %e, %Y, %k:%M %p' => '%b %e, %Y, %k:%M %p',
- 'New due date: %B %e, %Y' => 'Новая дата завершения: %B %e, %Y',
- 'Start date changed: %B %e, %Y' => 'Изменить дату начала: %B %e, %Y',
'%%Y-%%m-%%d' => '%%Y-%%m-%%d',
'Total for all columns' => 'Суммарно для всех колонок',
'You need at least 2 days of data to show the chart.' => 'Для отображения диаграммы нужно по крайней мере 2 дня.',
@@ -786,7 +776,6 @@ return array(
'Not assigned' => 'Не назначенные',
'View advanced search syntax' => 'Просмотр расширенного синтаксиса поиска',
'Overview' => 'Обзор',
- '%b %e %Y' => '%b %e %Y',
'Board/Calendar/List view' => 'Просмотр Доска/Календарь/Список',
'Switch to the board view' => 'Переключиться в режим доски',
'Switch to the calendar view' => 'Переключиться в режим календаря',
@@ -876,8 +865,6 @@ return array(
'End date:' => 'Дата завершения:',
'There is no start date or end date for this project.' => 'В проекте не указаны дата начала или завершения.',
'Projects Gantt chart' => 'Диаграмма Ганта проектов',
- 'Start date: %s' => 'Дата начала: %s',
- 'End date: %s' => 'Дата завершения: %s',
'Link type' => 'Тип ссылки',
'Change task color when using a specific task link' => 'Изменение цвета задач при использовании ссылки на определенные задачи',
'Task link creation or modification' => 'Ссылка на создание или модификацию задачи',
@@ -1125,4 +1112,10 @@ return array(
'Moved:' => 'Перемещена:',
'Task #%d' => 'Задача #%d',
'Sub-tasks' => 'Подзадачи',
+ // 'Date and time format' => '',
+ // 'Time format' => '',
+ // 'Start date: ' => '',
+ // 'End date: ' => '',
+ // 'New due date: ' => '',
+ // 'Start date changed: ' => '',
);
diff --git a/app/Locale/sr_Latn_RS/translations.php b/app/Locale/sr_Latn_RS/translations.php
index 47ae3d7b..3551c281 100644
--- a/app/Locale/sr_Latn_RS/translations.php
+++ b/app/Locale/sr_Latn_RS/translations.php
@@ -102,7 +102,6 @@ return array(
'Open a task' => 'Otvori zadatak',
'Do you really want to open this task: "%s"?' => 'Da li zaista želiš da otvoriš zadatak: "%s"?',
'Back to the board' => 'Nazad na tablu',
- 'Created on %B %e, %Y at %k:%M %p' => 'Kreiran %e %B %Y o %k:%M',
'There is nobody assigned' => 'Niko nije dodeljen!',
'Column on the board:' => 'Kolona na tabli:',
'Close this task' => 'Zatvori ovaj zadatak',
@@ -156,7 +155,6 @@ return array(
'Work in progress' => 'U radu',
'Done' => 'Gotovo',
'Application version:' => 'Verzija aplikacije:',
- '%B %e, %Y at %k:%M %p' => '%e %B %Y o %k:%M',
'Id' => 'Id',
'%d closed tasks' => '%d zatvorenih zadataka',
'No task for this project' => 'Nema dodeljenih zadataka ovom projektu',
@@ -180,8 +178,6 @@ return array(
'Edit this task' => 'Izmeni ovaj zadatak',
'Due Date' => 'Termin',
'Invalid date' => 'Loš datum',
- 'Must be done before %B %e, %Y' => 'Termin do %e %B %Y',
- '%B %e, %Y' => '%e %B %Y',
'Automatic actions' => 'Automatske akcije',
'Your automatic action have been created successfully.' => 'Uspešno kreirana automatska akcija',
'Unable to create your automatic action.' => 'Nemoguće kreiranje automatske akcije',
@@ -317,7 +313,6 @@ return array(
'Unable to upload the file.' => 'Nije moguće snimiti fajl.',
'Display another project' => 'Prikaži drugi projekat',
'Created by %s' => 'Kreirao %s',
- 'Last modified on %B %e, %Y at %k:%M %p' => 'Poslednja izmena %e %B %Y o %k:%M',
'Tasks Export' => 'Izvoz zadataka',
'Tasks exportation for "%s"' => 'Izvoz zadataka za "%s"',
'Start Date' => 'Početni datum',
@@ -589,7 +584,6 @@ return array(
// 'This task' => '',
// '<1h' => '',
// '%dh' => '',
- // '%b %e' => '',
// 'Expand tasks' => '',
// 'Collapse tasks' => '',
// 'Expand/collapse tasks' => '',
@@ -758,10 +752,6 @@ return array(
// 'Only for tasks assigned to me' => '',
// 'Only for tasks created by me' => '',
// 'Only for tasks created by me and assigned to me' => '',
- // '%A' => '',
- // '%b %e, %Y, %k:%M %p' => '',
- // 'New due date: %B %e, %Y' => '',
- // 'Start date changed: %B %e, %Y' => '',
// '%%Y-%%m-%%d' => '',
// 'Total for all columns' => '',
// 'You need at least 2 days of data to show the chart.' => '',
@@ -786,7 +776,6 @@ return array(
// 'Not assigned' => '',
// 'View advanced search syntax' => '',
// 'Overview' => '',
- // '%b %e %Y' => '',
// 'Board/Calendar/List view' => '',
// 'Switch to the board view' => '',
// 'Switch to the calendar view' => '',
@@ -876,8 +865,6 @@ return array(
// 'End date:' => '',
// 'There is no start date or end date for this project.' => '',
// 'Projects Gantt chart' => '',
- // 'Start date: %s' => '',
- // 'End date: %s' => '',
// 'Link type' => '',
// 'Change task color when using a specific task link' => '',
// 'Task link creation or modification' => '',
@@ -1125,4 +1112,10 @@ return array(
// 'Moved:' => '',
// 'Task #%d' => '',
// 'Sub-tasks' => '',
+ // 'Date and time format' => '',
+ // 'Time format' => '',
+ // 'Start date: ' => '',
+ // 'End date: ' => '',
+ // 'New due date: ' => '',
+ // 'Start date changed: ' => '',
);
diff --git a/app/Locale/sv_SE/translations.php b/app/Locale/sv_SE/translations.php
index 4218561a..c0aa883c 100644
--- a/app/Locale/sv_SE/translations.php
+++ b/app/Locale/sv_SE/translations.php
@@ -102,7 +102,6 @@ return array(
'Open a task' => 'Öppna en uppgift',
'Do you really want to open this task: "%s"?' => 'Vill du verkligen öppna denna uppgift: "%s"?',
'Back to the board' => 'Tillbaka till tavlan',
- 'Created on %B %e, %Y at %k:%M %p' => 'Skapad %Y-%m-%d kl %H:%M',
'There is nobody assigned' => 'Det finns ingen tilldelad',
'Column on the board:' => 'Kolumn på tavlan:',
'Close this task' => 'Stäng uppgiften',
@@ -156,7 +155,6 @@ return array(
'Work in progress' => 'Pågående',
'Done' => 'Slutfört',
'Application version:' => 'Version:',
- '%B %e, %Y at %k:%M %p' => '%Y-%m-%d kl %H:%M',
'Id' => 'ID',
'%d closed tasks' => '%d stängda uppgifter',
'No task for this project' => 'Inga uppgifter i detta projekt',
@@ -180,8 +178,6 @@ return array(
'Edit this task' => 'Ändra denna uppgift',
'Due Date' => 'Måldatum',
'Invalid date' => 'Ej tillåtet datum',
- 'Must be done before %B %e, %Y' => 'Måste vara klart innan %Y-%m-%d',
- '%B %e, %Y' => '%Y-%m-%d',
'Automatic actions' => 'Automatiska åtgärder',
'Your automatic action have been created successfully.' => 'Din automatiska åtgärd har skapats.',
'Unable to create your automatic action.' => 'Kunde inte skapa din automatiska åtgärd.',
@@ -317,7 +313,6 @@ return array(
'Unable to upload the file.' => 'Kunde inte ladda upp filen.',
'Display another project' => 'Visa ett annat projekt',
'Created by %s' => 'Skapad av %s',
- 'Last modified on %B %e, %Y at %k:%M %p' => 'Senaste ändring %Y-%m-%d kl %H:%M',
'Tasks Export' => 'Exportera uppgifter',
'Tasks exportation for "%s"' => 'Exportera uppgifter för "%s"',
'Start Date' => 'Startdatum',
@@ -589,7 +584,6 @@ return array(
'This task' => 'Denna uppgift',
'<1h' => '<1h',
'%dh' => '%dh',
- '%b %e' => '%b %e',
'Expand tasks' => 'Expandera uppgifter',
'Collapse tasks' => 'Minimera uppgifter',
'Expand/collapse tasks' => 'Expandera/minimera uppgifter',
@@ -758,10 +752,6 @@ return array(
'Only for tasks assigned to me' => 'Bara för uppgifter tilldelade mig',
'Only for tasks created by me' => 'Bara för uppgifter skapade av mig',
'Only for tasks created by me and assigned to me' => 'Bara för uppgifter skapade av mig och tilldelade till mig',
- '%A' => '%A',
- '%b %e, %Y, %k:%M %p' => '%b %e, %Y, %k:%M %p',
- 'New due date: %B %e, %Y' => 'Nytt förfallodatum: %B %e, %Y',
- 'Start date changed: %B %e, %Y' => 'Startdatum ändrat: %B %e, %Y',
'%%Y-%%m-%%d' => '%%Y-%%m-%%d',
'Total for all columns' => 'Totalt för alla kolumner',
'You need at least 2 days of data to show the chart.' => 'Du behöver minst två dagars data för att visa diagrammet.',
@@ -786,7 +776,6 @@ return array(
'Not assigned' => 'Inte tilldelad',
'View advanced search syntax' => 'Visa avancerad söksyntax',
'Overview' => 'Översikts',
- '%b %e %Y' => '%b %e %Y',
'Board/Calendar/List view' => 'Tavla/Kalender/Listvy',
'Switch to the board view' => 'Växla till tavelvy',
'Switch to the calendar view' => 'Växla till kalendervy',
@@ -876,8 +865,6 @@ return array(
// 'End date:' => '',
// 'There is no start date or end date for this project.' => '',
// 'Projects Gantt chart' => '',
- // 'Start date: %s' => '',
- // 'End date: %s' => '',
// 'Link type' => '',
// 'Change task color when using a specific task link' => '',
// 'Task link creation or modification' => '',
@@ -1125,4 +1112,10 @@ return array(
// 'Moved:' => '',
// 'Task #%d' => '',
// 'Sub-tasks' => '',
+ // 'Date and time format' => '',
+ // 'Time format' => '',
+ // 'Start date: ' => '',
+ // 'End date: ' => '',
+ // 'New due date: ' => '',
+ // 'Start date changed: ' => '',
);
diff --git a/app/Locale/th_TH/translations.php b/app/Locale/th_TH/translations.php
index eb4c0e77..1ccc2d90 100644
--- a/app/Locale/th_TH/translations.php
+++ b/app/Locale/th_TH/translations.php
@@ -102,7 +102,6 @@ return array(
'Open a task' => 'เปิดงาน',
'Do you really want to open this task: "%s"?' => 'คุณต้องการเปิดงาน: « %s » ใช่หรือไม่?',
'Back to the board' => 'กลับไปที่บอร์ด',
- 'Created on %B %e, %Y at %k:%M %p' => 'สร้างวันที่ %d/%m/%Y เวลา %H:%M',
'There is nobody assigned' => 'ไม่มีใครถูกกำหนด',
'Column on the board:' => 'คอลัมน์บนบอร์ด:',
'Close this task' => 'ปิดงานนี้',
@@ -156,7 +155,6 @@ return array(
'Work in progress' => 'กำลังทำ',
'Done' => 'เสร็จ',
'Application version:' => 'แอพเวอร์ชัน:',
- '%B %e, %Y at %k:%M %p' => '%d/%m/%Y เวลา %H:%M',
'Id' => 'ไอดี',
'%d closed tasks' => '%d งานที่ปิด',
'No task for this project' => 'ไม่มีงานสำหรับโปรเจคนี้',
@@ -180,8 +178,6 @@ return array(
'Edit this task' => 'แก้ไขงาน',
'Due Date' => 'วันที่ครบกำหนด',
'Invalid date' => 'วันที่ผิด',
- 'Must be done before %B %e, %Y' => 'ต้องทำให้เสร็จก่อน %d/%m/%Y',
- '%B %e, %Y' => '%d/%m/%Y',
'Automatic actions' => 'การกระทำอัตโนมัติ',
'Your automatic action have been created successfully.' => 'การกระทำอัตโนมัติสร้างเรียบร้อยแล้ว',
'Unable to create your automatic action.' => 'ไม่สามารถสร้างการกระทำอัตโนมัติได้',
@@ -317,7 +313,6 @@ return array(
'Unable to upload the file.' => 'ไม่สามารถอัพโหลดไฟล์ได้',
'Display another project' => 'แสดงโปรเจคอื่น',
'Created by %s' => 'สร้างโดย %s',
- 'Last modified on %B %e, %Y at %k:%M %p' => 'แก้ไขล่าสุดวันที่ %B %e, %Y เวลา %k:%M %p',
'Tasks Export' => 'ส่งออกงาน',
'Tasks exportation for "%s"' => 'ส่งออกงานสำหรับ "%s"',
'Start Date' => 'เริ่มวันที่',
@@ -589,7 +584,6 @@ return array(
'This task' => 'งานนี้',
// '<1h' => '',
// '%dh' => '',
- // '%b %e' => '',
'Expand tasks' => 'ขยายงาน',
'Collapse tasks' => 'ย่องาน',
'Expand/collapse tasks' => 'ขยาย/ย่อ งาน',
@@ -758,10 +752,6 @@ return array(
// 'Only for tasks assigned to me' => '',
// 'Only for tasks created by me' => '',
// 'Only for tasks created by me and assigned to me' => '',
- // '%A' => '',
- // '%b %e, %Y, %k:%M %p' => '',
- // 'New due date: %B %e, %Y' => '',
- // 'Start date changed: %B %e, %Y' => '',
// '%%Y-%%m-%%d' => '',
// 'Total for all columns' => '',
// 'You need at least 2 days of data to show the chart.' => '',
@@ -786,7 +776,6 @@ return array(
// 'Not assigned' => '',
// 'View advanced search syntax' => '',
// 'Overview' => '',
- // '%b %e %Y' => '',
// 'Board/Calendar/List view' => '',
// 'Switch to the board view' => '',
// 'Switch to the calendar view' => '',
@@ -876,8 +865,6 @@ return array(
// 'End date:' => '',
// 'There is no start date or end date for this project.' => '',
// 'Projects Gantt chart' => '',
- // 'Start date: %s' => '',
- // 'End date: %s' => '',
// 'Link type' => '',
// 'Change task color when using a specific task link' => '',
// 'Task link creation or modification' => '',
@@ -1125,4 +1112,10 @@ return array(
// 'Moved:' => '',
// 'Task #%d' => '',
// 'Sub-tasks' => '',
+ // 'Date and time format' => '',
+ // 'Time format' => '',
+ // 'Start date: ' => '',
+ // 'End date: ' => '',
+ // 'New due date: ' => '',
+ // 'Start date changed: ' => '',
);
diff --git a/app/Locale/tr_TR/translations.php b/app/Locale/tr_TR/translations.php
index 6fecb37a..10153331 100644
--- a/app/Locale/tr_TR/translations.php
+++ b/app/Locale/tr_TR/translations.php
@@ -102,7 +102,6 @@ return array(
'Open a task' => 'Bir görevi aç',
'Do you really want to open this task: "%s"?' => 'Bu görevi gerçekten açmak istiyor musunuz: "%s"?',
'Back to the board' => 'Tabloya dön',
- 'Created on %B %e, %Y at %k:%M %p' => '%B %e, %Y, saat %k:%M %p da oluşturuldu',
'There is nobody assigned' => 'Kimse atanmamış',
'Column on the board:' => 'Tablodaki sütun:',
'Close this task' => 'Görevi kapat',
@@ -156,7 +155,6 @@ return array(
'Work in progress' => 'İşlemde',
'Done' => 'Tamamlandı',
'Application version:' => 'Uygulama versiyonu:',
- '%B %e, %Y at %k:%M %p' => '%B %e, %Y saat %k:%M %p',
'Id' => 'Kod',
'%d closed tasks' => '%d kapatılmış görevler',
'No task for this project' => 'Bu proje için görev yok',
@@ -180,8 +178,6 @@ return array(
'Edit this task' => 'Bu görevi değiştir',
'Due Date' => 'Bitiş Tarihi',
'Invalid date' => 'Geçersiz tarihi',
- 'Must be done before %B %e, %Y' => '%B %e, %Y tarihinden önce yapılmalı',
- '%B %e, %Y' => '%d %B %Y',
'Automatic actions' => 'Otomatik işlemler',
'Your automatic action have been created successfully.' => 'Otomatik işlem başarıyla oluşturuldu',
'Unable to create your automatic action.' => 'Otomatik işleminiz oluşturulamadı',
@@ -317,7 +313,6 @@ return array(
'Unable to upload the file.' => 'Dosya yüklenemiyor.',
'Display another project' => 'Başka bir proje göster',
'Created by %s' => '%s tarafından oluşturuldu',
- 'Last modified on %B %e, %Y at %k:%M %p' => 'Son değişiklik tarihi %d.%m.%Y, saati %H:%M',
'Tasks Export' => 'Görevleri dışa aktar',
'Tasks exportation for "%s"' => '"%s" için görevleri dışa aktar',
'Start Date' => 'Başlangıç tarihi',
@@ -589,7 +584,6 @@ return array(
'This task' => 'Bu görev',
'<1h' => '<1s',
'%dh' => '%ds',
- // '%b %e' => '',
'Expand tasks' => 'Görevleri genişlet',
'Collapse tasks' => 'Görevleri daralt',
'Expand/collapse tasks' => 'Görevleri genişlet/daralt',
@@ -758,10 +752,6 @@ return array(
'Only for tasks assigned to me' => 'Yalnızca bana atanmış görevler için',
'Only for tasks created by me' => 'Yalnızca benim oluşturduğum görevler için',
'Only for tasks created by me and assigned to me' => 'Yalnızca benim oluşturduğum ve bana atanmış görevler için',
- '%A' => '%A',
- '%b %e, %Y, %k:%M %p' => '%b %e, %Y, %k:%M %p',
- 'New due date: %B %e, %Y' => 'Yeni tamamlanma tarihi: %B %e, %Y',
- 'Start date changed: %B %e, %Y' => 'Başlangıç tarihi değiştirildi: %B %e, %Y',
'%%Y-%%m-%%d' => '%%Y-%%m-%%d',
'Total for all columns' => 'Tüm sütunlar için toplam',
'You need at least 2 days of data to show the chart.' => 'Grafiği göstermek için en az iki günlük veriye ihtiyaç var.',
@@ -786,7 +776,6 @@ return array(
'Not assigned' => 'Atanmamış',
'View advanced search syntax' => 'Gelişmiş arama kodlarını göster',
'Overview' => 'Genel bakış',
- '%b %e %Y' => '%b %e %Y',
'Board/Calendar/List view' => 'Tablo/Takvim/Liste görünümü',
'Switch to the board view' => 'Tablo görünümüne geç',
'Switch to the calendar view' => 'Takvim görünümüne geç',
@@ -876,8 +865,6 @@ return array(
'End date:' => 'Bitiş tarihi:',
'There is no start date or end date for this project.' => 'Bu proje için başlangıç veya bitiş tarihi yok.',
'Projects Gantt chart' => 'Projeler Gantt diyagramı',
- 'Start date: %s' => 'Başlangıç tarihi: %s',
- 'End date: %s' => 'Bitiş tarihi: %s',
'Link type' => 'Bağlantı türü',
'Change task color when using a specific task link' => 'Belirli bir görev bağlantısı kullanıldığında görevin rengini değiştir',
'Task link creation or modification' => 'Görev bağlantısı oluşturulması veya değiştirilmesi',
@@ -1125,4 +1112,10 @@ return array(
// 'Moved:' => '',
// 'Task #%d' => '',
// 'Sub-tasks' => '',
+ // 'Date and time format' => '',
+ // 'Time format' => '',
+ // 'Start date: ' => '',
+ // 'End date: ' => '',
+ // 'New due date: ' => '',
+ // 'Start date changed: ' => '',
);
diff --git a/app/Locale/zh_CN/translations.php b/app/Locale/zh_CN/translations.php
index ae90468d..acdcdf30 100644
--- a/app/Locale/zh_CN/translations.php
+++ b/app/Locale/zh_CN/translations.php
@@ -102,7 +102,6 @@ return array(
'Open a task' => '开一个任务',
'Do you really want to open this task: "%s"?' => '你确定要开这个任务吗?"%s"',
'Back to the board' => '回到看板',
- 'Created on %B %e, %Y at %k:%M %p' => '创建时间:%Y/%m/%d %H:%M',
'There is nobody assigned' => '当前无人被指派',
'Column on the board:' => '看板上的栏目:',
'Close this task' => '关闭该任务',
@@ -156,7 +155,6 @@ return array(
'Work in progress' => '工作进行中',
'Done' => '完成',
'Application version:' => '应用程序版本:',
- '%B %e, %Y at %k:%M %p' => '%Y/%m/%d %H:%M',
'Id' => '编号',
'%d closed tasks' => '%d个已关闭任务',
'No task for this project' => '该项目尚无任务',
@@ -180,8 +178,6 @@ return array(
'Edit this task' => '编辑该任务',
'Due Date' => '到期时间',
'Invalid date' => '无效日期',
- 'Must be done before %B %e, %Y' => '必须在%Y/%m/%d前完成',
- '%B %e, %Y' => '%Y/%m/%d',
'Automatic actions' => '自动动作',
'Your automatic action have been created successfully.' => '您的自动动作已成功创建',
'Unable to create your automatic action.' => '无法为您创建自动动作。',
@@ -317,7 +313,6 @@ return array(
'Unable to upload the file.' => '无法上传文件',
'Display another project' => '显示其它项目',
'Created by %s' => '创建者:%s',
- 'Last modified on %B %e, %Y at %k:%M %p' => '最后修改:%Y/%m/%d/ %H:%M',
'Tasks Export' => '任务导出',
'Tasks exportation for "%s"' => '导出"%s"的任务',
'Start Date' => '开始时间',
@@ -589,7 +584,6 @@ return array(
'This task' => '此任务',
'<1h' => '<1h',
'%dh' => '%dh',
- // '%b %e' => '',
'Expand tasks' => '展开任务',
'Collapse tasks' => '收缩任务',
'Expand/collapse tasks' => '展开/收缩任务',
@@ -758,10 +752,6 @@ return array(
'Only for tasks assigned to me' => '所有指派给我的任务',
'Only for tasks created by me' => '所有我创建的任务',
'Only for tasks created by me and assigned to me' => '所有我创建的并且指派给我的任务',
- // '%A' => '',
- // '%b %e, %Y, %k:%M %p' => '',
- 'New due date: %B %e, %Y' => '新的超期时间:%B %e, %Y',
- 'Start date changed: %B %e, %Y' => '开始时间已变为:%B %e, %Y',
// '%%Y-%%m-%%d' => '',
'Total for all columns' => '所有栏目下的',
'You need at least 2 days of data to show the chart.' => '当前柱状图至少需要2天的数据。',
@@ -786,7 +776,6 @@ return array(
'Not assigned' => '未指派',
'View advanced search syntax' => '查看高级搜索语法',
'Overview' => '概览',
- // '%b %e %Y' => '',
'Board/Calendar/List view' => '看板/日程/列表视图',
'Switch to the board view' => '切换到看板视图',
'Switch to the calendar view' => '切换到日程视图',
@@ -876,8 +865,6 @@ return array(
'End date:' => '结束日期',
'There is no start date or end date for this project.' => '当前项目没有开始或结束日期',
'Projects Gantt chart' => '项目甘特图',
- 'Start date: %s' => '开始日期%s',
- 'End date: %s' => '结束日期%s',
'Link type' => '关联类型',
'Change task color when using a specific task link' => '当任务关联到指定任务时改变颜色',
'Task link creation or modification' => '任务链接创建或更新时间',
@@ -1125,4 +1112,10 @@ return array(
// 'Moved:' => '',
// 'Task #%d' => '',
// 'Sub-tasks' => '',
+ // 'Date and time format' => '',
+ // 'Time format' => '',
+ // 'Start date: ' => '',
+ // 'End date: ' => '',
+ // 'New due date: ' => '',
+ // 'Start date changed: ' => '',
);
diff --git a/app/Model/File.php b/app/Model/File.php
index be62cdb3..46fc4bb9 100644
--- a/app/Model/File.php
+++ b/app/Model/File.php
@@ -308,7 +308,7 @@ class File extends Base
*/
public function uploadScreenshot($project_id, $task_id, $blob)
{
- $original_filename = e('Screenshot taken %s', dt('%B %e, %Y at %k:%M %p', time())).'.png';
+ $original_filename = e('Screenshot taken %s', $this->helper->dt->datetime(time())).'.png';
return $this->uploadContent($project_id, $task_id, $original_filename, $blob);
}
diff --git a/app/Model/TaskCreation.php b/app/Model/TaskCreation.php
index 975cc7a3..f7d981fa 100644
--- a/app/Model/TaskCreation.php
+++ b/app/Model/TaskCreation.php
@@ -49,8 +49,9 @@ class TaskCreation extends Base
*/
public function prepare(array &$values)
{
- $this->dateParser->convert($values, array('date_due'));
- $this->dateParser->convert($values, array('date_started'), true);
+ $values = $this->dateParser->convert($values, array('date_due'));
+ $values = $this->dateParser->convert($values, array('date_started'), true);
+
$this->removeFields($values, array('another_task'));
$this->resetFields($values, array('date_started', 'creator_id', 'owner_id', 'swimlane_id', 'date_due', 'score', 'category_id', 'time_estimated'));
diff --git a/app/Model/TaskExport.php b/app/Model/TaskExport.php
index 278c0897..ed179a4f 100644
--- a/app/Model/TaskExport.php
+++ b/app/Model/TaskExport.php
@@ -106,7 +106,7 @@ class TaskExport extends Base
$task['score'] = $task['score'] ?: 0;
$task['swimlane_id'] = isset($swimlanes[$task['swimlane_id']]) ? $swimlanes[$task['swimlane_id']] : '?';
- $this->dateParser->format($task, array('date_due', 'date_modification', 'date_creation', 'date_started', 'date_completed'), 'Y-m-d');
+ $task = $this->dateParser->format($task, array('date_due', 'date_modification', 'date_creation', 'date_started', 'date_completed'), 'Y-m-d');
return $task;
}
diff --git a/app/Model/TaskModification.php b/app/Model/TaskModification.php
index eee7b2e0..8e59b3fe 100644
--- a/app/Model/TaskModification.php
+++ b/app/Model/TaskModification.php
@@ -84,8 +84,9 @@ class TaskModification extends Base
*/
public function prepare(array &$values)
{
- $this->dateParser->convert($values, array('date_due'));
- $this->dateParser->convert($values, array('date_started'), true);
+ $values = $this->dateParser->convert($values, array('date_due'));
+ $values = $this->dateParser->convert($values, array('date_started'), true);
+
$this->removeFields($values, array('another_task', 'id'));
$this->resetFields($values, array('date_due', 'date_started', 'score', 'category_id', 'time_estimated', 'time_spent'));
$this->convertIntegerFields($values, array('priority', 'is_active', 'recurrence_status', 'recurrence_trigger', 'recurrence_factor', 'recurrence_timeframe', 'recurrence_basedate'));
diff --git a/app/Template/app/notifications.php b/app/Template/app/notifications.php
index 511f377b..4cb3c571 100644
--- a/app/Template/app/notifications.php
+++ b/app/Template/app/notifications.php
@@ -49,7 +49,7 @@
- = dt('%B %e, %Y at %k:%M %p', $notification['date_creation']) ?>
+ = $this->dt->datetime($notification['date_creation']) ?>
diff --git a/app/Template/app/tasks.php b/app/Template/app/tasks.php
index f4f9b2ad..786d7159 100644
--- a/app/Template/app/tasks.php
+++ b/app/Template/app/tasks.php
@@ -33,7 +33,7 @@
- = dt('%B %e, %Y', $task['date_due']) ?>
+ = $this->dt->date($task['date_due']) ?>
diff --git a/app/Template/board/task_footer.php b/app/Template/board/task_footer.php
index 1912dd83..73e68602 100644
--- a/app/Template/board/task_footer.php
+++ b/app/Template/board/task_footer.php
@@ -22,7 +22,7 @@
- = (date('Y') === date('Y', $task['date_due']) ? dt('%b %e', $task['date_due']) : dt('%b %e %Y', $task['date_due'])) ?>
+ = $this->dt->date($task['date_due']) ?>
diff --git a/app/Template/board/tooltip_comments.php b/app/Template/board/tooltip_comments.php
index 2e2c0c1e..ca91e13f 100644
--- a/app/Template/board/tooltip_comments.php
+++ b/app/Template/board/tooltip_comments.php
@@ -4,7 +4,7 @@
@
-
+
= $this->e($file['name']) ?>
- '.t('uploaded on: %s', dt('%B %e, %Y at %k:%M %p', $file['date'])).' '.t('size: %s', $this->text->bytes($file['size'])) ?>'>
+ '.t('uploaded on: %s', $this->dt->datetime($file['date'])).' '.t('size: %s', $this->text->bytes($file['size'])) ?>'>
@@ -38,7 +38,7 @@
= $this->e($file['name']) ?>
- '.t('uploaded on: %s', dt('%B %e, %Y at %k:%M %p', $file['date'])).' '.t('size: %s', $this->text->bytes($file['size'])) ?>'>
+ '.t('uploaded on: %s', $this->dt->datetime($file['date'])).' '.t('size: %s', $this->text->bytes($file['size'])) ?>'>
diff --git a/app/Template/listing/show.php b/app/Template/listing/show.php
index c24110f4..e7aa5947 100644
--- a/app/Template/listing/show.php
+++ b/app/Template/listing/show.php
@@ -43,7 +43,7 @@
- = dt('%B %e, %Y', $task['date_due']) ?>
+ = $this->dt->date($task['date_due']) ?>
diff --git a/app/Template/notification/task_create.php b/app/Template/notification/task_create.php
index 1d834d44..fb7898fc 100644
--- a/app/Template/notification/task_create.php
+++ b/app/Template/notification/task_create.php
@@ -2,11 +2,11 @@
- = dt('Created on %B %e, %Y at %k:%M %p', $task['date_creation']) ?>
+ = t('Created:').' '.$this->dt->datetime($task['date_creation']) ?>
- = dt('Must be done before %B %e, %Y', $task['date_due']) ?>
+ = t('Due date:').' '.$this->dt->date($task['date_due']) ?>
diff --git a/app/Template/notification/task_overdue.php b/app/Template/notification/task_overdue.php
index a231937b..d7e6ff5a 100644
--- a/app/Template/notification/task_overdue.php
+++ b/app/Template/notification/task_overdue.php
@@ -9,7 +9,7 @@
= $this->e($task['title']) ?>
- (= dt('%B %e, %Y', $task['date_due']) ?>)
+ (= $this->dt->date($task['date_due']) ?>)
(= t('Assigned to %s', $task['assignee_name'] ?: $task['assignee_username']) ?> )
diff --git a/app/Template/project/index.php b/app/Template/project/index.php
index c5dd267c..8d384e58 100644
--- a/app/Template/project/index.php
+++ b/app/Template/project/index.php
@@ -57,10 +57,10 @@
= $this->url->link($this->e($project['name']), 'project', 'show', array('project_id' => $project['id'])) ?>
- = $project['start_date'] ?>
+ = $this->dt->date($project['start_date']) ?>
- = $project['end_date'] ?>
+ = $this->dt->date($project['end_date']) ?>
0): ?>
diff --git a/app/Template/project/show.php b/app/Template/project/show.php
index 5f1aefc1..166b8902 100644
--- a/app/Template/project/show.php
+++ b/app/Template/project/show.php
@@ -21,15 +21,15 @@
- = dt('Last modified on %B %e, %Y at %k:%M %p', $project['last_modified']) ?>
+ = t('Modified:').' '.$this->dt->datetime($project['last_modified']) ?>
- = t('Start date: %s', $project['start_date']) ?>
+ = t('Start date: ').$this->dt->date($project['start_date']) ?>
- = t('End date: %s', $project['end_date']) ?>
+ = t('End date: ').$this->dt->date($project['end_date']) ?>
0): ?>
diff --git a/app/Template/project_user/tasks.php b/app/Template/project_user/tasks.php
index f4fc2723..8d1cbd96 100644
--- a/app/Template/project_user/tasks.php
+++ b/app/Template/project_user/tasks.php
@@ -33,10 +33,10 @@
- = dt('%B %e, %Y', $task['date_started']) ?>
+ = $this->dt->date($task['date_started']) ?>
- = dt('%B %e, %Y', $task['date_due']) ?>
+ = $this->dt->date($task['date_due']) ?>
diff --git a/app/Template/search/results.php b/app/Template/search/results.php
index 88eed87c..3bb0e603 100644
--- a/app/Template/search/results.php
+++ b/app/Template/search/results.php
@@ -38,7 +38,7 @@
- = dt('%B %e, %Y', $task['date_due']) ?>
+ = $this->dt->date($task['date_due']) ?>
diff --git a/app/Template/task/changes.php b/app/Template/task/changes.php
index f288a8f4..db844857 100644
--- a/app/Template/task/changes.php
+++ b/app/Template/task/changes.php
@@ -31,7 +31,7 @@
if (empty($task['date_due'])) {
echo ''.t('The due date have been removed').' ';
} else {
- echo ''.dt('New due date: %B %e, %Y', $task['date_due']).' ';
+ echo ''.t('New due date: ').$this->dt->date($task['date_due']).' ';
}
break;
case 'description':
@@ -56,7 +56,7 @@
break;
case 'date_started':
if ($value != 0) {
- echo ''.dt('Start date changed: %B %e, %Y', $task['date_started']).' ';
+ echo ''.t('Start date changed: ').$this->dt->datetime($task['date_started']).' ';
}
break;
default:
diff --git a/app/Template/task/details.php b/app/Template/task/details.php
index 838eb260..5c2e3cff 100644
--- a/app/Template/task/details.php
+++ b/app/Template/task/details.php
@@ -79,7 +79,7 @@
= t('Due date:') ?>
- = dt('%B %e, %Y', $task['date_due']) ?>
+ = $this->dt->date($task['date_due']) ?>
@@ -100,28 +100,28 @@
= t('Created:') ?>
- = dt('%B %e, %Y at %k:%M %p', $task['date_creation']) ?>
+ = $this->dt->datetime($task['date_creation']) ?>
= t('Modified:') ?>
- = dt('%B %e, %Y at %k:%M %p', $task['date_modification']) ?>
+ = $this->dt->datetime($task['date_modification']) ?>
= t('Completed:') ?>
- = dt('%B %e, %Y at %k:%M %p', $task['date_completed']) ?>
+ = $this->dt->datetime($task['date_completed']) ?>
= t('Started:') ?>
- = dt('%B %e, %Y at %k:%M %p', $task['date_started']) ?>
+ = $this->dt->datetime($task['date_started']) ?>
= t('Moved:') ?>
- = dt('%B %e, %Y at %k:%M %p', $task['date_moved']) ?>
+ = $this->dt->datetime($task['date_moved']) ?>
diff --git a/app/Template/task/time_tracking_details.php b/app/Template/task/time_tracking_details.php
index 85ad5567..147c5109 100644
--- a/app/Template/task/time_tracking_details.php
+++ b/app/Template/task/time_tracking_details.php
@@ -16,8 +16,8 @@
= $this->url->link($this->e($record['user_fullname'] ?: $record['username']), 'user', 'show', array('user_id' => $record['user_id'])) ?>
= t($record['subtask_title']) ?>
- = dt('%B %e, %Y at %k:%M %p', $record['start']) ?>
- = dt('%B %e, %Y at %k:%M %p', $record['end']) ?>
+ = $this->dt->datetime($record['start']) ?>
+ = $this->dt->datetime($record['end']) ?>
= n($record['time_spent']).' '.t('hours') ?>
diff --git a/app/Template/task/transitions.php b/app/Template/task/transitions.php
index 2ca2387f..d79c2fd9 100644
--- a/app/Template/task/transitions.php
+++ b/app/Template/task/transitions.php
@@ -15,7 +15,7 @@
- = dt('%B %e, %Y at %k:%M %p', $transition['date']) ?>
+ = $this->dt->datetime($transition['date']) ?>
= $this->e($transition['src_column']) ?>
= $this->e($transition['dst_column']) ?>
= $this->url->link($this->e($transition['name'] ?: $transition['username']), 'user', 'show', array('user_id' => $transition['user_id'])) ?>
diff --git a/app/Template/task_external_link/show.php b/app/Template/task_external_link/show.php
index 2dc3d1dd..12d8e4f6 100644
--- a/app/Template/task_external_link/show.php
+++ b/app/Template/task_external_link/show.php
@@ -31,7 +31,7 @@
= $this->e($link['creator_name'] ?: $link['creator_username']) ?>
- = dt('%B %e, %Y', $link['date_creation']) ?>
+ = $this->dt->date($link['date_creation']) ?>
user->hasProjectAccess('TaskExternalLink', 'edit', $task['project_id'])): ?>
diff --git a/app/Template/user/last.php b/app/Template/user/last.php
index 8879466e..d6c86391 100644
--- a/app/Template/user/last.php
+++ b/app/Template/user/last.php
@@ -14,7 +14,7 @@
- = dt('%B %e, %Y at %k:%M %p', $login['date_creation']) ?>
+ = $this->dt->datetime($login['date_creation']) ?>
= $this->e($login['auth_type']) ?>
= $this->e($login['ip']) ?>
= $this->e($login['user_agent']) ?>
diff --git a/app/Template/user/password_reset.php b/app/Template/user/password_reset.php
index b4c9a0c4..4e9063ef 100644
--- a/app/Template/user/password_reset.php
+++ b/app/Template/user/password_reset.php
@@ -15,8 +15,8 @@
- = dt('%B %e, %Y at %k:%M %p', $token['date_creation']) ?>
- = dt('%B %e, %Y at %k:%M %p', $token['date_expiration']) ?>
+ = $this->dt->datetime($token['date_creation']) ?>
+ = $this->dt->datetime($token['date_expiration']) ?>
= $token['is_active'] == 0 ? t('No') : t('Yes') ?>
= $this->e($token['ip']) ?>
= $this->e($token['user_agent']) ?>
diff --git a/app/Template/user/sessions.php b/app/Template/user/sessions.php
index 7a66c5ad..8db02430 100644
--- a/app/Template/user/sessions.php
+++ b/app/Template/user/sessions.php
@@ -15,8 +15,8 @@
- = dt('%B %e, %Y at %k:%M %p', $session['date_creation']) ?>
- = dt('%B %e, %Y at %k:%M %p', $session['expiration']) ?>
+ = $this->dt->datetime($session['date_creation']) ?>
+ = $this->dt->datetime($session['expiration']) ?>
= $this->e($session['ip']) ?>
= $this->e($session['user_agent']) ?>
= $this->url->link(t('Remove'), 'User', 'removeSession', array('user_id' => $user['id'], 'id' => $session['id']), true) ?>
diff --git a/app/Template/user/timesheet.php b/app/Template/user/timesheet.php
index 5c0d3af8..4a6e42c5 100644
--- a/app/Template/user/timesheet.php
+++ b/app/Template/user/timesheet.php
@@ -18,8 +18,8 @@
= $this->url->link($this->e($record['task_title']), 'task', 'show', array('project_id' => $record['project_id'], 'task_id' => $record['task_id'])) ?>
= $this->url->link($this->e($record['subtask_title']), 'task', 'show', array('project_id' => $record['project_id'], 'task_id' => $record['task_id'])) ?>
- = dt('%B %e, %Y at %k:%M %p', $record['start']) ?>
- = dt('%B %e, %Y at %k:%M %p', $record['end']) ?>
+ = $this->dt->datetime($record['start']) ?>
+ = $this->dt->datetime($record['end']) ?>
= n($record['time_spent']).' '.t('hours') ?>
diff --git a/app/Validator/TaskValidator.php b/app/Validator/TaskValidator.php
index 7b73aeba..1a77dd32 100644
--- a/app/Validator/TaskValidator.php
+++ b/app/Validator/TaskValidator.php
@@ -40,8 +40,8 @@ class TaskValidator extends Base
new Validators\Integer('priority', t('This value must be an integer')),
new Validators\MaxLength('title', t('The maximum length is %d characters', 200), 200),
new Validators\MaxLength('reference', t('The maximum length is %d characters', 50), 50),
- new Validators\Date('date_due', t('Invalid date'), $this->dateParser->getDateFormats()),
- new Validators\Date('date_started', t('Invalid date'), $this->dateParser->getAllFormats()),
+ new Validators\Date('date_due', t('Invalid date'), $this->dateParser->getDateFormats(true)),
+ new Validators\Date('date_started', t('Invalid date'), $this->dateParser->getDateTimeFormats(true)),
new Validators\Numeric('time_spent', t('This value must be numeric')),
new Validators\Numeric('time_estimated', t('This value must be numeric')),
);
diff --git a/app/functions.php b/app/functions.php
index fe6e6757..b9b30834 100644
--- a/app/functions.php
+++ b/app/functions.php
@@ -31,13 +31,3 @@ function n($value)
{
return Translator::getInstance()->number($value);
}
-
-/**
- * Translate a date
- *
- * @return string
- */
-function dt($format, $timestamp)
-{
- return Translator::getInstance()->datetime($format, $timestamp);
-}
diff --git a/doc/translations.markdown b/doc/translations.markdown
index 629c4355..00707e1c 100644
--- a/doc/translations.markdown
+++ b/doc/translations.markdown
@@ -5,7 +5,7 @@ How to translate Kanboard to a new language?
--------------------------------------------
- Translations are stored inside the directory `app/Locale`
-- There is subdirectory for each language, for example in French we have `fr_FR`, Italian `it_IT` etc.
+- There is a subdirectory for each language, for example in French we have `fr_FR`, Italian `it_IT` etc.
- A translation is a PHP file that returns an Array with a key-value pairs
- The key is the original text in English and the value is the translation of the corresponding language
- **French translations are always up to date**
@@ -34,20 +34,9 @@ Translations are displayed with the following functions in the source code:
- `t()`: display text with HTML escaping
- `e()`: display text without HTML escaping
-- `dt()`: display date and time using the `strftime()` function formats
Always use the english version in the source code.
-### Date and time translation
-
-Date strings use the function `strftime()` to format the date.
-
-For example, the original English version can be defined like that `Created on %B %e, %Y at %k:%M %p` and that will output something like that `Created on January 11, 2015 at 15:19 PM`. The French version can be modified to display a different format, `Créé le %d/%m/%Y à %H:%M` and the result will be `Créé le 11/01/2015 à 15:19`.
-
-All formats are available in the [PHP documentation](http://php.net/strftime).
-
-### Placeholders
-
Text strings use the function `sprintf()` to replace elements:
- `%s` is used to replace a string
diff --git a/tests/units/Core/DateParserTest.php b/tests/units/Core/DateParserTest.php
index 0d345784..dc3366b3 100644
--- a/tests/units/Core/DateParserTest.php
+++ b/tests/units/Core/DateParserTest.php
@@ -6,79 +6,167 @@ use Kanboard\Core\DateParser;
class DateParserTest extends Base
{
+ public function testGetTimeFormats()
+ {
+ $dateParser = new DateParser($this->container);
+ $this->assertCount(2, $dateParser->getTimeFormats());
+ $this->assertContains('H:i', $dateParser->getTimeFormats());
+ $this->assertContains('g:i a', $dateParser->getTimeFormats());
+ }
+
+ public function testGetDateFormats()
+ {
+ $dateParser = new DateParser($this->container);
+ $this->assertCount(4, $dateParser->getDateFormats());
+ $this->assertCount(6, $dateParser->getDateFormats(true));
+ $this->assertContains('d/m/Y', $dateParser->getDateFormats());
+ $this->assertNotContains('Y-m-d', $dateParser->getDateFormats());
+ $this->assertContains('Y-m-d', $dateParser->getDateFormats(true));
+ }
+
+ public function testGetDateTimeFormats()
+ {
+ $dateParser = new DateParser($this->container);
+ $this->assertCount(8, $dateParser->getDateTimeFormats());
+ $this->assertCount(12, $dateParser->getDateTimeFormats(true));
+ $this->assertContains('d/m/Y H:i', $dateParser->getDateTimeFormats());
+ $this->assertNotContains('Y-m-d H:i', $dateParser->getDateTimeFormats());
+ $this->assertContains('Y-m-d g:i a', $dateParser->getDateTimeFormats(true));
+ }
+
+ public function testGetAllDateFormats()
+ {
+ $dateParser = new DateParser($this->container);
+ $this->assertCount(12, $dateParser->getAllDateFormats());
+ $this->assertCount(18, $dateParser->getAllDateFormats(true));
+ $this->assertContains('d/m/Y', $dateParser->getAllDateFormats());
+ $this->assertContains('d/m/Y H:i', $dateParser->getAllDateFormats());
+ $this->assertNotContains('Y-m-d H:i', $dateParser->getAllDateFormats());
+ $this->assertContains('Y-m-d g:i a', $dateParser->getAllDateFormats(true));
+ $this->assertContains('Y-m-d', $dateParser->getAllDateFormats(true));
+ }
+
+ public function testGetAllAvailableFormats()
+ {
+ $dateParser = new DateParser($this->container);
+
+ $formats = $dateParser->getAvailableFormats($dateParser->getDateFormats());
+ $this->assertArrayHasKey('d/m/Y', $formats);
+ $this->assertContains(date('d/m/Y'), $formats);
+
+ $formats = $dateParser->getAvailableFormats($dateParser->getDateTimeFormats());
+ $this->assertArrayHasKey('d/m/Y H:i', $formats);
+ $this->assertContains(date('d/m/Y H:i'), $formats);
+
+ $formats = $dateParser->getAvailableFormats($dateParser->getAllDateFormats());
+ $this->assertArrayHasKey('d/m/Y', $formats);
+ $this->assertContains(date('d/m/Y'), $formats);
+ $this->assertArrayHasKey('d/m/Y H:i', $formats);
+ $this->assertContains(date('d/m/Y H:i'), $formats);
+ }
+
+ public function testGetTimestamp()
+ {
+ $dateParser = new DateParser($this->container);
+
+ $this->assertEquals(1393995600, $dateParser->getTimestamp(1393995600));
+ $this->assertEquals('2014-03-05', date('Y-m-d', $dateParser->getTimestamp('2014-03-05')));
+ $this->assertEquals('2014-03-05', date('Y-m-d', $dateParser->getTimestamp('2014_03_05')));
+ $this->assertEquals('2014-03-05', date('Y-m-d', $dateParser->getTimestamp('03/05/2014')));
+ $this->assertEquals('2014-03-25 17:18', date('Y-m-d H:i', $dateParser->getTimestamp('03/25/2014 5:18 pm')));
+ $this->assertEquals('2014-03-25 05:18', date('Y-m-d H:i', $dateParser->getTimestamp('03/25/2014 5:18 am')));
+ $this->assertEquals('2014-03-25 17:18', date('Y-m-d H:i', $dateParser->getTimestamp('03/25/2014 5:18pm')));
+ $this->assertEquals('2014-03-25 23:14', date('Y-m-d H:i', $dateParser->getTimestamp('03/25/2014 23:14')));
+ $this->assertEquals('2014-03-29 23:14', date('Y-m-d H:i', $dateParser->getTimestamp('2014_03_29 23:14')));
+ $this->assertEquals('2014-03-29 23:14', date('Y-m-d H:i', $dateParser->getTimestamp('2014-03-29 23:14')));
+ }
+
public function testDateRange()
{
- $d = new DateParser($this->container);
+ $dateParser = new DateParser($this->container);
- $this->assertTrue($d->withinDateRange(new DateTime('2015-03-14 15:30:00'), new DateTime('2015-03-14 15:00:00'), new DateTime('2015-03-14 16:00:00')));
- $this->assertFalse($d->withinDateRange(new DateTime('2015-03-14 15:30:00'), new DateTime('2015-03-14 16:00:00'), new DateTime('2015-03-14 17:00:00')));
+ $this->assertTrue($dateParser->withinDateRange(new DateTime('2015-03-14 15:30:00'), new DateTime('2015-03-14 15:00:00'), new DateTime('2015-03-14 16:00:00')));
+ $this->assertFalse($dateParser->withinDateRange(new DateTime('2015-03-14 15:30:00'), new DateTime('2015-03-14 16:00:00'), new DateTime('2015-03-14 17:00:00')));
+ }
+
+ public function testGetHours()
+ {
+ $dateParser = new DateParser($this->container);
+
+ $this->assertEquals(1, $dateParser->getHours(new DateTime('2015-03-14 15:00:00'), new DateTime('2015-03-14 16:00:00')));
+ $this->assertEquals(2.5, $dateParser->getHours(new DateTime('2015-03-14 15:00:00'), new DateTime('2015-03-14 17:30:00')));
+ $this->assertEquals(2.75, $dateParser->getHours(new DateTime('2015-03-14 15:00:00'), new DateTime('2015-03-14 17:45:00')));
+ $this->assertEquals(3, $dateParser->getHours(new DateTime('2015-03-14 14:57:00'), new DateTime('2015-03-14 17:58:00')));
+ $this->assertEquals(3, $dateParser->getHours(new DateTime('2015-03-14 14:57:00'), new DateTime('2015-03-14 11:58:00')));
}
public function testRoundSeconds()
{
- $d = new DateParser($this->container);
- $this->assertEquals('16:30', date('H:i', $d->getRoundedSeconds(strtotime('16:28'))));
- $this->assertEquals('16:00', date('H:i', $d->getRoundedSeconds(strtotime('16:02'))));
- $this->assertEquals('16:15', date('H:i', $d->getRoundedSeconds(strtotime('16:14'))));
- $this->assertEquals('17:00', date('H:i', $d->getRoundedSeconds(strtotime('16:58'))));
+ $dateParser = new DateParser($this->container);
+ $this->assertEquals('16:30', date('H:i', $dateParser->getRoundedSeconds(strtotime('16:28'))));
+ $this->assertEquals('16:00', date('H:i', $dateParser->getRoundedSeconds(strtotime('16:02'))));
+ $this->assertEquals('16:15', date('H:i', $dateParser->getRoundedSeconds(strtotime('16:14'))));
+ $this->assertEquals('17:00', date('H:i', $dateParser->getRoundedSeconds(strtotime('16:58'))));
}
- public function testGetHours()
+ public function testGetIsoDate()
{
- $d = new DateParser($this->container);
+ $dateParser = new DateParser($this->container);
+
+ $this->assertEquals('2016-02-06', $dateParser->getIsoDate(1454786217));
+ $this->assertEquals('2014-03-05', $dateParser->getIsoDate('2014-03-05'));
+ $this->assertEquals('2014-03-05', $dateParser->getIsoDate('2014_03_05'));
+ $this->assertEquals('2014-03-05', $dateParser->getIsoDate('03/05/2014'));
+ $this->assertEquals('2014-03-25', $dateParser->getIsoDate('03/25/2014 5:18 pm'));
+ $this->assertEquals('2014-03-25', $dateParser->getIsoDate('03/25/2014 5:18 am'));
+ $this->assertEquals('2014-03-25', $dateParser->getIsoDate('03/25/2014 5:18pm'));
+ $this->assertEquals('2014-03-25', $dateParser->getIsoDate('03/25/2014 23:14'));
+ $this->assertEquals('2014-03-29', $dateParser->getIsoDate('2014_03_29 23:14'));
+ $this->assertEquals('2014-03-29', $dateParser->getIsoDate('2014-03-29 23:14'));
+ }
- $this->assertEquals(1, $d->getHours(new DateTime('2015-03-14 15:00:00'), new DateTime('2015-03-14 16:00:00')));
- $this->assertEquals(2.5, $d->getHours(new DateTime('2015-03-14 15:00:00'), new DateTime('2015-03-14 17:30:00')));
- $this->assertEquals(2.75, $d->getHours(new DateTime('2015-03-14 15:00:00'), new DateTime('2015-03-14 17:45:00')));
- $this->assertEquals(3, $d->getHours(new DateTime('2015-03-14 14:57:00'), new DateTime('2015-03-14 17:58:00')));
- $this->assertEquals(3, $d->getHours(new DateTime('2015-03-14 14:57:00'), new DateTime('2015-03-14 11:58:00')));
+ public function testGetTimestampFromIsoFormat()
+ {
+ $dateParser = new DateParser($this->container);
+ $this->assertEquals('2014-03-05 00:00', date('Y-m-d H:i', $dateParser->getTimestampFromIsoFormat('2014-03-05')));
+ $this->assertEquals(date('Y-m-d 00:00', strtotime('+2 days')), date('Y-m-d H:i', $dateParser->getTimestampFromIsoFormat(strtotime('+2 days'))));
}
- public function testValidDate()
+ public function testRemoveTimeFromTimestamp()
{
- $d = new DateParser($this->container);
-
- $this->assertEquals('2014-03-05', date('Y-m-d', $d->getValidDate('2014-03-05', 'Y-m-d')));
- $this->assertEquals('2014-03-05', date('Y-m-d', $d->getValidDate('2014_03_05', 'Y_m_d')));
- $this->assertEquals('2014-03-05', date('Y-m-d', $d->getValidDate('05/03/2014', 'd/m/Y')));
- $this->assertEquals('2014-03-05', date('Y-m-d', $d->getValidDate('03/05/2014', 'm/d/Y')));
- $this->assertEquals('2014-03-05', date('Y-m-d', $d->getValidDate('3/5/2014', 'm/d/Y')));
- $this->assertEquals('2014-03-05', date('Y-m-d', $d->getValidDate('5/3/2014', 'd/m/Y')));
- $this->assertEquals('2014-03-05', date('Y-m-d', $d->getValidDate('5/3/14', 'd/m/y')));
- $this->assertEquals(0, $d->getValidDate('5/3/14', 'd/m/Y'));
- $this->assertEquals(0, $d->getValidDate('5-3-2014', 'd/m/Y'));
+ $dateParser = new DateParser($this->container);
+ $this->assertEquals('2016-02-06 00:00', date('Y-m-d H:i', $dateParser->removeTimeFromTimestamp(1454786217)));
}
- public function testGetTimestamp()
+ public function testFormat()
{
- $d = new DateParser($this->container);
-
- $this->assertEquals('2014-03-05', date('Y-m-d', $d->getTimestamp('2014-03-05')));
- $this->assertEquals('2014-03-05', date('Y-m-d', $d->getTimestamp('2014_03_05')));
- $this->assertEquals('2014-03-05', date('Y-m-d', $d->getTimestamp('03/05/2014')));
- $this->assertEquals('2014-03-25 17:18', date('Y-m-d H:i', $d->getTimestamp('03/25/2014 5:18 pm')));
- $this->assertEquals('2014-03-25 05:18', date('Y-m-d H:i', $d->getTimestamp('03/25/2014 5:18 am')));
- $this->assertEquals('2014-03-25 05:18', date('Y-m-d H:i', $d->getTimestamp('03/25/2014 5:18am')));
- $this->assertEquals('2014-03-25 23:14', date('Y-m-d H:i', $d->getTimestamp('03/25/2014 23:14')));
- $this->assertEquals('2014-03-29 23:14', date('Y-m-d H:i', $d->getTimestamp('2014_03_29 23:14')));
- $this->assertEquals('2014-03-29 23:14', date('Y-m-d H:i', $d->getTimestamp('2014-03-29 23:14')));
+ $dateParser = new DateParser($this->container);
+ $values['date'] = '1454787006';
+
+ $this->assertEquals(array('date' => '06/02/2016'), $dateParser->format($values, array('date'), 'd/m/Y'));
+ $this->assertEquals(array('date' => '02/06/2016 7:30 pm'), $dateParser->format($values, array('date'), 'm/d/Y g:i a'));
}
public function testConvert()
{
- $d = new DateParser($this->container);
-
+ $dateParser = new DateParser($this->container);
$values = array(
'date_due' => '2015-01-25',
- 'date_started' => '2015_01_25',
+ 'date_started' => '2015-01-25 17:25',
);
- $d->convert($values, array('date_due', 'date_started'));
+ $this->assertEquals(
+ array('date_due' => 1422144000, 'date_started' => 1422144000),
+ $dateParser->convert($values, array('date_due', 'date_started'))
+ );
- $this->assertEquals(mktime(0, 0, 0, 1, 25, 2015), $values['date_due']);
- $this->assertEquals('2015-01-25', date('Y-m-d', $values['date_due']));
+ $values = array(
+ 'date_started' => '2015-01-25 17:25',
+ );
- $this->assertEquals(mktime(0, 0, 0, 1, 25, 2015), $values['date_started']);
- $this->assertEquals('2015-01-25', date('Y-m-d', $values['date_started']));
+ $this->assertEquals(
+ array('date_started' => 1422206700),
+ $dateParser->convert($values, array('date_due', 'date_started'), true)
+ );
}
}
diff --git a/tests/units/Helper/DatetimeHelperTest.php b/tests/units/Helper/DatetimeHelperTest.php
index 8e9c461b..f27a2eb9 100644
--- a/tests/units/Helper/DatetimeHelperTest.php
+++ b/tests/units/Helper/DatetimeHelperTest.php
@@ -6,23 +6,45 @@ use Kanboard\Helper\Dt;
class DatetimeHelperTest extends Base
{
+ public function testGetTime()
+ {
+ $helper = new Dt($this->container);
+ $this->assertEquals('17:25', $helper->time(1422206700));
+ }
+
+ public function testGetDate()
+ {
+ $helper = new Dt($this->container);
+ $this->assertEquals('01/25/2015', $helper->date(1422206700));
+ $this->assertEquals('01/25/2015', $helper->date('2015-01-25'));
+ $this->assertEquals('', $helper->date('0'));
+ $this->assertEquals('', $helper->date(0));
+ $this->assertEquals('', $helper->date(''));
+ }
+
+ public function testGetDatetime()
+ {
+ $helper = new Dt($this->container);
+ $this->assertEquals('01/25/2015 17:25', $helper->datetime(1422206700));
+ }
+
public function testAge()
{
- $h = new Dt($this->container);
-
- $this->assertEquals('<15m', $h->age(0, 30));
- $this->assertEquals('<30m', $h->age(0, 1000));
- $this->assertEquals('<1h', $h->age(0, 3000));
- $this->assertEquals('~2h', $h->age(0, 2*3600));
- $this->assertEquals('1d', $h->age(0, 30*3600));
- $this->assertEquals('2d', $h->age(0, 65*3600));
+ $helper = new Dt($this->container);
+
+ $this->assertEquals('<15m', $helper->age(0, 30));
+ $this->assertEquals('<30m', $helper->age(0, 1000));
+ $this->assertEquals('<1h', $helper->age(0, 3000));
+ $this->assertEquals('~2h', $helper->age(0, 2*3600));
+ $this->assertEquals('1d', $helper->age(0, 30*3600));
+ $this->assertEquals('2d', $helper->age(0, 65*3600));
}
public function testGetDayHours()
{
- $h = new Dt($this->container);
+ $helper = new Dt($this->container);
- $slots = $h->getDayHours();
+ $slots = $helper->getDayHours();
$this->assertNotEmpty($slots);
$this->assertCount(48, $slots);
@@ -36,9 +58,9 @@ class DatetimeHelperTest extends Base
public function testGetWeekDays()
{
- $h = new Dt($this->container);
+ $helper = new Dt($this->container);
- $slots = $h->getWeekDays();
+ $slots = $helper->getWeekDays();
$this->assertNotEmpty($slots);
$this->assertCount(7, $slots);
@@ -48,9 +70,9 @@ class DatetimeHelperTest extends Base
public function testGetWeekDay()
{
- $h = new Dt($this->container);
+ $helper = new Dt($this->container);
- $this->assertEquals('Monday', $h->getWeekDay(1));
- $this->assertEquals('Sunday', $h->getWeekDay(7));
+ $this->assertEquals('Monday', $helper->getWeekDay(1));
+ $this->assertEquals('Sunday', $helper->getWeekDay(7));
}
}
diff --git a/tests/units/Model/TaskCreationTest.php b/tests/units/Model/TaskCreationTest.php
index 19b3b0d1..781a7147 100644
--- a/tests/units/Model/TaskCreationTest.php
+++ b/tests/units/Model/TaskCreationTest.php
@@ -295,7 +295,7 @@ class TaskCreationTest extends Base
$task = $tf->getById(2);
$this->assertNotEmpty($task);
$this->assertEquals(2, $task['id']);
- $this->assertEquals($timestamp, $task['date_due']);
+ $this->assertEquals(date('Y-m-d 00:00', $timestamp), date('Y-m-d 00:00', $task['date_due']));
$task = $tf->getById(3);
$this->assertEquals(3, $task['id']);
@@ -422,6 +422,6 @@ class TaskCreationTest extends Base
$task = $tf->getById(1);
$this->assertNotEmpty($task);
- $this->assertEquals('2050-01-10 12:30', date('Y-m-d H:i', $task['date_due']));
+ $this->assertEquals('2050-01-10 00:00', date('Y-m-d H:i', $task['date_due']));
}
}
diff --git a/tests/units/Model/TaskDuplicationTest.php b/tests/units/Model/TaskDuplicationTest.php
index 798b3835..8649c6b0 100644
--- a/tests/units/Model/TaskDuplicationTest.php
+++ b/tests/units/Model/TaskDuplicationTest.php
@@ -2,6 +2,7 @@
require_once __DIR__.'/../Base.php';
+use Kanboard\Core\DateParser;
use Kanboard\Model\Task;
use Kanboard\Model\TaskCreation;
use Kanboard\Model\TaskDuplication;
@@ -665,6 +666,7 @@ class TaskDuplicationTest extends Base
$tf = new TaskFinder($this->container);
$p = new Project($this->container);
$c = new Category($this->container);
+ $dp = new DateParser($this->container);
$this->assertEquals(1, $p->create(array('name' => 'test1')));
@@ -685,7 +687,7 @@ class TaskDuplicationTest extends Base
$this->assertNotEmpty($task);
$this->assertEquals(Task::RECURRING_STATUS_PROCESSED, $task['recurrence_status']);
$this->assertEquals(2, $task['recurrence_child']);
- $this->assertEquals(1436561776, $task['date_due'], '', 2);
+ $this->assertEquals(1436486400, $task['date_due'], '', 2);
$task = $tf->getById(2);
$this->assertNotEmpty($task);
@@ -695,6 +697,6 @@ class TaskDuplicationTest extends Base
$this->assertEquals(Task::RECURRING_BASEDATE_TRIGGERDATE, $task['recurrence_basedate']);
$this->assertEquals(1, $task['recurrence_parent']);
$this->assertEquals(2, $task['recurrence_factor']);
- $this->assertEquals(strtotime('+2 days'), $task['date_due'], '', 2);
+ $this->assertEquals($dp->removeTimeFromTimestamp(strtotime('+2 days')), $task['date_due'], '', 2);
}
}
--
cgit v1.2.3
From 8e25c875f26b05e3138fb4d09d9f720456c09f76 Mon Sep 17 00:00:00 2001
From: Frederic Guillot
Date: Sun, 14 Feb 2016 15:25:16 -0500
Subject: Add ProjecFile and TaskFile models
---
app/Api/File.php | 55 ++-
app/Controller/BoardTooltip.php | 2 +-
app/Controller/File.php | 26 +-
app/Controller/Task.php | 4 +-
app/Core/Base.php | 3 +-
app/Model/File.php | 282 ++++++-------
app/Model/Notification.php | 4 +-
app/Model/ProjectFile.php | 40 ++
app/Model/Task.php | 2 +-
app/Model/TaskFile.php | 54 +++
app/Model/TaskFinder.php | 2 +-
app/Notification/Mail.php | 4 +-
app/Schema/Mysql.php | 22 +-
app/Schema/Postgres.php | 23 +-
app/Schema/Sqlite.php | 21 +-
app/ServiceProvider/ClassProvider.php | 3 +-
app/Subscriber/NotificationSubscriber.php | 4 +-
app/Template/event/file_create.php | 11 -
app/Template/event/task_file_create.php | 11 +
app/Template/notification/file_create.php | 5 -
app/Template/notification/task_file_create.php | 5 +
doc/api-file-procedures.markdown | 24 +-
.../AverageTimeSpentColumnAnalyticTest.php | 96 ++---
tests/units/Base.php | 6 +
tests/units/Model/FileTest.php | 263 ------------
tests/units/Model/NotificationTest.php | 4 +-
tests/units/Model/ProjectActivityTest.php | 1 -
tests/units/Model/ProjectFileTest.php | 311 ++++++++++++++
tests/units/Model/TaskFileTest.php | 458 +++++++++++++++++++++
tests/units/Model/UserNotificationTest.php | 1 -
tests/units/Model/UserUnreadNotificationTest.php | 1 -
tests/units/Notification/MailTest.php | 4 +-
32 files changed, 1206 insertions(+), 546 deletions(-)
create mode 100644 app/Model/ProjectFile.php
create mode 100644 app/Model/TaskFile.php
delete mode 100644 app/Template/event/file_create.php
create mode 100644 app/Template/event/task_file_create.php
delete mode 100644 app/Template/notification/file_create.php
create mode 100644 app/Template/notification/task_file_create.php
delete mode 100644 tests/units/Model/FileTest.php
create mode 100644 tests/units/Model/ProjectFileTest.php
create mode 100644 tests/units/Model/TaskFileTest.php
(limited to 'app/Model/File.php')
diff --git a/app/Api/File.php b/app/Api/File.php
index 269803e1..e4204e6d 100644
--- a/app/Api/File.php
+++ b/app/Api/File.php
@@ -2,6 +2,7 @@
namespace Kanboard\Api;
+use Kanboard\Core\Base;
use Kanboard\Core\ObjectStorage\ObjectStorageException;
/**
@@ -10,22 +11,22 @@ use Kanboard\Core\ObjectStorage\ObjectStorageException;
* @package api
* @author Frederic Guillot
*/
-class File extends \Kanboard\Core\Base
+class File extends Base
{
- public function getFile($file_id)
+ public function getTaskFile($file_id)
{
- return $this->file->getById($file_id);
+ return $this->taskFile->getById($file_id);
}
- public function getAllFiles($task_id)
+ public function getAllTaskFiles($task_id)
{
- return $this->file->getAll($task_id);
+ return $this->taskFile->getAll($task_id);
}
- public function downloadFile($file_id)
+ public function downloadTaskFile($file_id)
{
try {
- $file = $this->file->getById($file_id);
+ $file = $this->taskFile->getById($file_id);
if (! empty($file)) {
return base64_encode($this->objectStorage->get($file['path']));
@@ -36,23 +37,55 @@ class File extends \Kanboard\Core\Base
}
}
- public function createFile($project_id, $task_id, $filename, $blob)
+ public function createTaskFile($project_id, $task_id, $filename, $blob)
{
try {
- return $this->file->uploadContent($project_id, $task_id, $filename, $blob);
+ return $this->taskFile->uploadContent($task_id, $filename, $blob);
} catch (ObjectStorageException $e) {
$this->logger->error($e->getMessage());
return false;
}
}
+ public function removeTaskFile($file_id)
+ {
+ return $this->taskFile->remove($file_id);
+ }
+
+ public function removeAllTaskFiles($task_id)
+ {
+ return $this->taskFile->removeAll($task_id);
+ }
+
+ // Deprecated procedures
+
+ public function getFile($file_id)
+ {
+ return $this->getTaskFile($file_id);
+ }
+
+ public function getAllFiles($task_id)
+ {
+ return $this->getAllTaskFiles($task_id);
+ }
+
+ public function downloadFile($file_id)
+ {
+ return $this->downloadTaskFile($file_id);
+ }
+
+ public function createFile($project_id, $task_id, $filename, $blob)
+ {
+ return $this->createTaskFile($project_id, $task_id, $filename, $blob);
+ }
+
public function removeFile($file_id)
{
- return $this->file->remove($file_id);
+ return $this->removeTaskFile($file_id);
}
public function removeAllFiles($task_id)
{
- return $this->file->removeAll($task_id);
+ return $this->removeAllTaskFiles($task_id);
}
}
diff --git a/app/Controller/BoardTooltip.php b/app/Controller/BoardTooltip.php
index da07ec4e..bc07ce09 100644
--- a/app/Controller/BoardTooltip.php
+++ b/app/Controller/BoardTooltip.php
@@ -62,7 +62,7 @@ class BoardTooltip extends Base
$task = $this->getTask();
$this->response->html($this->template->render('board/tooltip_files', array(
- 'files' => $this->file->getAll($task['id']),
+ 'files' => $this->taskFile->getAll($task['id']),
'task' => $task,
)));
}
diff --git a/app/Controller/File.php b/app/Controller/File.php
index 4ac45fbd..c5517df8 100644
--- a/app/Controller/File.php
+++ b/app/Controller/File.php
@@ -21,7 +21,7 @@ class File extends Base
{
$task = $this->getTask();
- if ($this->request->isPost() && $this->file->uploadScreenshot($task['project_id'], $task['id'], $this->request->getValue('screenshot')) !== false) {
+ if ($this->request->isPost() && $this->taskFile->uploadScreenshot($task['id'], $this->request->getValue('screenshot')) !== false) {
$this->flash->success(t('Screenshot uploaded successfully.'));
return $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])), true);
}
@@ -55,7 +55,7 @@ class File extends Base
{
$task = $this->getTask();
- if (! $this->file->uploadFiles($task['project_id'], $task['id'], 'files')) {
+ if (! $this->taskFile->uploadFiles($task['id'], $this->request->getFileInfo('files'))) {
$this->flash->failure(t('Unable to upload the file.'));
}
@@ -71,7 +71,7 @@ class File extends Base
{
try {
$task = $this->getTask();
- $file = $this->file->getById($this->request->getIntegerParam('file_id'));
+ $file = $this->taskFile->getById($this->request->getIntegerParam('file_id'));
if ($file['task_id'] != $task['id']) {
$this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
@@ -92,7 +92,7 @@ class File extends Base
public function open()
{
$task = $this->getTask();
- $file = $this->file->getById($this->request->getIntegerParam('file_id'));
+ $file = $this->taskFile->getById($this->request->getIntegerParam('file_id'));
if ($file['task_id'] == $task['id']) {
$this->response->html($this->template->render('file/open', array(
@@ -111,10 +111,10 @@ class File extends Base
{
try {
$task = $this->getTask();
- $file = $this->file->getById($this->request->getIntegerParam('file_id'));
+ $file = $this->taskFile->getById($this->request->getIntegerParam('file_id'));
if ($file['task_id'] == $task['id']) {
- $this->response->contentType($this->file->getImageMimeType($file['name']));
+ $this->response->contentType($this->taskFile->getImageMimeType($file['name']));
$this->objectStorage->output($file['path']);
}
} catch (ObjectStorageException $e) {
@@ -133,18 +133,18 @@ class File extends Base
try {
$task = $this->getTask();
- $file = $this->file->getById($this->request->getIntegerParam('file_id'));
+ $file = $this->taskFile->getById($this->request->getIntegerParam('file_id'));
if ($file['task_id'] == $task['id']) {
- $this->objectStorage->output($this->file->getThumbnailPath($file['path']));
+ $this->objectStorage->output($this->taskFile->getThumbnailPath($file['path']));
}
} catch (ObjectStorageException $e) {
$this->logger->error($e->getMessage());
// Try to generate thumbnail on the fly for images uploaded before Kanboard < 1.0.19
$data = $this->objectStorage->get($file['path']);
- $this->file->generateThumbnailFromData($file['path'], $data);
- $this->objectStorage->output($this->file->getThumbnailPath($file['path']));
+ $this->taskFile->generateThumbnailFromData($file['path'], $data);
+ $this->objectStorage->output($this->taskFile->getThumbnailPath($file['path']));
}
}
@@ -157,9 +157,9 @@ class File extends Base
{
$this->checkCSRFParam();
$task = $this->getTask();
- $file = $this->file->getById($this->request->getIntegerParam('file_id'));
+ $file = $this->taskFile->getById($this->request->getIntegerParam('file_id'));
- if ($file['task_id'] == $task['id'] && $this->file->remove($file['id'])) {
+ if ($file['task_id'] == $task['id'] && $this->taskFile->remove($file['id'])) {
$this->flash->success(t('File removed successfully.'));
} else {
$this->flash->failure(t('Unable to remove this file.'));
@@ -176,7 +176,7 @@ class File extends Base
public function confirm()
{
$task = $this->getTask();
- $file = $this->file->getById($this->request->getIntegerParam('file_id'));
+ $file = $this->taskFile->getById($this->request->getIntegerParam('file_id'));
$this->response->html($this->helper->layout->task('file/remove', array(
'task' => $task,
diff --git a/app/Controller/Task.php b/app/Controller/Task.php
index 4db8f86e..98b7a041 100644
--- a/app/Controller/Task.php
+++ b/app/Controller/Task.php
@@ -66,8 +66,8 @@ class Task extends Base
$this->response->html($this->helper->layout->task('task/show', array(
'project' => $this->project->getById($task['project_id']),
- 'files' => $this->file->getAllDocuments($task['id']),
- 'images' => $this->file->getAllImages($task['id']),
+ 'files' => $this->taskFile->getAllDocuments($task['id']),
+ 'images' => $this->taskFile->getAllImages($task['id']),
'comments' => $this->comment->getAll($task['id'], $this->userSession->getCommentSorting()),
'subtasks' => $subtasks,
'links' => $this->taskLink->getAllGroupedByLabel($task['id']),
diff --git a/app/Core/Base.php b/app/Core/Base.php
index ab99fcea..31c07355 100644
--- a/app/Core/Base.php
+++ b/app/Core/Base.php
@@ -67,7 +67,8 @@ use Pimple\Container;
* @property \Kanboard\Model\Config $config
* @property \Kanboard\Model\Currency $currency
* @property \Kanboard\Model\CustomFilter $customFilter
- * @property \Kanboard\Model\File $file
+ * @property \Kanboard\Model\TaskFile $taskFile
+ * @property \Kanboard\Model\ProjectFile $projectFile
* @property \Kanboard\Model\Group $group
* @property \Kanboard\Model\GroupMember $groupMember
* @property \Kanboard\Model\LastLogin $lastLogin
diff --git a/app/Model/File.php b/app/Model/File.php
index 46fc4bb9..e17ecb2b 100644
--- a/app/Model/File.php
+++ b/app/Model/File.php
@@ -2,31 +2,44 @@
namespace Kanboard\Model;
+use Exception;
use Kanboard\Event\FileEvent;
use Kanboard\Core\Tool;
use Kanboard\Core\ObjectStorage\ObjectStorageException;
/**
- * File model
+ * Base File Model
*
* @package model
* @author Frederic Guillot
*/
-class File extends Base
+abstract class File extends Base
{
/**
- * SQL table name
- *
- * @var string
- */
- const TABLE = 'files';
-
- /**
- * Events
+ * Get PicoDb query to get all files
*
- * @var string
+ * @access protected
+ * @return \PicoDb\Table
*/
- const EVENT_CREATE = 'file.create';
+ protected function getQuery()
+ {
+ return $this->db
+ ->table(static::TABLE)
+ ->columns(
+ static::TABLE.'.id',
+ static::TABLE.'.name',
+ static::TABLE.'.path',
+ static::TABLE.'.is_image',
+ static::TABLE.'.'.static::FOREIGN_KEY,
+ static::TABLE.'.date',
+ static::TABLE.'.user_id',
+ static::TABLE.'.size',
+ User::TABLE.'.username',
+ User::TABLE.'.name as user_name'
+ )
+ ->join(User::TABLE, 'id', 'user_id')
+ ->asc(static::TABLE.'.name');
+ }
/**
* Get a file by the id
@@ -37,146 +50,120 @@ class File extends Base
*/
public function getById($file_id)
{
- return $this->db->table(self::TABLE)->eq('id', $file_id)->findOne();
+ return $this->db->table(static::TABLE)->eq('id', $file_id)->findOne();
}
/**
- * Remove a file
+ * Get all files
*
* @access public
- * @param integer $file_id File id
- * @return bool
+ * @param integer $id
+ * @return array
*/
- public function remove($file_id)
+ public function getAll($id)
{
- try {
- $file = $this->getbyId($file_id);
- $this->objectStorage->remove($file['path']);
-
- if ($file['is_image'] == 1) {
- $this->objectStorage->remove($this->getThumbnailPath($file['path']));
- }
-
- return $this->db->table(self::TABLE)->eq('id', $file['id'])->remove();
- } catch (ObjectStorageException $e) {
- $this->logger->error($e->getMessage());
- return false;
- }
+ return $this->getQuery()->eq(static::FOREIGN_KEY, $id)->findAll();
}
/**
- * Remove all files for a given task
+ * Get all images
*
* @access public
- * @param integer $task_id Task id
- * @return bool
+ * @param integer $id
+ * @return array
*/
- public function removeAll($task_id)
+ public function getAllImages($id)
{
- $file_ids = $this->db->table(self::TABLE)->eq('task_id', $task_id)->asc('id')->findAllByColumn('id');
- $results = array();
-
- foreach ($file_ids as $file_id) {
- $results[] = $this->remove($file_id);
- }
+ return $this->getQuery()->eq(static::FOREIGN_KEY, $id)->eq('is_image', 1)->findAll();
+ }
- return ! in_array(false, $results, true);
+ /**
+ * Get all files without images
+ *
+ * @access public
+ * @param integer $id
+ * @return array
+ */
+ public function getAllDocuments($id)
+ {
+ return $this->getQuery()->eq(static::FOREIGN_KEY, $id)->eq('is_image', 0)->findAll();
}
/**
* Create a file entry in the database
*
* @access public
- * @param integer $task_id Task id
+ * @param integer $id Foreign key
* @param string $name Filename
* @param string $path Path on the disk
* @param integer $size File size
* @return bool|integer
*/
- public function create($task_id, $name, $path, $size)
+ public function create($id, $name, $path, $size)
{
- $result = $this->db->table(self::TABLE)->save(array(
- 'task_id' => $task_id,
+ $values = array(
+ static::FOREIGN_KEY => $id,
'name' => substr($name, 0, 255),
'path' => $path,
'is_image' => $this->isImage($name) ? 1 : 0,
'size' => $size,
'user_id' => $this->userSession->getId() ?: 0,
'date' => time(),
- ));
+ );
- if ($result) {
- $this->container['dispatcher']->dispatch(
- self::EVENT_CREATE,
- new FileEvent(array('task_id' => $task_id, 'name' => $name))
- );
+ $result = $this->db->table(static::TABLE)->insert($values);
- return (int) $this->db->getLastId();
+ if ($result) {
+ $file_id = (int) $this->db->getLastId();
+ $event = new FileEvent($values + array('file_id' => $file_id));
+ $this->dispatcher->dispatch(static::EVENT_CREATE, $event);
+ return $file_id;
}
return false;
}
/**
- * Get PicoDb query to get all files
+ * Remove all files
*
* @access public
- * @return \PicoDb\Table
+ * @param integer $id
+ * @return bool
*/
- public function getQuery()
+ public function removeAll($id)
{
- return $this->db
- ->table(self::TABLE)
- ->columns(
- self::TABLE.'.id',
- self::TABLE.'.name',
- self::TABLE.'.path',
- self::TABLE.'.is_image',
- self::TABLE.'.task_id',
- self::TABLE.'.date',
- self::TABLE.'.user_id',
- self::TABLE.'.size',
- User::TABLE.'.username',
- User::TABLE.'.name as user_name'
- )
- ->join(User::TABLE, 'id', 'user_id')
- ->asc(self::TABLE.'.name');
- }
+ $file_ids = $this->db->table(static::TABLE)->eq(static::FOREIGN_KEY, $id)->asc('id')->findAllByColumn('id');
+ $results = array();
- /**
- * Get all files for a given task
- *
- * @access public
- * @param integer $task_id Task id
- * @return array
- */
- public function getAll($task_id)
- {
- return $this->getQuery()->eq('task_id', $task_id)->findAll();
- }
+ foreach ($file_ids as $file_id) {
+ $results[] = $this->remove($file_id);
+ }
- /**
- * Get all images for a given task
- *
- * @access public
- * @param integer $task_id Task id
- * @return array
- */
- public function getAllImages($task_id)
- {
- return $this->getQuery()->eq('task_id', $task_id)->eq('is_image', 1)->findAll();
+ return ! in_array(false, $results, true);
}
/**
- * Get all files without images for a given task
+ * Remove a file
*
* @access public
- * @param integer $task_id Task id
- * @return array
+ * @param integer $file_id File id
+ * @return bool
*/
- public function getAllDocuments($task_id)
+ public function remove($file_id)
{
- return $this->getQuery()->eq('task_id', $task_id)->eq('is_image', 0)->findAll();
+ try {
+ $file = $this->getById($file_id);
+ $this->objectStorage->remove($file['path']);
+
+ if ($file['is_image'] == 1) {
+ $this->objectStorage->remove($this->getThumbnailPath($file['path']));
+ }
+
+ return $this->db->table(static::TABLE)->eq('id', $file['id'])->remove();
+ } catch (ObjectStorageException $e) {
+ $this->logger->error($e->getMessage());
+ return false;
+ }
}
/**
@@ -226,103 +213,96 @@ class File extends Base
}
/**
- * Generate the path for a new filename
+ * Generate the path for a thumbnails
*
* @access public
- * @param integer $project_id Project id
- * @param integer $task_id Task id
- * @param string $filename Filename
+ * @param string $key Storage key
* @return string
*/
- public function generatePath($project_id, $task_id, $filename)
+ public function getThumbnailPath($key)
{
- return $project_id.DIRECTORY_SEPARATOR.$task_id.DIRECTORY_SEPARATOR.hash('sha1', $filename.time());
+ return 'thumbnails'.DIRECTORY_SEPARATOR.$key;
}
/**
- * Generate the path for a thumbnails
+ * Generate the path for a new filename
*
* @access public
- * @param string $key Storage key
+ * @param integer $id Foreign key
+ * @param string $filename Filename
* @return string
*/
- public function getThumbnailPath($key)
+ public function generatePath($id, $filename)
{
- return 'thumbnails'.DIRECTORY_SEPARATOR.$key;
+ return static::PATH_PREFIX.DIRECTORY_SEPARATOR.$id.DIRECTORY_SEPARATOR.hash('sha1', $filename.time());
}
/**
- * Handle file upload
+ * Upload multiple files
*
* @access public
- * @param integer $project_id Project id
- * @param integer $task_id Task id
- * @param string $form_name File form name
+ * @param integer $id
+ * @param array $files
* @return bool
*/
- public function uploadFiles($project_id, $task_id, $form_name)
+ public function uploadFiles($id, array $files)
{
try {
- $file = $this->request->getFileInfo($form_name);
-
- if (empty($file)) {
+ if (empty($files)) {
return false;
}
- foreach ($file['error'] as $key => $error) {
- if ($error == UPLOAD_ERR_OK && $file['size'][$key] > 0) {
- $original_filename = $file['name'][$key];
- $uploaded_filename = $file['tmp_name'][$key];
- $destination_filename = $this->generatePath($project_id, $task_id, $original_filename);
-
- if ($this->isImage($original_filename)) {
- $this->generateThumbnailFromFile($uploaded_filename, $destination_filename);
- }
-
- $this->objectStorage->moveUploadedFile($uploaded_filename, $destination_filename);
-
- $this->create(
- $task_id,
- $original_filename,
- $destination_filename,
- $file['size'][$key]
- );
- }
+ foreach (array_keys($files['error']) as $key) {
+ $file = array(
+ 'name' => $files['name'][$key],
+ 'tmp_name' => $files['tmp_name'][$key],
+ 'size' => $files['size'][$key],
+ 'error' => $files['error'][$key],
+ );
+
+ $this->uploadFile($id, $file);
}
return true;
- } catch (ObjectStorageException $e) {
+ } catch (Exception $e) {
$this->logger->error($e->getMessage());
return false;
}
}
/**
- * Handle screenshot upload
+ * Upload a file
*
* @access public
- * @param integer $project_id Project id
- * @param integer $task_id Task id
- * @param string $blob Base64 encoded image
- * @return bool|integer
+ * @param integer $id
+ * @param array $file
*/
- public function uploadScreenshot($project_id, $task_id, $blob)
+ public function uploadFile($id, array $file)
{
- $original_filename = e('Screenshot taken %s', $this->helper->dt->datetime(time())).'.png';
- return $this->uploadContent($project_id, $task_id, $original_filename, $blob);
+ if ($file['error'] == UPLOAD_ERR_OK && $file['size'] > 0) {
+ $destination_filename = $this->generatePath($id, $file['name']);
+
+ if ($this->isImage($file['name'])) {
+ $this->generateThumbnailFromFile($file['tmp_name'], $destination_filename);
+ }
+
+ $this->objectStorage->moveUploadedFile($file['tmp_name'], $destination_filename);
+ $this->create($id, $file['name'], $destination_filename, $file['size']);
+ } else {
+ throw new Exception('File not uploaded: '.var_export($file['error'], true));
+ }
}
/**
* Handle file upload (base64 encoded content)
*
* @access public
- * @param integer $project_id Project id
- * @param integer $task_id Task id
- * @param string $original_filename Filename
- * @param string $blob Base64 encoded file
+ * @param integer $id
+ * @param string $original_filename
+ * @param string $blob
* @return bool|integer
*/
- public function uploadContent($project_id, $task_id, $original_filename, $blob)
+ public function uploadContent($id, $original_filename, $blob)
{
try {
$data = base64_decode($blob);
@@ -331,7 +311,7 @@ class File extends Base
return false;
}
- $destination_filename = $this->generatePath($project_id, $task_id, $original_filename);
+ $destination_filename = $this->generatePath($id, $original_filename);
$this->objectStorage->put($destination_filename, $data);
if ($this->isImage($original_filename)) {
@@ -339,7 +319,7 @@ class File extends Base
}
return $this->create(
- $task_id,
+ $id,
$original_filename,
$destination_filename,
strlen($data)
diff --git a/app/Model/Notification.php b/app/Model/Notification.php
index 87c1a796..c252aa31 100644
--- a/app/Model/Notification.php
+++ b/app/Model/Notification.php
@@ -72,7 +72,7 @@ class Notification extends Base
return e('%s updated a comment on the task #%d', $event_author, $event_data['task']['id']);
case Comment::EVENT_CREATE:
return e('%s commented on the task #%d', $event_author, $event_data['task']['id']);
- case File::EVENT_CREATE:
+ case TaskFile::EVENT_CREATE:
return e('%s attached a file to the task #%d', $event_author, $event_data['task']['id']);
case Task::EVENT_USER_MENTION:
return e('%s mentioned you in the task #%d', $event_author, $event_data['task']['id']);
@@ -94,7 +94,7 @@ class Notification extends Base
public function getTitleWithoutAuthor($event_name, array $event_data)
{
switch ($event_name) {
- case File::EVENT_CREATE:
+ case TaskFile::EVENT_CREATE:
return e('New attachment on task #%d: %s', $event_data['file']['task_id'], $event_data['file']['name']);
case Comment::EVENT_CREATE:
return e('New comment on task #%d', $event_data['comment']['task_id']);
diff --git a/app/Model/ProjectFile.php b/app/Model/ProjectFile.php
new file mode 100644
index 00000000..aa9bf15b
--- /dev/null
+++ b/app/Model/ProjectFile.php
@@ -0,0 +1,40 @@
+file->removeAll($task_id);
+ $this->taskFile->removeAll($task_id);
return $this->db->table(self::TABLE)->eq('id', $task_id)->remove();
}
diff --git a/app/Model/TaskFile.php b/app/Model/TaskFile.php
new file mode 100644
index 00000000..45a3b97f
--- /dev/null
+++ b/app/Model/TaskFile.php
@@ -0,0 +1,54 @@
+helper->dt->datetime(time())).'.png';
+ return $this->uploadContent($task_id, $original_filename, $blob);
+ }
+}
diff --git a/app/Model/TaskFinder.php b/app/Model/TaskFinder.php
index 4d673097..95ddc12f 100644
--- a/app/Model/TaskFinder.php
+++ b/app/Model/TaskFinder.php
@@ -89,7 +89,7 @@ class TaskFinder extends Base
->table(Task::TABLE)
->columns(
'(SELECT COUNT(*) FROM '.Comment::TABLE.' WHERE task_id=tasks.id) AS nb_comments',
- '(SELECT COUNT(*) FROM '.File::TABLE.' WHERE task_id=tasks.id) AS nb_files',
+ '(SELECT COUNT(*) FROM '.TaskFile::TABLE.' WHERE task_id=tasks.id) AS nb_files',
'(SELECT COUNT(*) FROM '.Subtask::TABLE.' WHERE '.Subtask::TABLE.'.task_id=tasks.id) AS nb_subtasks',
'(SELECT COUNT(*) FROM '.Subtask::TABLE.' WHERE '.Subtask::TABLE.'.task_id=tasks.id AND status=2) AS nb_completed_subtasks',
'(SELECT COUNT(*) FROM '.TaskLink::TABLE.' WHERE '.TaskLink::TABLE.'.task_id = tasks.id) AS nb_links',
diff --git a/app/Notification/Mail.php b/app/Notification/Mail.php
index d05dbdf2..c924fb50 100644
--- a/app/Notification/Mail.php
+++ b/app/Notification/Mail.php
@@ -4,7 +4,7 @@ namespace Kanboard\Notification;
use Kanboard\Core\Base;
use Kanboard\Model\Task;
-use Kanboard\Model\File;
+use Kanboard\Model\TaskFile;
use Kanboard\Model\Comment;
use Kanboard\Model\Subtask;
@@ -82,7 +82,7 @@ class Mail extends Base implements NotificationInterface
public function getMailSubject($event_name, array $event_data)
{
switch ($event_name) {
- case File::EVENT_CREATE:
+ case TaskFile::EVENT_CREATE:
$subject = $this->getStandardMailSubject(e('New attachment'), $event_data);
break;
case Comment::EVENT_CREATE:
diff --git a/app/Schema/Mysql.php b/app/Schema/Mysql.php
index 1cebbd22..c85dde6f 100644
--- a/app/Schema/Mysql.php
+++ b/app/Schema/Mysql.php
@@ -6,7 +6,27 @@ use PDO;
use Kanboard\Core\Security\Token;
use Kanboard\Core\Security\Role;
-const VERSION = 105;
+const VERSION = 106;
+
+function version_106(PDO $pdo)
+{
+ $pdo->exec('RENAME TABLE files TO task_has_files');
+
+ $pdo->exec("
+ CREATE TABLE project_has_files (
+ `id` INT NOT NULL AUTO_INCREMENT,
+ `project_id` INT NOT NULL,
+ `name` VARCHAR(255) NOT NULL,
+ `path` VARCHAR(255) NOT NULL,
+ `is_image` TINYINT(1) DEFAULT 0,
+ `size` INT DEFAULT 0 NOT NULL,
+ `user_id` INT DEFAULT 0 NOT NULL,
+ `date` INT DEFAULT 0 NOT NULL,
+ FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE,
+ PRIMARY KEY(id)
+ ) ENGINE=InnoDB CHARSET=utf8"
+ );
+}
function version_105(PDO $pdo)
{
diff --git a/app/Schema/Postgres.php b/app/Schema/Postgres.php
index b0b89a7c..dc8de510 100644
--- a/app/Schema/Postgres.php
+++ b/app/Schema/Postgres.php
@@ -6,7 +6,26 @@ use PDO;
use Kanboard\Core\Security\Token;
use Kanboard\Core\Security\Role;
-const VERSION = 85;
+const VERSION = 86;
+
+function version_86(PDO $pdo)
+{
+ $pdo->exec('ALTER TABLE files RENAME TO task_has_files');
+
+ $pdo->exec("
+ CREATE TABLE project_has_files (
+ id SERIAL PRIMARY KEY,
+ project_id INTEGER NOT NULL,
+ name VARCHAR(255) NOT NULL,
+ path VARCHAR(255) NOT NULL,
+ is_image BOOLEAN DEFAULT '0',
+ size INTEGER DEFAULT 0 NOT NULL,
+ user_id INTEGER DEFAULT 0 NOT NULL,
+ date INTEGER DEFAULT 0 NOT NULL,
+ FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE
+ )"
+ );
+}
function version_85(PDO $pdo)
{
@@ -17,7 +36,7 @@ function version_84(PDO $pdo)
{
$pdo->exec("
CREATE TABLE task_has_external_links (
- id SERIAL,
+ id SERIAL PRIMARY KEY,
link_type VARCHAR(100) NOT NULL,
dependency VARCHAR(100) NOT NULL,
title VARCHAR(255) NOT NULL,
diff --git a/app/Schema/Sqlite.php b/app/Schema/Sqlite.php
index aa10e58b..e88f621f 100644
--- a/app/Schema/Sqlite.php
+++ b/app/Schema/Sqlite.php
@@ -6,7 +6,26 @@ use Kanboard\Core\Security\Token;
use Kanboard\Core\Security\Role;
use PDO;
-const VERSION = 97;
+const VERSION = 98;
+
+function version_98(PDO $pdo)
+{
+ $pdo->exec('ALTER TABLE files RENAME TO task_has_files');
+
+ $pdo->exec("
+ CREATE TABLE project_has_files (
+ id INTEGER PRIMARY KEY,
+ project_id INTEGER NOT NULL,
+ name TEXT COLLATE NOCASE NOT NULL,
+ path TEXT NOT NULL,
+ is_image INTEGER DEFAULT 0,
+ size INTEGER DEFAULT 0 NOT NULL,
+ user_id INTEGER DEFAULT 0 NOT NULL,
+ date INTEGER DEFAULT 0 NOT NULL,
+ FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE
+ )"
+ );
+}
function version_97(PDO $pdo)
{
diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php
index 61a4c512..a4fa1ff2 100644
--- a/app/ServiceProvider/ClassProvider.php
+++ b/app/ServiceProvider/ClassProvider.php
@@ -31,7 +31,6 @@ class ClassProvider implements ServiceProviderInterface
'Config',
'Currency',
'CustomFilter',
- 'File',
'Group',
'GroupMember',
'LastLogin',
@@ -40,6 +39,7 @@ class ClassProvider implements ServiceProviderInterface
'OverdueNotification',
'PasswordReset',
'Project',
+ 'ProjectFile',
'ProjectActivity',
'ProjectDuplication',
'ProjectDailyColumnStats',
@@ -63,6 +63,7 @@ class ClassProvider implements ServiceProviderInterface
'TaskExport',
'TaskExternalLink',
'TaskFinder',
+ 'TaskFile',
'TaskFilter',
'TaskLink',
'TaskModification',
diff --git a/app/Subscriber/NotificationSubscriber.php b/app/Subscriber/NotificationSubscriber.php
index 07660050..651b8a96 100644
--- a/app/Subscriber/NotificationSubscriber.php
+++ b/app/Subscriber/NotificationSubscriber.php
@@ -6,7 +6,7 @@ use Kanboard\Event\GenericEvent;
use Kanboard\Model\Task;
use Kanboard\Model\Comment;
use Kanboard\Model\Subtask;
-use Kanboard\Model\File;
+use Kanboard\Model\TaskFile;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class NotificationSubscriber extends BaseSubscriber implements EventSubscriberInterface
@@ -28,7 +28,7 @@ class NotificationSubscriber extends BaseSubscriber implements EventSubscriberIn
Comment::EVENT_CREATE => 'handleEvent',
Comment::EVENT_UPDATE => 'handleEvent',
Comment::EVENT_USER_MENTION => 'handleEvent',
- File::EVENT_CREATE => 'handleEvent',
+ TaskFile::EVENT_CREATE => 'handleEvent',
);
}
diff --git a/app/Template/event/file_create.php b/app/Template/event/file_create.php
deleted file mode 100644
index 1a36bc8f..00000000
--- a/app/Template/event/file_create.php
+++ /dev/null
@@ -1,11 +0,0 @@
-= $this->user->avatar($email, $author) ?>
-
-
- = e('%s attached a new file to the task %s',
- $this->e($author),
- $this->url->link(t('#%d', $task['id']), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']))
- ) ?>
-
-
- = $this->e($file['name']) ?>
-
\ No newline at end of file
diff --git a/app/Template/event/task_file_create.php b/app/Template/event/task_file_create.php
new file mode 100644
index 00000000..1a36bc8f
--- /dev/null
+++ b/app/Template/event/task_file_create.php
@@ -0,0 +1,11 @@
+= $this->user->avatar($email, $author) ?>
+
+
+ = e('%s attached a new file to the task %s',
+ $this->e($author),
+ $this->url->link(t('#%d', $task['id']), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']))
+ ) ?>
+
+
+ = $this->e($file['name']) ?>
+
\ No newline at end of file
diff --git a/app/Template/notification/file_create.php b/app/Template/notification/file_create.php
deleted file mode 100644
index 63f7d1b8..00000000
--- a/app/Template/notification/file_create.php
+++ /dev/null
@@ -1,5 +0,0 @@
-= $this->e($task['title']) ?> (#= $task['id'] ?>)
-
-= t('New attachment added "%s"', $file['name']) ?>
-
-= $this->render('notification/footer', array('task' => $task, 'application_url' => $application_url)) ?>
\ No newline at end of file
diff --git a/app/Template/notification/task_file_create.php b/app/Template/notification/task_file_create.php
new file mode 100644
index 00000000..63f7d1b8
--- /dev/null
+++ b/app/Template/notification/task_file_create.php
@@ -0,0 +1,5 @@
+= $this->e($task['title']) ?> (#= $task['id'] ?>)
+
+= t('New attachment added "%s"', $file['name']) ?>
+
+= $this->render('notification/footer', array('task' => $task, 'application_url' => $application_url)) ?>
\ No newline at end of file
diff --git a/doc/api-file-procedures.markdown b/doc/api-file-procedures.markdown
index bd05ce6b..930be733 100644
--- a/doc/api-file-procedures.markdown
+++ b/doc/api-file-procedures.markdown
@@ -1,7 +1,7 @@
API File Procedures
===================
-## createFile
+## createTaskFile
- Purpose: **Create and upload a new task attachment**
- Parameters:
@@ -18,7 +18,7 @@ Request example:
```json
{
"jsonrpc": "2.0",
- "method": "createFile",
+ "method": "createTaskFile",
"id": 94500810,
"params": [
1,
@@ -39,7 +39,7 @@ Response example:
}
```
-## getAllFiles
+## getAllTaskFiles
- Purpose: **Get all files attached to task**
- Parameters:
@@ -52,7 +52,7 @@ Request example:
```json
{
"jsonrpc": "2.0",
- "method": "getAllFiles",
+ "method": "getAllTaskFiles",
"id": 1880662820,
"params": {
"task_id": 1
@@ -83,7 +83,7 @@ Response example:
}
```
-## getFile
+## getTaskFile
- Purpose: **Get file information**
- Parameters:
@@ -96,7 +96,7 @@ Request example:
```json
{
"jsonrpc": "2.0",
- "method": "getFile",
+ "method": "getTaskFile",
"id": 318676852,
"params": [
"1"
@@ -123,7 +123,7 @@ Response example:
}
```
-## downloadFile
+## downloadTaskFile
- Purpose: **Download file contents (encoded in base64)**
- Parameters:
@@ -136,7 +136,7 @@ Request example:
```json
{
"jsonrpc": "2.0",
- "method": "downloadFile",
+ "method": "downloadTaskFile",
"id": 235943344,
"params": [
"1"
@@ -154,7 +154,7 @@ Response example:
}
```
-## removeFile
+## removeTaskFile
- Purpose: **Remove file**
- Parameters:
@@ -167,7 +167,7 @@ Request example:
```json
{
"jsonrpc": "2.0",
- "method": "removeFile",
+ "method": "removeTaskFile",
"id": 447036524,
"params": [
"1"
@@ -185,7 +185,7 @@ Response example:
}
```
-## removeAllFiles
+## removeAllTaskFiles
- Purpose: **Remove all files associated to a task**
- Parameters:
@@ -198,7 +198,7 @@ Request example:
```json
{
"jsonrpc": "2.0",
- "method": "removeAllFiles",
+ "method": "removeAllTaskFiles",
"id": 593312993,
"params": {
"task_id": 1
diff --git a/tests/units/Analytic/AverageTimeSpentColumnAnalyticTest.php b/tests/units/Analytic/AverageTimeSpentColumnAnalyticTest.php
index 8ad6d1e7..4e01bfa9 100644
--- a/tests/units/Analytic/AverageTimeSpentColumnAnalyticTest.php
+++ b/tests/units/Analytic/AverageTimeSpentColumnAnalyticTest.php
@@ -28,34 +28,26 @@ class AverageTimeSpentColumnAnalyticTest extends Base
$this->container['db']->table(Task::TABLE)->eq('id', 2)->update(array('date_completed' => $now + 1800));
$stats = $averageLeadCycleTimeAnalytic->build(1);
- $expected = array(
- 1 => array(
- 'count' => 2,
- 'time_spent' => 3600+1800,
- 'average' => (int) ((3600+1800)/2),
- 'title' => 'Backlog',
- ),
- 2 => array(
- 'count' => 0,
- 'time_spent' => 0,
- 'average' => 0,
- 'title' => 'Ready',
- ),
- 3 => array(
- 'count' => 0,
- 'time_spent' => 0,
- 'average' => 0,
- 'title' => 'Work in progress',
- ),
- 4 => array(
- 'count' => 0,
- 'time_spent' => 0,
- 'average' => 0,
- 'title' => 'Done',
- )
- );
-
- $this->assertEquals($expected, $stats);
+
+ $this->assertEquals(2, $stats[1]['count']);
+ $this->assertEquals(3600+1800, $stats[1]['time_spent'], '', 3);
+ $this->assertEquals((int) ((3600+1800)/2), $stats[1]['average'], '', 3);
+ $this->assertEquals('Backlog', $stats[1]['title']);
+
+ $this->assertEquals(0, $stats[2]['count']);
+ $this->assertEquals(0, $stats[2]['time_spent'], '', 3);
+ $this->assertEquals(0, $stats[2]['average'], '', 3);
+ $this->assertEquals('Ready', $stats[2]['title']);
+
+ $this->assertEquals(0, $stats[3]['count']);
+ $this->assertEquals(0, $stats[3]['time_spent'], '', 3);
+ $this->assertEquals(0, $stats[3]['average'], '', 3);
+ $this->assertEquals('Work in progress', $stats[3]['title']);
+
+ $this->assertEquals(0, $stats[4]['count']);
+ $this->assertEquals(0, $stats[4]['time_spent'], '', 3);
+ $this->assertEquals(0, $stats[4]['average'], '', 3);
+ $this->assertEquals('Done', $stats[4]['title']);
}
public function testAverageWithTransitions()
@@ -85,33 +77,25 @@ class AverageTimeSpentColumnAnalyticTest extends Base
}
$stats = $averageLeadCycleTimeAnalytic->build(1);
- $expected = array(
- 1 => array(
- 'count' => 2,
- 'time_spent' => 3600+1800,
- 'average' => (int) ((3600+1800)/2),
- 'title' => 'Backlog',
- ),
- 2 => array(
- 'count' => 0,
- 'time_spent' => 0,
- 'average' => 0,
- 'title' => 'Ready',
- ),
- 3 => array(
- 'count' => 2,
- 'time_spent' => 1800,
- 'average' => 900,
- 'title' => 'Work in progress',
- ),
- 4 => array(
- 'count' => 0,
- 'time_spent' => 0,
- 'average' => 0,
- 'title' => 'Done',
- )
- );
-
- $this->assertEquals($expected, $stats);
+
+ $this->assertEquals(2, $stats[1]['count']);
+ $this->assertEquals(3600+1800, $stats[1]['time_spent'], '', 3);
+ $this->assertEquals((int) ((3600+1800)/2), $stats[1]['average'], '', 3);
+ $this->assertEquals('Backlog', $stats[1]['title']);
+
+ $this->assertEquals(0, $stats[2]['count']);
+ $this->assertEquals(0, $stats[2]['time_spent'], '', 3);
+ $this->assertEquals(0, $stats[2]['average'], '', 3);
+ $this->assertEquals('Ready', $stats[2]['title']);
+
+ $this->assertEquals(2, $stats[3]['count']);
+ $this->assertEquals(1800, $stats[3]['time_spent'], '', 3);
+ $this->assertEquals(900, $stats[3]['average'], '', 3);
+ $this->assertEquals('Work in progress', $stats[3]['title']);
+
+ $this->assertEquals(0, $stats[4]['count']);
+ $this->assertEquals(0, $stats[4]['time_spent'], '', 3);
+ $this->assertEquals(0, $stats[4]['average'], '', 3);
+ $this->assertEquals('Done', $stats[4]['title']);
}
}
diff --git a/tests/units/Base.php b/tests/units/Base.php
index 22c6304f..eb9fc68b 100644
--- a/tests/units/Base.php
+++ b/tests/units/Base.php
@@ -67,6 +67,12 @@ abstract class Base extends PHPUnit_Framework_TestCase
->setMethods(array('getType', 'getSelectedTypes'))
->getMock();
+ $this->container['objectStorage'] = $this
+ ->getMockBuilder('\Kanboard\Core\ObjectStorage\FileStorage')
+ ->setConstructorArgs(array($this->container))
+ ->setMethods(array('put', 'moveFile', 'remove', 'moveUploadedFile'))
+ ->getMock();
+
$this->container['sessionStorage'] = new SessionStorage;
$this->container->register(new ActionProvider);
diff --git a/tests/units/Model/FileTest.php b/tests/units/Model/FileTest.php
deleted file mode 100644
index 29f6ee93..00000000
--- a/tests/units/Model/FileTest.php
+++ /dev/null
@@ -1,263 +0,0 @@
-container['objectStorage'] = $this
- ->getMockBuilder('\Kanboard\Core\ObjectStorage\FileStorage')
- ->setConstructorArgs(array($this->container))
- ->setMethods(array('put', 'moveFile', 'remove'))
- ->getMock();
- }
-
- public function testCreation()
- {
- $p = new Project($this->container);
- $f = new File($this->container);
- $tc = new TaskCreation($this->container);
-
- $this->assertEquals(1, $p->create(array('name' => 'test')));
- $this->assertEquals(1, $tc->create(array('project_id' => 1, 'title' => 'test')));
-
- $this->assertEquals(1, $f->create(1, 'test', '/tmp/foo', 10));
-
- $file = $f->getById(1);
- $this->assertNotEmpty($file);
- $this->assertEquals('test', $file['name']);
- $this->assertEquals('/tmp/foo', $file['path']);
- $this->assertEquals(0, $file['is_image']);
- $this->assertEquals(1, $file['task_id']);
- $this->assertEquals(time(), $file['date'], '', 2);
- $this->assertEquals(0, $file['user_id']);
- $this->assertEquals(10, $file['size']);
-
- $this->assertEquals(2, $f->create(1, 'test2.png', '/tmp/foobar', 10));
-
- $file = $f->getById(2);
- $this->assertNotEmpty($file);
- $this->assertEquals('test2.png', $file['name']);
- $this->assertEquals('/tmp/foobar', $file['path']);
- $this->assertEquals(1, $file['is_image']);
- }
-
- public function testCreationFileNameTooLong()
- {
- $p = new Project($this->container);
- $f = new File($this->container);
- $tc = new TaskCreation($this->container);
-
- $this->assertEquals(1, $p->create(array('name' => 'test')));
- $this->assertEquals(1, $tc->create(array('project_id' => 1, 'title' => 'test')));
-
- $this->assertNotFalse($f->create(1, 'test', '/tmp/foo', 10));
- $this->assertNotFalse($f->create(1, str_repeat('a', 1000), '/tmp/foo', 10));
-
- $files = $f->getAll(1);
- $this->assertNotEmpty($files);
- $this->assertCount(2, $files);
-
- $this->assertEquals(str_repeat('a', 255), $files[0]['name']);
- $this->assertEquals('test', $files[1]['name']);
- }
-
- public function testIsImage()
- {
- $f = new File($this->container);
-
- $this->assertTrue($f->isImage('test.png'));
- $this->assertTrue($f->isImage('test.jpeg'));
- $this->assertTrue($f->isImage('test.gif'));
- $this->assertTrue($f->isImage('test.jpg'));
- $this->assertTrue($f->isImage('test.JPG'));
-
- $this->assertFalse($f->isImage('test.bmp'));
- $this->assertFalse($f->isImage('test'));
- $this->assertFalse($f->isImage('test.pdf'));
- }
-
- public function testGeneratePath()
- {
- $f = new File($this->container);
-
- $this->assertStringStartsWith('12'.DIRECTORY_SEPARATOR.'34'.DIRECTORY_SEPARATOR, $f->generatePath(12, 34, 'test.png'));
- $this->assertNotEquals($f->generatePath(12, 34, 'test1.png'), $f->generatePath(12, 34, 'test2.png'));
- }
-
- public function testUploadScreenshot()
- {
- $p = new Project($this->container);
- $tc = new TaskCreation($this->container);
-
- $this->assertEquals(1, $p->create(array('name' => 'test')));
- $this->assertEquals(1, $tc->create(array('project_id' => 1, 'title' => 'test')));
-
- $data = base64_encode('image data');
-
- $f = $this
- ->getMockBuilder('\Kanboard\Model\File')
- ->setConstructorArgs(array($this->container))
- ->setMethods(array('generateThumbnailFromData'))
- ->getMock();
-
- $this->container['objectStorage']
- ->expects($this->once())
- ->method('put')
- ->with(
- $this->stringContains('1'.DIRECTORY_SEPARATOR.'1'.DIRECTORY_SEPARATOR),
- $this->equalTo(base64_decode($data))
- )
- ->will($this->returnValue(true));
-
- $f->expects($this->once())
- ->method('generateThumbnailFromData');
-
- $this->assertEquals(1, $f->uploadScreenshot(1, 1, $data));
-
- $file = $f->getById(1);
- $this->assertNotEmpty($file);
- $this->assertStringStartsWith('Screenshot taken ', $file['name']);
- $this->assertStringStartsWith('1'.DIRECTORY_SEPARATOR.'1'.DIRECTORY_SEPARATOR, $file['path']);
- $this->assertEquals(1, $file['is_image']);
- $this->assertEquals(1, $file['task_id']);
- $this->assertEquals(time(), $file['date'], '', 2);
- $this->assertEquals(0, $file['user_id']);
- $this->assertEquals(10, $file['size']);
- }
-
- public function testUploadFileContent()
- {
- $p = new Project($this->container);
- $f = new File($this->container);
- $tc = new TaskCreation($this->container);
-
- $this->assertEquals(1, $p->create(array('name' => 'test')));
- $this->assertEquals(1, $tc->create(array('project_id' => 1, 'title' => 'test')));
-
- $data = base64_encode('file data');
-
- $this->container['objectStorage']
- ->expects($this->once())
- ->method('put')
- ->with(
- $this->stringContains('1'.DIRECTORY_SEPARATOR.'1'.DIRECTORY_SEPARATOR),
- $this->equalTo(base64_decode($data))
- )
- ->will($this->returnValue(true));
-
- $this->assertEquals(1, $f->uploadContent(1, 1, 'my file.pdf', $data));
-
- $file = $f->getById(1);
- $this->assertNotEmpty($file);
- $this->assertEquals('my file.pdf', $file['name']);
- $this->assertStringStartsWith('1'.DIRECTORY_SEPARATOR.'1'.DIRECTORY_SEPARATOR, $file['path']);
- $this->assertEquals(0, $file['is_image']);
- $this->assertEquals(1, $file['task_id']);
- $this->assertEquals(time(), $file['date'], '', 2);
- $this->assertEquals(0, $file['user_id']);
- $this->assertEquals(9, $file['size']);
- }
-
- public function testGetAll()
- {
- $p = new Project($this->container);
- $f = new File($this->container);
- $tc = new TaskCreation($this->container);
-
- $this->assertEquals(1, $p->create(array('name' => 'test')));
- $this->assertEquals(1, $tc->create(array('project_id' => 1, 'title' => 'test')));
-
- $this->assertEquals(1, $f->create(1, 'B.pdf', '/tmp/foo', 10));
- $this->assertEquals(2, $f->create(1, 'A.png', '/tmp/foo', 10));
- $this->assertEquals(3, $f->create(1, 'D.doc', '/tmp/foo', 10));
- $this->assertEquals(4, $f->create(1, 'C.JPG', '/tmp/foo', 10));
-
- $files = $f->getAll(1);
- $this->assertNotEmpty($files);
- $this->assertCount(4, $files);
- $this->assertEquals('A.png', $files[0]['name']);
- $this->assertEquals('B.pdf', $files[1]['name']);
- $this->assertEquals('C.JPG', $files[2]['name']);
- $this->assertEquals('D.doc', $files[3]['name']);
-
- $files = $f->getAllImages(1);
- $this->assertNotEmpty($files);
- $this->assertCount(2, $files);
- $this->assertEquals('A.png', $files[0]['name']);
- $this->assertEquals('C.JPG', $files[1]['name']);
-
- $files = $f->getAllDocuments(1);
- $this->assertNotEmpty($files);
- $this->assertCount(2, $files);
- $this->assertEquals('B.pdf', $files[0]['name']);
- $this->assertEquals('D.doc', $files[1]['name']);
- }
-
- public function testRemove()
- {
- $p = new Project($this->container);
- $f = new File($this->container);
- $tc = new TaskCreation($this->container);
-
- $this->assertEquals(1, $p->create(array('name' => 'test')));
- $this->assertEquals(1, $tc->create(array('project_id' => 1, 'title' => 'test')));
-
- $this->assertEquals(1, $f->create(1, 'B.pdf', DIRECTORY_SEPARATOR.'tmp'.DIRECTORY_SEPARATOR.'foo1', 10));
- $this->assertEquals(2, $f->create(1, 'A.png', DIRECTORY_SEPARATOR.'tmp'.DIRECTORY_SEPARATOR.'foo2', 10));
- $this->assertEquals(3, $f->create(1, 'D.doc', DIRECTORY_SEPARATOR.'tmp'.DIRECTORY_SEPARATOR.'foo3', 10));
-
- $this->container['objectStorage']
- ->expects($this->at(0))
- ->method('remove')
- ->with(
- $this->equalTo(DIRECTORY_SEPARATOR.'tmp'.DIRECTORY_SEPARATOR.'foo2')
- )
- ->will($this->returnValue(true));
-
- $this->container['objectStorage']
- ->expects($this->at(1))
- ->method('remove')
- ->with(
- $this->equalTo('thumbnails'.DIRECTORY_SEPARATOR.DIRECTORY_SEPARATOR.'tmp'.DIRECTORY_SEPARATOR.'foo2')
- )
- ->will($this->returnValue(true));
-
- $this->container['objectStorage']
- ->expects($this->at(2))
- ->method('remove')
- ->with(
- $this->equalTo(DIRECTORY_SEPARATOR.'tmp'.DIRECTORY_SEPARATOR.'foo1')
- )
- ->will($this->returnValue(true));
-
- $this->container['objectStorage']
- ->expects($this->at(3))
- ->method('remove')
- ->with(
- $this->equalTo(DIRECTORY_SEPARATOR.'tmp'.DIRECTORY_SEPARATOR.'foo3')
- )
- ->will($this->returnValue(true));
-
- $this->assertTrue($f->remove(2));
-
- $files = $f->getAll(1);
- $this->assertNotEmpty($files);
- $this->assertCount(2, $files);
- $this->assertEquals('B.pdf', $files[0]['name']);
- $this->assertEquals('D.doc', $files[1]['name']);
-
- $this->assertTrue($f->removeAll(1));
-
- $files = $f->getAll(1);
- $this->assertEmpty($files);
- }
-}
diff --git a/tests/units/Model/NotificationTest.php b/tests/units/Model/NotificationTest.php
index 7f9977ce..03ee5867 100644
--- a/tests/units/Model/NotificationTest.php
+++ b/tests/units/Model/NotificationTest.php
@@ -7,7 +7,7 @@ use Kanboard\Model\TaskCreation;
use Kanboard\Model\Subtask;
use Kanboard\Model\Comment;
use Kanboard\Model\User;
-use Kanboard\Model\File;
+use Kanboard\Model\TaskFile;
use Kanboard\Model\Task;
use Kanboard\Model\Project;
use Kanboard\Model\Notification;
@@ -23,7 +23,7 @@ class NotificationTest extends Base
$tc = new TaskCreation($this->container);
$s = new Subtask($this->container);
$c = new Comment($this->container);
- $f = new File($this->container);
+ $f = new TaskFile($this->container);
$this->assertEquals(1, $p->create(array('name' => 'test')));
$this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1)));
diff --git a/tests/units/Model/ProjectActivityTest.php b/tests/units/Model/ProjectActivityTest.php
index 10201aa8..04d3004d 100644
--- a/tests/units/Model/ProjectActivityTest.php
+++ b/tests/units/Model/ProjectActivityTest.php
@@ -9,7 +9,6 @@ use Kanboard\Model\ProjectActivity;
use Kanboard\Model\Project;
use Kanboard\Model\Subtask;
use Kanboard\Model\Comment;
-use Kanboard\Model\File;
class ProjectActivityTest extends Base
{
diff --git a/tests/units/Model/ProjectFileTest.php b/tests/units/Model/ProjectFileTest.php
new file mode 100644
index 00000000..d9b37fbe
--- /dev/null
+++ b/tests/units/Model/ProjectFileTest.php
@@ -0,0 +1,311 @@
+container);
+ $fileModel = new ProjectFile($this->container);
+
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test')));
+ $this->assertEquals(1, $fileModel->create(1, 'test', '/tmp/foo', 10));
+
+ $file = $fileModel->getById(1);
+ $this->assertEquals('test', $file['name']);
+ $this->assertEquals('/tmp/foo', $file['path']);
+ $this->assertEquals(0, $file['is_image']);
+ $this->assertEquals(1, $file['project_id']);
+ $this->assertEquals(time(), $file['date'], '', 2);
+ $this->assertEquals(0, $file['user_id']);
+ $this->assertEquals(10, $file['size']);
+
+ $this->assertEquals(2, $fileModel->create(1, 'test2.png', '/tmp/foobar', 10));
+
+ $file = $fileModel->getById(2);
+ $this->assertEquals('test2.png', $file['name']);
+ $this->assertEquals('/tmp/foobar', $file['path']);
+ $this->assertEquals(1, $file['is_image']);
+ }
+
+ public function testCreationWithFileNameTooLong()
+ {
+ $projectModel = new Project($this->container);
+ $fileModel = new ProjectFile($this->container);
+
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test')));
+
+ $this->assertNotFalse($fileModel->create(1, 'test', '/tmp/foo', 10));
+ $this->assertNotFalse($fileModel->create(1, str_repeat('a', 1000), '/tmp/foo', 10));
+
+ $files = $fileModel->getAll(1);
+ $this->assertNotEmpty($files);
+ $this->assertCount(2, $files);
+
+ $this->assertEquals(str_repeat('a', 255), $files[0]['name']);
+ $this->assertEquals('test', $files[1]['name']);
+ }
+
+ public function testCreationWithSessionOpen()
+ {
+ $this->container['sessionStorage']->user = array('id' => 1);
+
+ $projectModel = new Project($this->container);
+ $fileModel = new ProjectFile($this->container);
+
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test')));
+ $this->assertEquals(1, $fileModel->create(1, 'test', '/tmp/foo', 10));
+
+ $file = $fileModel->getById(1);
+ $this->assertEquals('test', $file['name']);
+ $this->assertEquals(1, $file['user_id']);
+ }
+
+ public function testGetAll()
+ {
+ $projectModel = new Project($this->container);
+ $fileModel = new ProjectFile($this->container);
+
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test')));
+
+ $this->assertEquals(1, $fileModel->create(1, 'B.pdf', '/tmp/foo', 10));
+ $this->assertEquals(2, $fileModel->create(1, 'A.png', '/tmp/foo', 10));
+ $this->assertEquals(3, $fileModel->create(1, 'D.doc', '/tmp/foo', 10));
+ $this->assertEquals(4, $fileModel->create(1, 'C.JPG', '/tmp/foo', 10));
+
+ $fileModeliles = $fileModel->getAll(1);
+ $this->assertNotEmpty($fileModeliles);
+ $this->assertCount(4, $fileModeliles);
+ $this->assertEquals('A.png', $fileModeliles[0]['name']);
+ $this->assertEquals('B.pdf', $fileModeliles[1]['name']);
+ $this->assertEquals('C.JPG', $fileModeliles[2]['name']);
+ $this->assertEquals('D.doc', $fileModeliles[3]['name']);
+
+ $fileModeliles = $fileModel->getAllImages(1);
+ $this->assertNotEmpty($fileModeliles);
+ $this->assertCount(2, $fileModeliles);
+ $this->assertEquals('A.png', $fileModeliles[0]['name']);
+ $this->assertEquals('C.JPG', $fileModeliles[1]['name']);
+
+ $fileModeliles = $fileModel->getAllDocuments(1);
+ $this->assertNotEmpty($fileModeliles);
+ $this->assertCount(2, $fileModeliles);
+ $this->assertEquals('B.pdf', $fileModeliles[0]['name']);
+ $this->assertEquals('D.doc', $fileModeliles[1]['name']);
+ }
+
+ public function testGetThumbnailPath()
+ {
+ $fileModel = new ProjectFile($this->container);
+ $this->assertEquals('thumbnails'.DIRECTORY_SEPARATOR.'test', $fileModel->getThumbnailPath('test'));
+ }
+
+ public function testGeneratePath()
+ {
+ $fileModel = new ProjectFile($this->container);
+
+ $this->assertStringStartsWith('projects'.DIRECTORY_SEPARATOR.'34'.DIRECTORY_SEPARATOR, $fileModel->generatePath(34, 'test.png'));
+ $this->assertNotEquals($fileModel->generatePath(34, 'test1.png'), $fileModel->generatePath(34, 'test2.png'));
+ }
+
+ public function testUploadFiles()
+ {
+ $fileModel = $this
+ ->getMockBuilder('\Kanboard\Model\ProjectFile')
+ ->setConstructorArgs(array($this->container))
+ ->setMethods(array('generateThumbnailFromFile'))
+ ->getMock();
+
+ $projectModel = new Project($this->container);
+
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test')));
+
+ $files = array(
+ 'name' => array(
+ 'file1.png',
+ 'file2.doc',
+ ),
+ 'tmp_name' => array(
+ '/tmp/phpYzdqkD',
+ '/tmp/phpeEwEWG',
+ ),
+ 'error' => array(
+ UPLOAD_ERR_OK,
+ UPLOAD_ERR_OK,
+ ),
+ 'size' => array(
+ 123,
+ 456,
+ ),
+ );
+
+ $fileModel
+ ->expects($this->once())
+ ->method('generateThumbnailFromFile');
+
+ $this->container['objectStorage']
+ ->expects($this->at(0))
+ ->method('moveUploadedFile')
+ ->with($this->equalTo('/tmp/phpYzdqkD'), $this->anything());
+
+ $this->container['objectStorage']
+ ->expects($this->at(1))
+ ->method('moveUploadedFile')
+ ->with($this->equalTo('/tmp/phpeEwEWG'), $this->anything());
+
+ $this->assertTrue($fileModel->uploadFiles(1, $files));
+
+ $files = $fileModel->getAll(1);
+ $this->assertCount(2, $files);
+
+ $this->assertEquals(1, $files[0]['id']);
+ $this->assertEquals('file1.png', $files[0]['name']);
+ $this->assertEquals(1, $files[0]['is_image']);
+ $this->assertEquals(1, $files[0]['project_id']);
+ $this->assertEquals(0, $files[0]['user_id']);
+ $this->assertEquals(123, $files[0]['size']);
+ $this->assertEquals(time(), $files[0]['date'], '', 2);
+
+ $this->assertEquals(2, $files[1]['id']);
+ $this->assertEquals('file2.doc', $files[1]['name']);
+ $this->assertEquals(0, $files[1]['is_image']);
+ $this->assertEquals(1, $files[1]['project_id']);
+ $this->assertEquals(0, $files[1]['user_id']);
+ $this->assertEquals(456, $files[1]['size']);
+ $this->assertEquals(time(), $files[1]['date'], '', 2);
+ }
+
+ public function testUploadFilesWithEmptyFiles()
+ {
+ $fileModel = new ProjectFile($this->container);
+ $this->assertFalse($fileModel->uploadFiles(1, array()));
+ }
+
+ public function testUploadFilesWithUploadError()
+ {
+ $files = array(
+ 'name' => array(
+ 'file1.png',
+ 'file2.doc',
+ ),
+ 'tmp_name' => array(
+ '',
+ '/tmp/phpeEwEWG',
+ ),
+ 'error' => array(
+ UPLOAD_ERR_CANT_WRITE,
+ UPLOAD_ERR_OK,
+ ),
+ 'size' => array(
+ 123,
+ 456,
+ ),
+ );
+
+ $fileModel = new ProjectFile($this->container);
+ $this->assertFalse($fileModel->uploadFiles(1, $files));
+ }
+
+ public function testUploadFilesWithObjectStorageError()
+ {
+ $files = array(
+ 'name' => array(
+ 'file1.csv',
+ 'file2.doc',
+ ),
+ 'tmp_name' => array(
+ '/tmp/phpYzdqkD',
+ '/tmp/phpeEwEWG',
+ ),
+ 'error' => array(
+ UPLOAD_ERR_OK,
+ UPLOAD_ERR_OK,
+ ),
+ 'size' => array(
+ 123,
+ 456,
+ ),
+ );
+
+ $this->container['objectStorage']
+ ->expects($this->at(0))
+ ->method('moveUploadedFile')
+ ->with($this->equalTo('/tmp/phpYzdqkD'), $this->anything())
+ ->will($this->throwException(new \Kanboard\Core\ObjectStorage\ObjectStorageException('test')));
+
+ $fileModel = new ProjectFile($this->container);
+ $this->assertFalse($fileModel->uploadFiles(1, $files));
+ }
+
+ public function testUploadFileContent()
+ {
+ $fileModel = $this
+ ->getMockBuilder('\Kanboard\Model\ProjectFile')
+ ->setConstructorArgs(array($this->container))
+ ->setMethods(array('generateThumbnailFromFile'))
+ ->getMock();
+
+ $projectModel = new Project($this->container);
+ $data = 'test';
+
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test')));
+
+ $this->container['objectStorage']
+ ->expects($this->once())
+ ->method('put')
+ ->with($this->anything(), $this->equalTo($data));
+
+ $this->assertEquals(1, $fileModel->uploadContent(1, 'test.doc', base64_encode($data)));
+
+ $files = $fileModel->getAll(1);
+ $this->assertCount(1, $files);
+
+ $this->assertEquals(1, $files[0]['id']);
+ $this->assertEquals('test.doc', $files[0]['name']);
+ $this->assertEquals(0, $files[0]['is_image']);
+ $this->assertEquals(1, $files[0]['project_id']);
+ $this->assertEquals(0, $files[0]['user_id']);
+ $this->assertEquals(4, $files[0]['size']);
+ $this->assertEquals(time(), $files[0]['date'], '', 2);
+ }
+
+ public function testUploadImageContent()
+ {
+ $fileModel = $this
+ ->getMockBuilder('\Kanboard\Model\ProjectFile')
+ ->setConstructorArgs(array($this->container))
+ ->setMethods(array('generateThumbnailFromFile'))
+ ->getMock();
+
+ $projectModel = new Project($this->container);
+ $data = 'test';
+
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test')));
+
+ $fileModel
+ ->expects($this->once())
+ ->method('generateThumbnailFromFile');
+
+ $this->container['objectStorage']
+ ->expects($this->once())
+ ->method('put')
+ ->with($this->anything(), $this->equalTo($data));
+
+ $this->assertEquals(1, $fileModel->uploadContent(1, 'test.png', base64_encode($data)));
+
+ $files = $fileModel->getAll(1);
+ $this->assertCount(1, $files);
+
+ $this->assertEquals(1, $files[0]['id']);
+ $this->assertEquals('test.png', $files[0]['name']);
+ $this->assertEquals(1, $files[0]['is_image']);
+ $this->assertEquals(1, $files[0]['project_id']);
+ $this->assertEquals(0, $files[0]['user_id']);
+ $this->assertEquals(4, $files[0]['size']);
+ $this->assertEquals(time(), $files[0]['date'], '', 2);
+ }
+}
diff --git a/tests/units/Model/TaskFileTest.php b/tests/units/Model/TaskFileTest.php
new file mode 100644
index 00000000..753a1fb6
--- /dev/null
+++ b/tests/units/Model/TaskFileTest.php
@@ -0,0 +1,458 @@
+container);
+ $fileModel = new TaskFile($this->container);
+ $taskCreationModel = new TaskCreation($this->container);
+
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test')));
+ $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test')));
+
+ $this->assertEquals(1, $fileModel->create(1, 'test', '/tmp/foo', 10));
+
+ $file = $fileModel->getById(1);
+ $this->assertEquals('test', $file['name']);
+ $this->assertEquals('/tmp/foo', $file['path']);
+ $this->assertEquals(0, $file['is_image']);
+ $this->assertEquals(1, $file['task_id']);
+ $this->assertEquals(time(), $file['date'], '', 2);
+ $this->assertEquals(0, $file['user_id']);
+ $this->assertEquals(10, $file['size']);
+
+ $this->assertEquals(2, $fileModel->create(1, 'test2.png', '/tmp/foobar', 10));
+
+ $file = $fileModel->getById(2);
+ $this->assertEquals('test2.png', $file['name']);
+ $this->assertEquals('/tmp/foobar', $file['path']);
+ $this->assertEquals(1, $file['is_image']);
+ }
+
+ public function testCreationWithFileNameTooLong()
+ {
+ $projectModel = new Project($this->container);
+ $fileModel = new TaskFile($this->container);
+ $taskCreationModel = new TaskCreation($this->container);
+
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test')));
+ $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test')));
+
+ $this->assertNotFalse($fileModel->create(1, 'test', '/tmp/foo', 10));
+ $this->assertNotFalse($fileModel->create(1, str_repeat('a', 1000), '/tmp/foo', 10));
+
+ $files = $fileModel->getAll(1);
+ $this->assertNotEmpty($files);
+ $this->assertCount(2, $files);
+
+ $this->assertEquals(str_repeat('a', 255), $files[0]['name']);
+ $this->assertEquals('test', $files[1]['name']);
+ }
+
+ public function testCreationWithSessionOpen()
+ {
+ $this->container['sessionStorage']->user = array('id' => 1);
+
+ $projectModel = new Project($this->container);
+ $fileModel = new TaskFile($this->container);
+ $taskCreationModel = new TaskCreation($this->container);
+
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test')));
+ $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test')));
+ $this->assertEquals(1, $fileModel->create(1, 'test', '/tmp/foo', 10));
+
+ $file = $fileModel->getById(1);
+ $this->assertEquals('test', $file['name']);
+ $this->assertEquals(1, $file['user_id']);
+ }
+
+ public function testGetAll()
+ {
+ $projectModel = new Project($this->container);
+ $fileModel = new TaskFile($this->container);
+ $taskCreationModel = new TaskCreation($this->container);
+
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test')));
+ $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test')));
+
+ $this->assertEquals(1, $fileModel->create(1, 'B.pdf', '/tmp/foo', 10));
+ $this->assertEquals(2, $fileModel->create(1, 'A.png', '/tmp/foo', 10));
+ $this->assertEquals(3, $fileModel->create(1, 'D.doc', '/tmp/foo', 10));
+ $this->assertEquals(4, $fileModel->create(1, 'C.JPG', '/tmp/foo', 10));
+
+ $fileModeliles = $fileModel->getAll(1);
+ $this->assertNotEmpty($fileModeliles);
+ $this->assertCount(4, $fileModeliles);
+ $this->assertEquals('A.png', $fileModeliles[0]['name']);
+ $this->assertEquals('B.pdf', $fileModeliles[1]['name']);
+ $this->assertEquals('C.JPG', $fileModeliles[2]['name']);
+ $this->assertEquals('D.doc', $fileModeliles[3]['name']);
+
+ $fileModeliles = $fileModel->getAllImages(1);
+ $this->assertNotEmpty($fileModeliles);
+ $this->assertCount(2, $fileModeliles);
+ $this->assertEquals('A.png', $fileModeliles[0]['name']);
+ $this->assertEquals('C.JPG', $fileModeliles[1]['name']);
+
+ $fileModeliles = $fileModel->getAllDocuments(1);
+ $this->assertNotEmpty($fileModeliles);
+ $this->assertCount(2, $fileModeliles);
+ $this->assertEquals('B.pdf', $fileModeliles[0]['name']);
+ $this->assertEquals('D.doc', $fileModeliles[1]['name']);
+ }
+
+ public function testIsImage()
+ {
+ $fileModel = new TaskFile($this->container);
+
+ $this->assertTrue($fileModel->isImage('test.png'));
+ $this->assertTrue($fileModel->isImage('test.jpeg'));
+ $this->assertTrue($fileModel->isImage('test.gif'));
+ $this->assertTrue($fileModel->isImage('test.jpg'));
+ $this->assertTrue($fileModel->isImage('test.JPG'));
+
+ $this->assertFalse($fileModel->isImage('test.bmp'));
+ $this->assertFalse($fileModel->isImage('test'));
+ $this->assertFalse($fileModel->isImage('test.pdf'));
+ }
+
+ public function testGetMimeType()
+ {
+ $fileModel = new TaskFile($this->container);
+
+ $this->assertEquals('image/jpeg', $fileModel->getImageMimeType('My File.JPG'));
+ $this->assertEquals('image/jpeg', $fileModel->getImageMimeType('My File.jpeg'));
+ $this->assertEquals('image/png', $fileModel->getImageMimeType('My File.PNG'));
+ $this->assertEquals('image/gif', $fileModel->getImageMimeType('My File.gif'));
+ $this->assertEquals('image/jpeg', $fileModel->getImageMimeType('My File.bmp'));
+ $this->assertEquals('image/jpeg', $fileModel->getImageMimeType('My File'));
+ }
+
+ public function testGetThumbnailPath()
+ {
+ $fileModel = new TaskFile($this->container);
+ $this->assertEquals('thumbnails'.DIRECTORY_SEPARATOR.'test', $fileModel->getThumbnailPath('test'));
+ }
+
+ public function testGeneratePath()
+ {
+ $fileModel = new TaskFile($this->container);
+
+ $this->assertStringStartsWith('tasks'.DIRECTORY_SEPARATOR.'34'.DIRECTORY_SEPARATOR, $fileModel->generatePath(34, 'test.png'));
+ $this->assertNotEquals($fileModel->generatePath(34, 'test1.png'), $fileModel->generatePath(34, 'test2.png'));
+ }
+
+ public function testUploadFiles()
+ {
+ $fileModel = $this
+ ->getMockBuilder('\Kanboard\Model\TaskFile')
+ ->setConstructorArgs(array($this->container))
+ ->setMethods(array('generateThumbnailFromFile'))
+ ->getMock();
+
+ $projectModel = new Project($this->container);
+ $taskCreationModel = new TaskCreation($this->container);
+
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test')));
+ $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test')));
+
+ $files = array(
+ 'name' => array(
+ 'file1.png',
+ 'file2.doc',
+ ),
+ 'tmp_name' => array(
+ '/tmp/phpYzdqkD',
+ '/tmp/phpeEwEWG',
+ ),
+ 'error' => array(
+ UPLOAD_ERR_OK,
+ UPLOAD_ERR_OK,
+ ),
+ 'size' => array(
+ 123,
+ 456,
+ ),
+ );
+
+ $fileModel
+ ->expects($this->once())
+ ->method('generateThumbnailFromFile');
+
+ $this->container['objectStorage']
+ ->expects($this->at(0))
+ ->method('moveUploadedFile')
+ ->with($this->equalTo('/tmp/phpYzdqkD'), $this->anything());
+
+ $this->container['objectStorage']
+ ->expects($this->at(1))
+ ->method('moveUploadedFile')
+ ->with($this->equalTo('/tmp/phpeEwEWG'), $this->anything());
+
+ $this->assertTrue($fileModel->uploadFiles(1, $files));
+
+ $files = $fileModel->getAll(1);
+ $this->assertCount(2, $files);
+
+ $this->assertEquals(1, $files[0]['id']);
+ $this->assertEquals('file1.png', $files[0]['name']);
+ $this->assertEquals(1, $files[0]['is_image']);
+ $this->assertEquals(1, $files[0]['task_id']);
+ $this->assertEquals(0, $files[0]['user_id']);
+ $this->assertEquals(123, $files[0]['size']);
+ $this->assertEquals(time(), $files[0]['date'], '', 2);
+
+ $this->assertEquals(2, $files[1]['id']);
+ $this->assertEquals('file2.doc', $files[1]['name']);
+ $this->assertEquals(0, $files[1]['is_image']);
+ $this->assertEquals(1, $files[1]['task_id']);
+ $this->assertEquals(0, $files[1]['user_id']);
+ $this->assertEquals(456, $files[1]['size']);
+ $this->assertEquals(time(), $files[1]['date'], '', 2);
+ }
+
+ public function testUploadFilesWithEmptyFiles()
+ {
+ $fileModel = new TaskFile($this->container);
+ $this->assertFalse($fileModel->uploadFiles(1, array()));
+ }
+
+ public function testUploadFilesWithUploadError()
+ {
+ $files = array(
+ 'name' => array(
+ 'file1.png',
+ 'file2.doc',
+ ),
+ 'tmp_name' => array(
+ '',
+ '/tmp/phpeEwEWG',
+ ),
+ 'error' => array(
+ UPLOAD_ERR_CANT_WRITE,
+ UPLOAD_ERR_OK,
+ ),
+ 'size' => array(
+ 123,
+ 456,
+ ),
+ );
+
+ $fileModel = new TaskFile($this->container);
+ $this->assertFalse($fileModel->uploadFiles(1, $files));
+ }
+
+ public function testUploadFilesWithObjectStorageError()
+ {
+ $files = array(
+ 'name' => array(
+ 'file1.csv',
+ 'file2.doc',
+ ),
+ 'tmp_name' => array(
+ '/tmp/phpYzdqkD',
+ '/tmp/phpeEwEWG',
+ ),
+ 'error' => array(
+ UPLOAD_ERR_OK,
+ UPLOAD_ERR_OK,
+ ),
+ 'size' => array(
+ 123,
+ 456,
+ ),
+ );
+
+ $this->container['objectStorage']
+ ->expects($this->at(0))
+ ->method('moveUploadedFile')
+ ->with($this->equalTo('/tmp/phpYzdqkD'), $this->anything())
+ ->will($this->throwException(new \Kanboard\Core\ObjectStorage\ObjectStorageException('test')));
+
+ $fileModel = new TaskFile($this->container);
+ $this->assertFalse($fileModel->uploadFiles(1, $files));
+ }
+
+ public function testUploadFileContent()
+ {
+ $fileModel = $this
+ ->getMockBuilder('\Kanboard\Model\TaskFile')
+ ->setConstructorArgs(array($this->container))
+ ->setMethods(array('generateThumbnailFromFile'))
+ ->getMock();
+
+ $projectModel = new Project($this->container);
+ $taskCreationModel = new TaskCreation($this->container);
+ $data = 'test';
+
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test')));
+ $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test')));
+
+ $this->container['objectStorage']
+ ->expects($this->once())
+ ->method('put')
+ ->with($this->anything(), $this->equalTo($data));
+
+ $this->assertEquals(1, $fileModel->uploadContent(1, 'test.doc', base64_encode($data)));
+
+ $files = $fileModel->getAll(1);
+ $this->assertCount(1, $files);
+
+ $this->assertEquals(1, $files[0]['id']);
+ $this->assertEquals('test.doc', $files[0]['name']);
+ $this->assertEquals(0, $files[0]['is_image']);
+ $this->assertEquals(1, $files[0]['task_id']);
+ $this->assertEquals(0, $files[0]['user_id']);
+ $this->assertEquals(4, $files[0]['size']);
+ $this->assertEquals(time(), $files[0]['date'], '', 2);
+ }
+
+ public function testUploadFileContentWithObjectStorageError()
+ {
+ $fileModel = $this
+ ->getMockBuilder('\Kanboard\Model\TaskFile')
+ ->setConstructorArgs(array($this->container))
+ ->setMethods(array('generateThumbnailFromFile'))
+ ->getMock();
+
+ $projectModel = new Project($this->container);
+ $taskCreationModel = new TaskCreation($this->container);
+ $data = 'test';
+
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test')));
+ $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test')));
+
+ $this->container['objectStorage']
+ ->expects($this->once())
+ ->method('put')
+ ->with($this->anything(), $this->equalTo($data))
+ ->will($this->throwException(new \Kanboard\Core\ObjectStorage\ObjectStorageException('test')));
+
+ $this->assertFalse($fileModel->uploadContent(1, 'test.doc', base64_encode($data)));
+ }
+
+ public function testUploadScreenshot()
+ {
+ $fileModel = $this
+ ->getMockBuilder('\Kanboard\Model\TaskFile')
+ ->setConstructorArgs(array($this->container))
+ ->setMethods(array('generateThumbnailFromFile'))
+ ->getMock();
+
+ $projectModel = new Project($this->container);
+ $taskCreationModel = new TaskCreation($this->container);
+ $data = 'test';
+
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test')));
+ $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test')));
+
+ $fileModel
+ ->expects($this->once())
+ ->method('generateThumbnailFromFile');
+
+ $this->container['objectStorage']
+ ->expects($this->once())
+ ->method('put')
+ ->with($this->anything(), $this->equalTo($data));
+
+ $this->assertEquals(1, $fileModel->uploadScreenshot(1, base64_encode($data)));
+
+ $files = $fileModel->getAll(1);
+ $this->assertCount(1, $files);
+
+ $this->assertEquals(1, $files[0]['id']);
+ $this->assertStringStartsWith('Screenshot taken ', $files[0]['name']);
+ $this->assertEquals(1, $files[0]['is_image']);
+ $this->assertEquals(1, $files[0]['task_id']);
+ $this->assertEquals(0, $files[0]['user_id']);
+ $this->assertEquals(4, $files[0]['size']);
+ $this->assertEquals(time(), $files[0]['date'], '', 2);
+ }
+
+ public function testRemove()
+ {
+ $fileModel = new TaskFile($this->container);
+ $projectModel = new Project($this->container);
+ $taskCreationModel = new TaskCreation($this->container);
+
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test')));
+ $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test')));
+ $this->assertEquals(1, $fileModel->create(1, 'test', 'tmp/foo', 10));
+
+ $this->container['objectStorage']
+ ->expects($this->once())
+ ->method('remove')
+ ->with('tmp/foo');
+
+ $this->assertTrue($fileModel->remove(1));
+ }
+
+ public function testRemoveWithObjectStorageError()
+ {
+ $fileModel = new TaskFile($this->container);
+ $projectModel = new Project($this->container);
+ $taskCreationModel = new TaskCreation($this->container);
+
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test')));
+ $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test')));
+ $this->assertEquals(1, $fileModel->create(1, 'test', 'tmp/foo', 10));
+
+ $this->container['objectStorage']
+ ->expects($this->once())
+ ->method('remove')
+ ->with('tmp/foo')
+ ->will($this->throwException(new \Kanboard\Core\ObjectStorage\ObjectStorageException('test')));
+
+ $this->assertFalse($fileModel->remove(1));
+ }
+
+ public function testRemoveImage()
+ {
+ $fileModel = new TaskFile($this->container);
+ $projectModel = new Project($this->container);
+ $taskCreationModel = new TaskCreation($this->container);
+
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test')));
+ $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test')));
+ $this->assertEquals(1, $fileModel->create(1, 'image.gif', 'tmp/image.gif', 10));
+
+ $this->container['objectStorage']
+ ->expects($this->at(0))
+ ->method('remove')
+ ->with('tmp/image.gif');
+
+ $this->container['objectStorage']
+ ->expects($this->at(1))
+ ->method('remove')
+ ->with('thumbnails'.DIRECTORY_SEPARATOR.'tmp/image.gif');
+
+ $this->assertTrue($fileModel->remove(1));
+ }
+
+ public function testRemoveAll()
+ {
+ $fileModel = new TaskFile($this->container);
+ $projectModel = new Project($this->container);
+ $taskCreationModel = new TaskCreation($this->container);
+
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test')));
+ $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test')));
+ $this->assertEquals(1, $fileModel->create(1, 'test', 'tmp/foo', 10));
+ $this->assertEquals(2, $fileModel->create(1, 'test', 'tmp/foo', 10));
+
+ $this->container['objectStorage']
+ ->expects($this->exactly(2))
+ ->method('remove')
+ ->with('tmp/foo');
+
+ $this->assertTrue($fileModel->removeAll(1));
+ }
+}
diff --git a/tests/units/Model/UserNotificationTest.php b/tests/units/Model/UserNotificationTest.php
index 8168a375..e1928661 100644
--- a/tests/units/Model/UserNotificationTest.php
+++ b/tests/units/Model/UserNotificationTest.php
@@ -9,7 +9,6 @@ use Kanboard\Model\Comment;
use Kanboard\Model\User;
use Kanboard\Model\Group;
use Kanboard\Model\GroupMember;
-use Kanboard\Model\File;
use Kanboard\Model\Project;
use Kanboard\Model\ProjectPermission;
use Kanboard\Model\Task;
diff --git a/tests/units/Model/UserUnreadNotificationTest.php b/tests/units/Model/UserUnreadNotificationTest.php
index bf274d95..62889bf0 100644
--- a/tests/units/Model/UserUnreadNotificationTest.php
+++ b/tests/units/Model/UserUnreadNotificationTest.php
@@ -7,7 +7,6 @@ use Kanboard\Model\TaskCreation;
use Kanboard\Model\Subtask;
use Kanboard\Model\Comment;
use Kanboard\Model\User;
-use Kanboard\Model\File;
use Kanboard\Model\Task;
use Kanboard\Model\Project;
use Kanboard\Model\UserUnreadNotification;
diff --git a/tests/units/Notification/MailTest.php b/tests/units/Notification/MailTest.php
index 8f343ba3..7dc6aaef 100644
--- a/tests/units/Notification/MailTest.php
+++ b/tests/units/Notification/MailTest.php
@@ -7,7 +7,7 @@ use Kanboard\Model\TaskCreation;
use Kanboard\Model\Subtask;
use Kanboard\Model\Comment;
use Kanboard\Model\User;
-use Kanboard\Model\File;
+use Kanboard\Model\TaskFile;
use Kanboard\Model\Project;
use Kanboard\Model\Task;
use Kanboard\Notification\Mail;
@@ -23,7 +23,7 @@ class MailTest extends Base
$tc = new TaskCreation($this->container);
$s = new Subtask($this->container);
$c = new Comment($this->container);
- $f = new File($this->container);
+ $f = new TaskFile($this->container);
$this->assertEquals(1, $p->create(array('name' => 'test')));
$this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1)));
--
cgit v1.2.3
From 8936792f6f7a408dae7e0a6a41274202822acd9c Mon Sep 17 00:00:00 2001
From: Frederic Guillot
Date: Tue, 16 Feb 2016 21:12:43 -0500
Subject: Add file attachements to projects
---
app/Controller/Base.php | 30 +++++++++
app/Controller/FileViewer.php | 89 +++++++++++++++++++++++++
app/Controller/ProjectFile.php | 79 ++++++++++++++++++++++
app/Controller/ProjectOverview.php | 2 +
app/Controller/TaskFile.php | 96 ++-------------------------
app/Helper/File.php | 24 +++++++
app/Model/File.php | 24 -------
app/Template/file_viewer/show.php | 8 +++
app/Template/project_file/create.php | 33 +++++++++
app/Template/project_file/remove.php | 15 +++++
app/Template/project_overview/columns.php | 8 +++
app/Template/project_overview/description.php | 8 +++
app/Template/project_overview/files.php | 92 +++++++++++++++++++++++++
app/Template/project_overview/information.php | 35 ++++++++++
app/Template/project_overview/show.php | 58 ++--------------
app/Template/task_file/create.php | 33 +++++++++
app/Template/task_file/new.php | 33 ---------
app/Template/task_file/open.php | 6 --
app/Template/task_file/show.php | 6 +-
tests/units/Helper/FileHelperText.php | 18 ++++-
tests/units/Model/TaskFileTest.php | 12 ----
21 files changed, 482 insertions(+), 227 deletions(-)
create mode 100644 app/Controller/FileViewer.php
create mode 100644 app/Controller/ProjectFile.php
create mode 100644 app/Template/file_viewer/show.php
create mode 100644 app/Template/project_file/create.php
create mode 100644 app/Template/project_file/remove.php
create mode 100644 app/Template/project_overview/columns.php
create mode 100644 app/Template/project_overview/description.php
create mode 100644 app/Template/project_overview/files.php
create mode 100644 app/Template/project_overview/information.php
create mode 100644 app/Template/task_file/create.php
delete mode 100644 app/Template/task_file/new.php
delete mode 100644 app/Template/task_file/open.php
(limited to 'app/Model/File.php')
diff --git a/app/Controller/Base.php b/app/Controller/Base.php
index c55ad9ad..884c439c 100644
--- a/app/Controller/Base.php
+++ b/app/Controller/Base.php
@@ -201,6 +201,36 @@ abstract class Base extends \Kanboard\Core\Base
return $task;
}
+ /**
+ * Get Task or Project file
+ *
+ * @access protected
+ */
+ protected function getFile()
+ {
+ $task_id = $this->request->getIntegerParam('task_id');
+ $file_id = $this->request->getIntegerParam('file_id');
+ $model = 'projectFile';
+
+ if ($task_id > 0) {
+ $model = 'taskFile';
+ $project_id = $this->taskFinder->getProjectId($task_id);
+
+ if ($project_id !== $this->request->getIntegerParam('project_id')) {
+ $this->forbidden();
+ }
+ }
+
+ $file = $this->$model->getById($file_id);
+
+ if (empty($file)) {
+ $this->notfound();
+ }
+
+ $file['model'] = $model;
+ return $file;
+ }
+
/**
* Common method to get a project
*
diff --git a/app/Controller/FileViewer.php b/app/Controller/FileViewer.php
new file mode 100644
index 00000000..24ccc691
--- /dev/null
+++ b/app/Controller/FileViewer.php
@@ -0,0 +1,89 @@
+getFile();
+ $params = array('file_id' => $file['id'], 'project_id' => $this->request->getIntegerParam('project_id'));
+
+ if ($file['model'] === 'taskFile') {
+ $params['task_id'] = $file['task_id'];
+ }
+
+ $this->response->html($this->template->render('file_viewer/show', array(
+ 'file' => $file,
+ 'params' => $params,
+ )));
+ }
+
+ /**
+ * Display image
+ *
+ * @access public
+ */
+ public function image()
+ {
+ try {
+ $file = $this->getFile();
+ $this->response->contentType($this->helper->file->getImageMimeType($file['name']));
+ $this->objectStorage->output($file['path']);
+ } catch (ObjectStorageException $e) {
+ $this->logger->error($e->getMessage());
+ }
+ }
+
+ /**
+ * Display image thumbnail
+ *
+ * @access public
+ */
+ public function thumbnail()
+ {
+ $this->response->contentType('image/jpeg');
+
+ try {
+ $file = $this->getFile();
+ $model = $file['model'];
+ $this->objectStorage->output($this->$model->getThumbnailPath($file['path']));
+ } catch (ObjectStorageException $e) {
+ $this->logger->error($e->getMessage());
+
+ // Try to generate thumbnail on the fly for images uploaded before Kanboard < 1.0.19
+ $data = $this->objectStorage->get($file['path']);
+ $this->$model->generateThumbnailFromData($file['path'], $data);
+ $this->objectStorage->output($this->$model->getThumbnailPath($file['path']));
+ }
+ }
+
+ /**
+ * File download
+ *
+ * @access public
+ */
+ public function download()
+ {
+ try {
+ $file = $this->getFile();
+ $this->response->forceDownload($file['name']);
+ $this->objectStorage->output($file['path']);
+ } catch (ObjectStorageException $e) {
+ $this->logger->error($e->getMessage());
+ }
+ }
+}
diff --git a/app/Controller/ProjectFile.php b/app/Controller/ProjectFile.php
new file mode 100644
index 00000000..96764a92
--- /dev/null
+++ b/app/Controller/ProjectFile.php
@@ -0,0 +1,79 @@
+getProject();
+
+ $this->response->html($this->template->render('project_file/create', array(
+ 'project' => $project,
+ 'max_size' => $this->helper->text->phpToBytes(ini_get('upload_max_filesize')),
+ )));
+ }
+
+ /**
+ * Save uploaded files
+ *
+ * @access public
+ */
+ public function save()
+ {
+ $project = $this->getProject();
+
+ if (! $this->projectFile->uploadFiles($project['id'], $this->request->getFileInfo('files'))) {
+ $this->flash->failure(t('Unable to upload the file.'));
+ }
+
+ $this->response->redirect($this->helper->url->to('ProjectOverview', 'show', array('project_id' => $project['id'])), true);
+ }
+
+ /**
+ * Remove a file
+ *
+ * @access public
+ */
+ public function remove()
+ {
+ $this->checkCSRFParam();
+ $project = $this->getProject();
+ $file = $this->projectFile->getById($this->request->getIntegerParam('file_id'));
+
+ if ($this->projectFile->remove($file['id'])) {
+ $this->flash->success(t('File removed successfully.'));
+ } else {
+ $this->flash->failure(t('Unable to remove this file.'));
+ }
+
+ $this->response->redirect($this->helper->url->to('ProjectOverview', 'show', array('project_id' => $project['id'])));
+ }
+
+ /**
+ * Confirmation dialog before removing a file
+ *
+ * @access public
+ */
+ public function confirm()
+ {
+ $project = $this->getProject();
+ $file = $this->projectFile->getById($this->request->getIntegerParam('file_id'));
+
+ $this->response->html($this->template->render('project_file/remove', array(
+ 'project' => $project,
+ 'file' => $file,
+ )));
+ }
+}
diff --git a/app/Controller/ProjectOverview.php b/app/Controller/ProjectOverview.php
index cbd65777..b0687ed3 100644
--- a/app/Controller/ProjectOverview.php
+++ b/app/Controller/ProjectOverview.php
@@ -19,6 +19,8 @@ class ProjectOverview extends Base
$params['users'] = $this->projectUserRole->getAllUsersGroupedByRole($params['project']['id']);
$params['roles'] = $this->role->getProjectRoles();
$params['events'] = $this->projectActivity->getProject($params['project']['id'], 10);
+ $params['images'] = $this->projectFile->getAllImages($params['project']['id']);
+ $params['files'] = $this->projectFile->getAllDocuments($params['project']['id']);
$this->project->getColumnStats($params['project']);
diff --git a/app/Controller/TaskFile.php b/app/Controller/TaskFile.php
index 102fdc5c..2b0152a7 100644
--- a/app/Controller/TaskFile.php
+++ b/app/Controller/TaskFile.php
@@ -2,10 +2,8 @@
namespace Kanboard\Controller;
-use Kanboard\Core\ObjectStorage\ObjectStorageException;
-
/**
- * File File Controller
+ * Task File Controller
*
* @package controller
* @author Frederic Guillot
@@ -26,7 +24,7 @@ class TaskFile extends Base
return $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])), true);
}
- $this->response->html($this->helper->layout->task('task_file/screenshot', array(
+ $this->response->html($this->template->render('task_file/screenshot', array(
'task' => $task,
)));
}
@@ -40,7 +38,7 @@ class TaskFile extends Base
{
$task = $this->getTask();
- $this->response->html($this->helper->layout->task('task_file/new', array(
+ $this->response->html($this->template->render('task_file/create', array(
'task' => $task,
'max_size' => $this->helper->text->phpToBytes(ini_get('upload_max_filesize')),
)));
@@ -62,92 +60,6 @@ class TaskFile extends Base
$this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])), true);
}
- /**
- * File download
- *
- * @access public
- */
- public function download()
- {
- try {
- $task = $this->getTask();
- $file = $this->taskFile->getById($this->request->getIntegerParam('file_id'));
-
- if ($file['task_id'] != $task['id']) {
- $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
- }
-
- $this->response->forceDownload($file['name']);
- $this->objectStorage->output($file['path']);
- } catch (ObjectStorageException $e) {
- $this->logger->error($e->getMessage());
- }
- }
-
- /**
- * Open a file (show the content in a popover)
- *
- * @access public
- */
- public function open()
- {
- $task = $this->getTask();
- $file = $this->taskFile->getById($this->request->getIntegerParam('file_id'));
-
- if ($file['task_id'] == $task['id']) {
- $this->response->html($this->template->render('task_file/open', array(
- 'file' => $file,
- 'task' => $task,
- )));
- }
- }
-
- /**
- * Display image
- *
- * @access public
- */
- public function image()
- {
- try {
- $task = $this->getTask();
- $file = $this->taskFile->getById($this->request->getIntegerParam('file_id'));
-
- if ($file['task_id'] == $task['id']) {
- $this->response->contentType($this->taskFile->getImageMimeType($file['name']));
- $this->objectStorage->output($file['path']);
- }
- } catch (ObjectStorageException $e) {
- $this->logger->error($e->getMessage());
- }
- }
-
- /**
- * Display image thumbnails
- *
- * @access public
- */
- public function thumbnail()
- {
- $this->response->contentType('image/jpeg');
-
- try {
- $task = $this->getTask();
- $file = $this->taskFile->getById($this->request->getIntegerParam('file_id'));
-
- if ($file['task_id'] == $task['id']) {
- $this->objectStorage->output($this->taskFile->getThumbnailPath($file['path']));
- }
- } catch (ObjectStorageException $e) {
- $this->logger->error($e->getMessage());
-
- // Try to generate thumbnail on the fly for images uploaded before Kanboard < 1.0.19
- $data = $this->objectStorage->get($file['path']);
- $this->taskFile->generateThumbnailFromData($file['path'], $data);
- $this->objectStorage->output($this->taskFile->getThumbnailPath($file['path']));
- }
- }
-
/**
* Remove a file
*
@@ -178,7 +90,7 @@ class TaskFile extends Base
$task = $this->getTask();
$file = $this->taskFile->getById($this->request->getIntegerParam('file_id'));
- $this->response->html($this->helper->layout->task('task_file/remove', array(
+ $this->response->html($this->template->render('task_file/remove', array(
'task' => $task,
'file' => $file,
)));
diff --git a/app/Helper/File.php b/app/Helper/File.php
index 20eda1e3..6948fe6a 100644
--- a/app/Helper/File.php
+++ b/app/Helper/File.php
@@ -58,4 +58,28 @@ class File extends \Kanboard\Core\Base
return 'fa-file-o';
}
+
+ /**
+ * Return the image mimetype based on the file extension
+ *
+ * @access public
+ * @param $filename
+ * @return string
+ */
+ public function getImageMimeType($filename)
+ {
+ $extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
+
+ switch ($extension) {
+ case 'jpeg':
+ case 'jpg':
+ return 'image/jpeg';
+ case 'png':
+ return 'image/png';
+ case 'gif':
+ return 'image/gif';
+ default:
+ return 'image/jpeg';
+ }
+ }
}
diff --git a/app/Model/File.php b/app/Model/File.php
index e17ecb2b..03ea691d 100644
--- a/app/Model/File.php
+++ b/app/Model/File.php
@@ -188,30 +188,6 @@ abstract class File extends Base
return false;
}
- /**
- * Return the image mimetype based on the file extension
- *
- * @access public
- * @param $filename
- * @return string
- */
- public function getImageMimeType($filename)
- {
- $extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
-
- switch ($extension) {
- case 'jpeg':
- case 'jpg':
- return 'image/jpeg';
- case 'png':
- return 'image/png';
- case 'gif':
- return 'image/gif';
- default:
- return 'image/jpeg';
- }
- }
-
/**
* Generate the path for a thumbnails
*
diff --git a/app/Template/file_viewer/show.php b/app/Template/file_viewer/show.php
new file mode 100644
index 00000000..e0d1b21e
--- /dev/null
+++ b/app/Template/file_viewer/show.php
@@ -0,0 +1,8 @@
+
\ No newline at end of file
diff --git a/app/Template/project_file/create.php b/app/Template/project_file/create.php
new file mode 100644
index 00000000..67315285
--- /dev/null
+++ b/app/Template/project_file/create.php
@@ -0,0 +1,33 @@
+
+
+
+ = t('All files have been uploaded successfully.') ?>
+ = $this->url->link(t('View uploaded files'), 'ProjectOverview', 'show', array('project_id' => $project['id'])) ?>
+
+
+
+
+
+
+
+
+
+
+
+ = t('or') ?>
+ = $this->url->link(t('cancel'), 'ProjectOverview', 'show', array('project_id' => $project['id']), false, 'close-popover') ?>
+
diff --git a/app/Template/project_file/remove.php b/app/Template/project_file/remove.php
new file mode 100644
index 00000000..4f0ba465
--- /dev/null
+++ b/app/Template/project_file/remove.php
@@ -0,0 +1,15 @@
+
+
+
+
+ = t('Do you really want to remove this file: "%s"?', $this->e($file['name'])) ?>
+
+
+
+ = $this->url->link(t('Yes'), 'ProjectFile', 'remove', array('project_id' => $project['id'], 'file_id' => $file['id']), true, 'btn btn-red') ?>
+ = t('or') ?>
+ = $this->url->link(t('cancel'), 'ProjectOverview', 'show', array('project_id' => $project['id']), false, 'close-popover') ?>
+
+
\ No newline at end of file
diff --git a/app/Template/project_overview/columns.php b/app/Template/project_overview/columns.php
new file mode 100644
index 00000000..870d753f
--- /dev/null
+++ b/app/Template/project_overview/columns.php
@@ -0,0 +1,8 @@
+
+
+
+ = $column['nb_tasks'] ?>
+ = $this->e($column['title']) ?>
+
+
+
diff --git a/app/Template/project_overview/description.php b/app/Template/project_overview/description.php
new file mode 100644
index 00000000..4137bf9f
--- /dev/null
+++ b/app/Template/project_overview/description.php
@@ -0,0 +1,8 @@
+
+
+
+ = $this->text->markdown($project['description']) ?>
+
+
diff --git a/app/Template/project_overview/files.php b/app/Template/project_overview/files.php
new file mode 100644
index 00000000..fea20ad6
--- /dev/null
+++ b/app/Template/project_overview/files.php
@@ -0,0 +1,92 @@
+
+
+
+ = t('There is no attachment at the moment.') ?>
+
+
+
+
+
+
+
+
+
+
+
+
+ user->hasProjectAccess('ProjectFile', 'remove', $project['id'])): ?>
+
+
+ = $this->url->link(t('Remove'), 'ProjectFile', 'confirm', array('project_id' => $project['id'], 'file_id' => $file['id']), false, 'popover') ?>
+
+
+
+
+ = $this->url->link(t('Download'), 'FileViewer', 'download', array('project_id' => $project['id'], 'file_id' => $file['id'])) ?>
+
+
+
+
+
+ dt->datetime($file['date'])).' '.t('Size: %s', $this->text->bytes($file['size'])) ?>'>
+
+
+ = t('Uploaded by %s', $file['user_name'] ?: $file['username']) ?>
+
+
+
+
+
+
+
+
+
+
+ = t('Filename') ?>
+ = t('Creator') ?>
+ = t('Date') ?>
+ = t('Size') ?>
+
+
+
+
+
+
+
+
+ user->hasProjectAccess('ProjectFile', 'remove', $project['id'])): ?>
+
+
+ = $this->url->link(t('Remove'), 'ProjectFile', 'confirm', array('project_id' => $project['id'], 'file_id' => $file['id']), false, 'popover') ?>
+
+
+
+
+ = $this->url->link(t('Download'), 'FileViewer', 'download', array('project_id' => $project['id'], 'file_id' => $file['id'])) ?>
+
+
+
+
+
+ = $this->e($file['user_name'] ?: $file['username']) ?>
+
+
+ = $this->dt->date($file['date']) ?>
+
+
+ = $this->text->bytes($file['size']) ?>
+
+
+
+
+
diff --git a/app/Template/project_overview/information.php b/app/Template/project_overview/information.php
new file mode 100644
index 00000000..12a1317d
--- /dev/null
+++ b/app/Template/project_overview/information.php
@@ -0,0 +1,35 @@
+
+
+
+ 0): ?>
+ = t('Project owner: ') ?>= $this->e($project['owner_name'] ?: $project['owner_username']) ?>
+
+
+
+ $role_name): ?>
+
+
+ = $role_name ?>:
+ = implode(', ', $users[$role]) ?>
+
+
+
+
+
+
+ = t('Start date: ').$this->dt->date($project['start_date']) ?>
+
+
+
+ = t('End date: ').$this->dt->date($project['end_date']) ?>
+
+
+
+ = $this->url->link(t('Public link'), 'board', 'readonly', array('token' => $project['token']), false, '', '', true) ?>
+ = $this->url->link(t('RSS feed'), 'feed', 'project', array('token' => $project['token']), false, '', '', true) ?>
+ = $this->url->link(t('iCal feed'), 'ical', 'project', array('token' => $project['token'])) ?>
+
+
+
diff --git a/app/Template/project_overview/show.php b/app/Template/project_overview/show.php
index b53b1c26..0038d952 100644
--- a/app/Template/project_overview/show.php
+++ b/app/Template/project_overview/show.php
@@ -4,60 +4,10 @@
'filters' => $filters,
)) ?>
-
-
-
- = $column['nb_tasks'] ?>
- = $this->e($column['title']) ?>
-
-
-
-
-
-
-
- = $this->text->markdown($project['description']) ?>
-
-
-
-
-
-
-
- 0): ?>
- = t('Project owner: ') ?>= $this->e($project['owner_name'] ?: $project['owner_username']) ?>
-
-
-
- $role_name): ?>
-
-
- = $role_name ?>:
- = implode(', ', $users[$role]) ?>
-
-
-
-
-
-
- = t('Start date: ').$this->dt->date($project['start_date']) ?>
-
-
-
- = t('End date: ').$this->dt->date($project['end_date']) ?>
-
-
-
- = $this->url->link(t('Public link'), 'board', 'readonly', array('token' => $project['token']), false, '', '', true) ?>
- = $this->url->link(t('RSS feed'), 'feed', 'project', array('token' => $project['token']), false, '', '', true) ?>
- = $this->url->link(t('iCal feed'), 'ical', 'project', array('token' => $project['token'])) ?>
-
-
-
+ = $this->render('project_overview/columns', array('project' => $project)) ?>
+ = $this->render('project_overview/description', array('project' => $project)) ?>
+ = $this->render('project_overview/files', array('project' => $project, 'images' => $images, 'files' => $files)) ?>
+ = $this->render('project_overview/information', array('project' => $project, 'users' => $users, 'roles' => $roles)) ?>
= t('ISO format is always accepted, example: "%s" and "%s"', date('Y-m-d'), date('Y_m_d')) ?>
+ = $this->form->label(t('Date and time format'), 'application_datetime_format') ?> + = $this->form->select('application_datetime_format', $datetime_formats, $values, $errors) ?> + + = $this->form->label(t('Time format'), 'application_time_format') ?> + = $this->form->select('application_time_format', $time_formats, $values, $errors) ?> + = $this->form->checkbox('password_reset', t('Enable "Forget Password"'), 1, $values['password_reset'] == 1) ?> = $this->form->label(t('Custom Stylesheet'), 'application_stylesheet') ?> diff --git a/app/Template/event/events.php b/app/Template/event/events.php index aec0b29e..bbb01be4 100644 --- a/app/Template/event/events.php +++ b/app/Template/event/events.php @@ -14,7 +14,7 @@ text->contains($event['event_name'], 'comment')): ?> - = dt('%B %e, %Y at %k:%M %p', $event['date_creation']) ?> + = $this->dt->datetime($event['date_creation']) ?>