diff options
28 files changed, 400 insertions, 258 deletions
@@ -6,6 +6,7 @@ New features: * Added automated action to change task color based on the priority * Added support for LDAP Posix Groups (OpenLDAP with memberUid) * Added support for LDAP user photo attribute (Avatar image) +* Added support for language LDAP attribute * Search in activity stream * Search in comments * Search by task creator diff --git a/app/Api/App.php b/app/Api/App.php index 635f1ce2..1c4737c0 100644 --- a/app/Api/App.php +++ b/app/Api/App.php @@ -12,7 +12,7 @@ class App extends \Kanboard\Core\Base { public function getTimezone() { - return $this->config->get('application_timezone'); + return $this->timezone->getCurrentTimezone(); } public function getVersion() diff --git a/app/Controller/Config.php b/app/Controller/Config.php index a1b8c2af..021534cf 100644 --- a/app/Controller/Config.php +++ b/app/Controller/Config.php @@ -42,7 +42,7 @@ class Config extends Base } if ($this->config->save($values)) { - $this->config->reload(); + $this->language->loadCurrentLanguage(); $this->flash->success(t('Settings saved successfully.')); } else { $this->flash->failure(t('Unable to save your settings.')); @@ -90,8 +90,8 @@ class Config extends Base $this->common('application'); $this->response->html($this->helper->layout->config('config/application', array( - 'languages' => $this->config->getLanguages(), - 'timezones' => $this->config->getTimezones(), + 'languages' => $this->language->getLanguages(), + 'timezones' => $this->timezone->getTimezones(), 'date_formats' => $this->dateParser->getAvailableFormats($this->dateParser->getDateFormats()), 'datetime_formats' => $this->dateParser->getAvailableFormats($this->dateParser->getDateTimeFormats()), 'time_formats' => $this->dateParser->getAvailableFormats($this->dateParser->getTimeFormats()), diff --git a/app/Controller/Currency.php b/app/Controller/Currency.php index ecaa9834..3e0de905 100644 --- a/app/Controller/Currency.php +++ b/app/Controller/Currency.php @@ -59,7 +59,6 @@ class Currency extends Base $values = $this->request->getValues(); if ($this->config->save($values)) { - $this->config->reload(); $this->flash->success(t('Settings saved successfully.')); } else { $this->flash->failure(t('Unable to save your settings.')); diff --git a/app/Controller/Doc.php b/app/Controller/Doc.php index 00b9e585..219ef8ad 100644 --- a/app/Controller/Doc.php +++ b/app/Controller/Doc.php @@ -20,7 +20,7 @@ class Doc extends Base $page = 'index'; } - if ($this->config->getCurrentLanguage() === 'fr_FR') { + if ($this->language->getCurrentLanguage() === 'fr_FR') { $filename = __DIR__.'/../../doc/fr/' . $page . '.markdown'; } else { $filename = __DIR__ . '/../../doc/' . $page . '.markdown'; @@ -83,7 +83,7 @@ class Doc extends Base */ public function replaceImageUrl(array $matches) { - if ($this->config->getCurrentLanguage() === 'fr_FR') { + if ($this->language->getCurrentLanguage() === 'fr_FR') { return '('.$this->helper->url->base().'doc/fr/'.$matches[1].')'; } diff --git a/app/Controller/User.php b/app/Controller/User.php index f7d7d2e0..4caed1e6 100644 --- a/app/Controller/User.php +++ b/app/Controller/User.php @@ -67,8 +67,8 @@ class User extends Base $is_remote = $this->request->getIntegerParam('remote') == 1 || (isset($values['is_ldap_user']) && $values['is_ldap_user'] == 1); $this->response->html($this->helper->layout->app($is_remote ? 'user/create_remote' : 'user/create_local', array( - 'timezones' => $this->config->getTimezones(true), - 'languages' => $this->config->getLanguages(true), + 'timezones' => $this->timezone->getTimezones(true), + 'languages' => $this->language->getLanguages(true), 'roles' => $this->role->getApplicationRoles(), 'projects' => $this->project->getList(), 'errors' => $errors, @@ -121,8 +121,8 @@ class User extends Base $user = $this->getUser(); $this->response->html($this->helper->layout->user('user/show', array( 'user' => $user, - 'timezones' => $this->config->getTimezones(true), - 'languages' => $this->config->getLanguages(true), + 'timezones' => $this->timezone->getTimezones(true), + 'languages' => $this->language->getLanguages(true), ))); } @@ -247,7 +247,7 @@ class User extends Base $this->response->html($this->helper->layout->user('user/integrations', array( 'user' => $user, - 'values' => $this->userMetadata->getall($user['id']), + 'values' => $this->userMetadata->getAll($user['id']), ))); } @@ -365,8 +365,8 @@ class User extends Base 'values' => $values, 'errors' => $errors, 'user' => $user, - 'timezones' => $this->config->getTimezones(true), - 'languages' => $this->config->getLanguages(true), + 'timezones' => $this->timezone->getTimezones(true), + 'languages' => $this->language->getLanguages(true), 'roles' => $this->role->getApplicationRoles(), ))); } diff --git a/app/Core/Base.php b/app/Core/Base.php index c065ea2a..39a8ccd6 100644 --- a/app/Core/Base.php +++ b/app/Core/Base.php @@ -65,6 +65,7 @@ use Pimple\Container; * @property \Kanboard\Model\ProjectFile $projectFile * @property \Kanboard\Model\Group $group * @property \Kanboard\Model\GroupMember $groupMember + * @property \Kanboard\Model\Language $language * @property \Kanboard\Model\LastLogin $lastLogin * @property \Kanboard\Model\Link $link * @property \Kanboard\Model\Notification $notification @@ -95,6 +96,7 @@ use Pimple\Container; * @property \Kanboard\Model\TaskPosition $taskPosition * @property \Kanboard\Model\TaskStatus $taskStatus * @property \Kanboard\Model\TaskMetadata $taskMetadata + * @property \Kanboard\Model\Timezone $timezone * @property \Kanboard\Model\Transition $transition * @property \Kanboard\Model\User $user * @property \Kanboard\Model\UserLocking $userLocking diff --git a/app/Core/Ldap/User.php b/app/Core/Ldap/User.php index d0036ea7..c54aa1ac 100644 --- a/app/Core/Ldap/User.php +++ b/app/Core/Ldap/User.php @@ -146,7 +146,8 @@ class User $entry->getFirstValue($this->getAttributeEmail()), $this->getRole($groupIds), $groupIds, - $entry->getFirstValue($this->getAttributePhoto()) + $entry->getFirstValue($this->getAttributePhoto()), + $entry->getFirstValue($this->getAttributeLanguage()) ); } @@ -166,6 +167,7 @@ class User $this->getAttributeEmail(), $this->getAttributeGroup(), $this->getAttributePhoto(), + $this->getAttributeLanguage(), ))); } @@ -237,6 +239,17 @@ class User } /** + * Get LDAP language attribute + * + * @access public + * @return string + */ + public function getAttributeLanguage() + { + return strtolower(LDAP_USER_ATTRIBUTE_LANGUAGE); + } + + /** * Get LDAP Group User filter * * @access public diff --git a/app/Formatter/TaskCalendarFormatter.php b/app/Formatter/TaskCalendarFormatter.php index 60b9a062..ca0d5c05 100644 --- a/app/Formatter/TaskCalendarFormatter.php +++ b/app/Formatter/TaskCalendarFormatter.php @@ -44,7 +44,7 @@ class TaskCalendarFormatter extends BaseTaskCalendarFormatter implements Formatt foreach ($this->query->findAll() as $task) { $events[] = array( - 'timezoneParam' => $this->config->getCurrentTimezone(), + 'timezoneParam' => $this->timezone->getCurrentTimezone(), 'id' => $task['id'], 'title' => t('#%d', $task['id']).' '.$task['title'], 'backgroundColor' => $this->color->getBackgroundColor($task['color_id']), diff --git a/app/Helper/AppHelper.php b/app/Helper/AppHelper.php index e6f6412d..1f497929 100644 --- a/app/Helper/AppHelper.php +++ b/app/Helper/AppHelper.php @@ -90,7 +90,7 @@ class AppHelper extends Base */ public function jsLang() { - return $this->config->getJsLanguageCode(); + return $this->language->getJsLanguageCode(); } /** @@ -101,7 +101,7 @@ class AppHelper extends Base */ public function getTimezone() { - return $this->config->getCurrentTimezone(); + return $this->timezone->getCurrentTimezone(); } /** diff --git a/app/Model/Config.php b/app/Model/Config.php index 0c363fb0..1b14efa1 100644 --- a/app/Model/Config.php +++ b/app/Model/Config.php @@ -2,7 +2,6 @@ namespace Kanboard\Model; -use Kanboard\Core\Translator; use Kanboard\Core\Security\Token; /** @@ -14,162 +13,7 @@ use Kanboard\Core\Security\Token; class Config extends Setting { /** - * Get available timezones - * - * @access public - * @param boolean $prepend Prepend a default value - * @return array - */ - public function getTimezones($prepend = false) - { - $timezones = timezone_identifiers_list(); - $listing = array_combine(array_values($timezones), $timezones); - - if ($prepend) { - return array('' => t('Application default')) + $listing; - } - - return $listing; - } - - /** - * Get current timezone - * - * @access public - * @return string - */ - public function getCurrentTimezone() - { - if ($this->userSession->isLogged() && ! empty($this->sessionStorage->user['timezone'])) { - return $this->sessionStorage->user['timezone']; - } - - return $this->get('application_timezone', 'UTC'); - } - - /** - * Set timezone - * - * @access public - */ - public function setupTimezone() - { - date_default_timezone_set($this->getCurrentTimezone()); - } - - /** - * Get available languages - * - * @access public - * @param boolean $prepend Prepend a default value - * @return array - */ - public function getLanguages($prepend = false) - { - // Sorted by value - $languages = array( - 'id_ID' => 'Bahasa Indonesia', - 'bs_BA' => 'Bosanski', - 'cs_CZ' => 'Čeština', - 'da_DK' => 'Dansk', - 'de_DE' => 'Deutsch', - 'en_US' => 'English', - 'es_ES' => 'Español', - 'fr_FR' => 'Français', - 'el_GR' => 'Grec', - 'it_IT' => 'Italiano', - 'hu_HU' => 'Magyar', - 'my_MY' => 'Melayu', - 'nl_NL' => 'Nederlands', - 'nb_NO' => 'Norsk', - 'pl_PL' => 'Polski', - 'pt_PT' => 'Português', - 'pt_BR' => 'Português (Brasil)', - 'ru_RU' => 'Русский', - 'sr_Latn_RS' => 'Srpski', - 'fi_FI' => 'Suomi', - 'sv_SE' => 'Svenska', - 'tr_TR' => 'Türkçe', - 'ko_KR' => '한국어', - 'zh_CN' => '中文(简体)', - 'ja_JP' => '日本語', - 'th_TH' => 'ไทย', - ); - - if ($prepend) { - return array('' => t('Application default')) + $languages; - } - - return $languages; - } - - /** - * Get javascript language code - * - * @access public - * @return string - */ - public function getJsLanguageCode() - { - $languages = array( - 'cs_CZ' => 'cs', - 'da_DK' => 'da', - 'de_DE' => 'de', - 'en_US' => 'en', - 'es_ES' => 'es', - 'fr_FR' => 'fr', - 'it_IT' => 'it', - 'hu_HU' => 'hu', - 'nl_NL' => 'nl', - 'nb_NO' => 'nb', - 'pl_PL' => 'pl', - 'pt_PT' => 'pt', - 'pt_BR' => 'pt-br', - 'ru_RU' => 'ru', - 'sr_Latn_RS' => 'sr', - 'fi_FI' => 'fi', - 'sv_SE' => 'sv', - 'tr_TR' => 'tr', - 'ko_KR' => 'ko', - 'zh_CN' => 'zh-cn', - 'ja_JP' => 'ja', - 'th_TH' => 'th', - 'id_ID' => 'id', - 'el_GR' => 'el', - ); - - $lang = $this->getCurrentLanguage(); - - return isset($languages[$lang]) ? $languages[$lang] : 'en'; - } - - /** - * Get current language - * - * @access public - * @return string - */ - public function getCurrentLanguage() - { - if ($this->userSession->isLogged() && ! empty($this->sessionStorage->user['language'])) { - return $this->sessionStorage->user['language']; - } - - return $this->get('application_language', 'en_US'); - } - - /** - * Load translations - * - * @access public - */ - public function setupTranslations() - { - Translator::load($this->getCurrentLanguage()); - } - - /** - * Get a config variable from the session or the database + * Get a config variable with in-memory caching * * @access public * @param string $name Parameter name @@ -183,16 +27,6 @@ class Config extends Setting } /** - * Reload settings in the session and the translations - * - * @access public - */ - public function reload() - { - $this->setupTranslations(); - } - - /** * Optimize the Sqlite database * * @access public @@ -200,7 +34,7 @@ class Config extends Setting */ public function optimizeDatabase() { - return $this->db->getconnection()->exec('VACUUM'); + return $this->db->getConnection()->exec('VACUUM'); } /** diff --git a/app/Model/Language.php b/app/Model/Language.php new file mode 100644 index 00000000..441771e0 --- /dev/null +++ b/app/Model/Language.php @@ -0,0 +1,178 @@ +<?php + +namespace Kanboard\Model; + +use Kanboard\Core\Translator; + +/** + * Class Language + * + * @package Kanboard\Model + * @author Frederic Guillot + */ +class Language extends Base +{ + /** + * Get all language codes + * + * @static + * @access public + * @return string[] + */ + public static function getCodes() + { + return array( + 'id_ID', + 'bs_BA', + 'cs_CZ', + 'da_DK', + 'de_DE', + 'en_US', + 'es_ES', + 'fr_FR', + 'el_GR', + 'it_IT', + 'hu_HU', + 'my_MY', + 'nl_NL', + 'nb_NO', + 'pl_PL', + 'pt_PT', + 'pt_BR', + 'ru_RU', + 'sr_Latn_RS', + 'fi_FI', + 'sv_SE', + 'tr_TR', + 'ko_KR', + 'zh_CN', + 'ja_JP', + 'th_TH', + ); + } + + /** + * Find language code + * + * @static + * @access public + * @param string $code + * @return string + */ + public static function findCode($code) + { + $code = str_replace('-', '_', $code); + return in_array($code, self::getCodes()) ? $code : ''; + } + + /** + * Get available languages + * + * @access public + * @param boolean $prepend Prepend a default value + * @return array + */ + public function getLanguages($prepend = false) + { + // Sorted by value + $languages = array( + 'id_ID' => 'Bahasa Indonesia', + 'bs_BA' => 'Bosanski', + 'cs_CZ' => 'Čeština', + 'da_DK' => 'Dansk', + 'de_DE' => 'Deutsch', + 'en_US' => 'English', + 'es_ES' => 'Español', + 'fr_FR' => 'Français', + 'el_GR' => 'Grec', + 'it_IT' => 'Italiano', + 'hu_HU' => 'Magyar', + 'my_MY' => 'Melayu', + 'nl_NL' => 'Nederlands', + 'nb_NO' => 'Norsk', + 'pl_PL' => 'Polski', + 'pt_PT' => 'Português', + 'pt_BR' => 'Português (Brasil)', + 'ru_RU' => 'Русский', + 'sr_Latn_RS' => 'Srpski', + 'fi_FI' => 'Suomi', + 'sv_SE' => 'Svenska', + 'tr_TR' => 'Türkçe', + 'ko_KR' => '한국어', + 'zh_CN' => '中文(简体)', + 'ja_JP' => '日本語', + 'th_TH' => 'ไทย', + ); + + if ($prepend) { + return array('' => t('Application default')) + $languages; + } + + return $languages; + } + + /** + * Get javascript language code + * + * @access public + * @return string + */ + public function getJsLanguageCode() + { + $languages = array( + 'cs_CZ' => 'cs', + 'da_DK' => 'da', + 'de_DE' => 'de', + 'en_US' => 'en', + 'es_ES' => 'es', + 'fr_FR' => 'fr', + 'it_IT' => 'it', + 'hu_HU' => 'hu', + 'nl_NL' => 'nl', + 'nb_NO' => 'nb', + 'pl_PL' => 'pl', + 'pt_PT' => 'pt', + 'pt_BR' => 'pt-br', + 'ru_RU' => 'ru', + 'sr_Latn_RS' => 'sr', + 'fi_FI' => 'fi', + 'sv_SE' => 'sv', + 'tr_TR' => 'tr', + 'ko_KR' => 'ko', + 'zh_CN' => 'zh-cn', + 'ja_JP' => 'ja', + 'th_TH' => 'th', + 'id_ID' => 'id', + 'el_GR' => 'el', + ); + + $lang = $this->getCurrentLanguage(); + + return isset($languages[$lang]) ? $languages[$lang] : 'en'; + } + + /** + * Get current language + * + * @access public + * @return string + */ + public function getCurrentLanguage() + { + if ($this->userSession->isLogged() && ! empty($this->sessionStorage->user['language'])) { + return $this->sessionStorage->user['language']; + } + + return $this->config->get('application_language', 'en_US'); + } + + /** + * Load translations for the current language + * + * @access public + */ + public function loadCurrentLanguage() + { + Translator::load($this->getCurrentLanguage()); + } +} diff --git a/app/Model/Timezone.php b/app/Model/Timezone.php new file mode 100644 index 00000000..c6b33736 --- /dev/null +++ b/app/Model/Timezone.php @@ -0,0 +1,56 @@ +<?php + +namespace Kanboard\Model; + +/** + * Class Timezone + * + * @package Kanboard\Model + * @author Frederic Guillot + */ +class Timezone extends Base +{ + /** + * Get available timezones + * + * @access public + * @param boolean $prepend Prepend a default value + * @return array + */ + public function getTimezones($prepend = false) + { + $timezones = timezone_identifiers_list(); + $listing = array_combine(array_values($timezones), $timezones); + + if ($prepend) { + return array('' => t('Application default')) + $listing; + } + + return $listing; + } + + /** + * Get current timezone + * + * @access public + * @return string + */ + public function getCurrentTimezone() + { + if ($this->userSession->isLogged() && ! empty($this->sessionStorage->user['timezone'])) { + return $this->sessionStorage->user['timezone']; + } + + return $this->config->get('application_timezone', 'UTC'); + } + + /** + * Set timezone + * + * @access public + */ + public function setCurrentTimezone() + { + date_default_timezone_set($this->getCurrentTimezone()); + } +} diff --git a/app/Model/UserNotification.php b/app/Model/UserNotification.php index 7795da2e..fcd1761b 100644 --- a/app/Model/UserNotification.php +++ b/app/Model/UserNotification.php @@ -54,7 +54,7 @@ class UserNotification extends Base } // Restore locales - $this->config->setupTranslations(); + $this->language->loadCurrentLanguage(); } /** diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php index 54e2ad78..31e3a20b 100644 --- a/app/ServiceProvider/ClassProvider.php +++ b/app/ServiceProvider/ClassProvider.php @@ -35,6 +35,7 @@ class ClassProvider implements ServiceProviderInterface 'CustomFilter', 'Group', 'GroupMember', + 'Language', 'LastLogin', 'Link', 'Notification', @@ -66,6 +67,7 @@ class ClassProvider implements ServiceProviderInterface 'TaskPosition', 'TaskStatus', 'TaskMetadata', + 'Timezone', 'Transition', 'User', 'UserLocking', diff --git a/app/Subscriber/BootstrapSubscriber.php b/app/Subscriber/BootstrapSubscriber.php index ef0215f3..7e341601 100644 --- a/app/Subscriber/BootstrapSubscriber.php +++ b/app/Subscriber/BootstrapSubscriber.php @@ -16,8 +16,8 @@ class BootstrapSubscriber extends BaseSubscriber implements EventSubscriberInter public function execute() { $this->logger->debug('Subscriber executed: '.__METHOD__); - $this->config->setupTranslations(); - $this->config->setupTimezone(); + $this->language->loadCurrentLanguage(); + $this->timezone->setCurrentTimezone(); $this->actionManager->attachEvents(); if ($this->userSession->isLogged()) { diff --git a/app/User/LdapUserProvider.php b/app/User/LdapUserProvider.php index 3e2dcd2b..74cf4cd5 100644 --- a/app/User/LdapUserProvider.php +++ b/app/User/LdapUserProvider.php @@ -3,6 +3,7 @@ namespace Kanboard\User; use Kanboard\Core\User\UserProviderInterface; +use Kanboard\Model\Language; /** * LDAP User Provider @@ -69,6 +70,14 @@ class LdapUserProvider implements UserProviderInterface protected $photo = ''; /** + * User language + * + * @access protected + * @var string + */ + protected $language = ''; + + /** * Constructor * * @access public @@ -80,7 +89,7 @@ class LdapUserProvider implements UserProviderInterface * @param string[] $groupIds * @param string $photo */ - public function __construct($dn, $username, $name, $email, $role, array $groupIds, $photo = '') + public function __construct($dn, $username, $name, $email, $role, array $groupIds, $photo = '', $language = '') { $this->dn = $dn; $this->username = $username; @@ -89,6 +98,7 @@ class LdapUserProvider implements UserProviderInterface $this->role = $role; $this->groupIds = $groupIds; $this->photo = $photo; + $this->language = $language; } /** @@ -198,9 +208,13 @@ class LdapUserProvider implements UserProviderInterface */ public function getExtraAttributes() { - return array( - 'is_ldap_user' => 1, - ); + $attributes = array('is_ldap_user' => 1); + + if (! empty($this->language)) { + $attributes['language'] = Language::findCode($this->language); + } + + return $attributes; } /** diff --git a/app/constants.php b/app/constants.php index 6f30af7f..5e1e886f 100644 --- a/app/constants.php +++ b/app/constants.php @@ -65,6 +65,7 @@ defined('LDAP_USER_ATTRIBUTE_FULLNAME') or define('LDAP_USER_ATTRIBUTE_FULLNAME' defined('LDAP_USER_ATTRIBUTE_EMAIL') or define('LDAP_USER_ATTRIBUTE_EMAIL', 'mail'); defined('LDAP_USER_ATTRIBUTE_GROUPS') or define('LDAP_USER_ATTRIBUTE_GROUPS', 'memberof'); defined('LDAP_USER_ATTRIBUTE_PHOTO') or define('LDAP_USER_ATTRIBUTE_PHOTO', ''); +defined('LDAP_USER_ATTRIBUTE_LANGUAGE') or define('LDAP_USER_ATTRIBUTE_LANGUAGE', ''); defined('LDAP_USER_CREATION') or define('LDAP_USER_CREATION', true); defined('LDAP_GROUP_ADMIN_DN') or define('LDAP_GROUP_ADMIN_DN', ''); diff --git a/config.default.php b/config.default.php index abc928a9..e3f8932c 100644 --- a/config.default.php +++ b/config.default.php @@ -120,6 +120,10 @@ define('LDAP_USER_ATTRIBUTE_GROUPS', 'memberof'); // LDAP attribute for user avatar image: thumbnailPhoto or jpegPhoto define('LDAP_USER_ATTRIBUTE_PHOTO', ''); +// LDAP attribute for user language, example: 'preferredlanguage' +// Put an empty string to disable language sync +define('LDAP_USER_ATTRIBUTE_LANGUAGE', ''); + // Allow automatic LDAP user creation define('LDAP_USER_CREATION', true); diff --git a/doc/config.markdown b/doc/config.markdown index a8df887f..0e3c3198 100644 --- a/doc/config.markdown +++ b/doc/config.markdown @@ -152,6 +152,10 @@ define('LDAP_USER_ATTRIBUTE_GROUPS', 'memberof'); // LDAP attribute for user avatar image: thumbnailPhoto or jpegPhoto define('LDAP_USER_ATTRIBUTE_PHOTO', ''); +// LDAP attribute for user language, example: 'preferredlanguage' +// Put an empty string to disable language sync +define('LDAP_USER_ATTRIBUTE_LANGUAGE', ''); + // Allow automatic LDAP user creation define('LDAP_USER_CREATION', true); diff --git a/doc/ldap-parameters.markdown b/doc/ldap-parameters.markdown index c18c2b06..80decc67 100644 --- a/doc/ldap-parameters.markdown +++ b/doc/ldap-parameters.markdown @@ -21,6 +21,7 @@ Here is the list of available LDAP parameters: | `LDAP_USER_ATTRIBUTE_EMAIL` | mail | LDAP attribute for user email | | `LDAP_USER_ATTRIBUTE_GROUPS` | memberof | LDAP attribute to find groups in user profile | | `LDAP_USER_ATTRIBUTE_PHOTO` | Empty | LDAP attribute to find user photo (jpegPhoto or thumbnailPhoto | +| `LDAP_USER_ATTRIBUTE_LANGUAGE` | Empty | LDAP attribute for user language (preferredlanguage), the accepted language format is "fr-FR" | | `LDAP_USER_CREATION` | true | Enable automatic LDAP user creation | | `LDAP_GROUP_ADMIN_DN` | Empty | LDAP DN for administrators (Example: "CN=Kanboard-Admins,CN=Users,DC=kanboard,DC=local") | | `LDAP_GROUP_MANAGER_DN` | Empty | LDAP DN for managers (Example: "CN=Kanboard Managers,CN=Users,DC=kanboard,DC=local") | diff --git a/doc/plugin-registration.markdown b/doc/plugin-registration.markdown index f212fc2e..03b3c841 100644 --- a/doc/plugin-registration.markdown +++ b/doc/plugin-registration.markdown @@ -86,7 +86,7 @@ Plugin can be translated in the same way as the rest of the application. You mus ```php $this->on('app.bootstrap', function($container) { - Translator::load($container['config']->getCurrentLanguage(), __DIR__.'/Locale'); + Translator::load($container['language']->getCurrentLanguage(), __DIR__.'/Locale'); }); ``` diff --git a/doc/translations.markdown b/doc/translations.markdown index 00707e1c..074d9ae3 100644 --- a/doc/translations.markdown +++ b/doc/translations.markdown @@ -16,7 +16,7 @@ How to translate Kanboard to a new language? 1. Make a new directory: `app/Locale/xx_XX` for example `app/Locale/fr_CA` for French Canadian 2. Create a new file for the translation: `app/Locale/xx_XX/translations.php` 3. Use the content of the French locales and replace the values -4. Inside the file `app/Model/Config.php`, add a new entry for your translation inside the function `getLanguages()` +4. Update the file `app/Model/Language.php` 5. Check with your local installation of Kanboard if everything is OK 6. Send a [pull-request with Github](https://help.github.com/articles/using-pull-requests/) diff --git a/tests/integration.mysql.xml b/tests/integration.mysql.xml index 30769371..9d87f77e 100644 --- a/tests/integration.mysql.xml +++ b/tests/integration.mysql.xml @@ -13,5 +13,8 @@ <const name="DB_USERNAME" value="root" /> <const name="DB_PASSWORD" value="" /> <const name="DB_PORT" value="" /> + <const name="DB_SSL_KEY" value="" /> + <const name="DB_SSL_CA" value="" /> + <const name="DB_SSL_CERT" value="" /> </php> -</phpunit>
\ No newline at end of file +</phpunit> diff --git a/tests/units/Model/ConfigTest.php b/tests/units/Model/ConfigTest.php index 6ccdbef9..ad74ad50 100644 --- a/tests/units/Model/ConfigTest.php +++ b/tests/units/Model/ConfigTest.php @@ -6,66 +6,6 @@ use Kanboard\Model\Config; class ConfigTest extends Base { - public function testGetTimezones() - { - $configModel = new Config($this->container); - $this->assertNotEmpty($configModel->getTimezones()); - $this->assertArrayHasKey('Europe/Paris', $configModel->getTimezones()); - $this->assertContains('Europe/Paris', $configModel->getTimezones()); - $this->assertArrayNotHasKey('', $configModel->getTimezones()); - - $this->assertArrayHasKey('', $configModel->getTimezones(true)); - $this->assertContains('Application default', $configModel->getTimezones(true)); - } - - public function testGetLanguages() - { - $configModel = new Config($this->container); - $this->assertNotEmpty($configModel->getLanguages()); - $this->assertArrayHasKey('fr_FR', $configModel->getLanguages()); - $this->assertContains('Français', $configModel->getLanguages()); - $this->assertArrayNotHasKey('', $configModel->getLanguages()); - - $this->assertArrayHasKey('', $configModel->getLanguages(true)); - $this->assertContains('Application default', $configModel->getLanguages(true)); - } - - public function testGetJsLanguage() - { - $configModel = new Config($this->container); - $this->assertEquals('en', $configModel->getJsLanguageCode()); - - $this->container['sessionStorage']->user = array('language' => 'fr_FR'); - $this->assertEquals('fr', $configModel->getJsLanguageCode()); - - $this->container['sessionStorage']->user = array('language' => 'xx_XX'); - $this->assertEquals('en', $configModel->getJsLanguageCode()); - } - - public function testGetCurrentLanguage() - { - $configModel = new Config($this->container); - $this->assertEquals('en_US', $configModel->getCurrentLanguage()); - - $this->container['sessionStorage']->user = array('language' => 'fr_FR'); - $this->assertEquals('fr_FR', $configModel->getCurrentLanguage()); - - $this->container['sessionStorage']->user = array('language' => 'xx_XX'); - $this->assertEquals('xx_XX', $configModel->getCurrentLanguage()); - } - - public function testGetCurrentTimezone() - { - $configModel = new Config($this->container); - $this->assertEquals('UTC', $configModel->getCurrentTimezone()); - - $this->container['sessionStorage']->user = array('timezone' => 'Europe/Paris'); - $this->assertEquals('Europe/Paris', $configModel->getCurrentTimezone()); - - $this->container['sessionStorage']->user = array('timezone' => 'Something'); - $this->assertEquals('Something', $configModel->getCurrentTimezone()); - } - public function testRegenerateToken() { $configModel = new Config($this->container); diff --git a/tests/units/Model/LanguageTest.php b/tests/units/Model/LanguageTest.php new file mode 100644 index 00000000..dff98a83 --- /dev/null +++ b/tests/units/Model/LanguageTest.php @@ -0,0 +1,58 @@ +<?php + +use Kanboard\Model\Language; + +require_once __DIR__.'/../Base.php'; + +class LanguageTest extends Base +{ + public function testGetCodes() + { + $codes = Language::getCodes(); + $this->assertContains('fr_FR', $codes); + $this->assertContains('en_US', $codes); + } + + public function testFindCode() + { + $this->assertSame('', Language::findCode('xx-XX')); + $this->assertSame('fr_FR', Language::findCode('fr-FR')); + $this->assertSame('en_US', Language::findCode('en-US')); + } + + public function testGetJsLanguage() + { + $languageModel = new Language($this->container); + $this->assertEquals('en', $languageModel->getJsLanguageCode()); + + $this->container['sessionStorage']->user = array('language' => 'fr_FR'); + $this->assertEquals('fr', $languageModel->getJsLanguageCode()); + + $this->container['sessionStorage']->user = array('language' => 'xx_XX'); + $this->assertEquals('en', $languageModel->getJsLanguageCode()); + } + + public function testGetCurrentLanguage() + { + $languageModel = new Language($this->container); + $this->assertEquals('en_US', $languageModel->getCurrentLanguage()); + + $this->container['sessionStorage']->user = array('language' => 'fr_FR'); + $this->assertEquals('fr_FR', $languageModel->getCurrentLanguage()); + + $this->container['sessionStorage']->user = array('language' => 'xx_XX'); + $this->assertEquals('xx_XX', $languageModel->getCurrentLanguage()); + } + + public function testGetLanguages() + { + $languageModel = new Language($this->container); + $this->assertNotEmpty($languageModel->getLanguages()); + $this->assertArrayHasKey('fr_FR', $languageModel->getLanguages()); + $this->assertContains('Français', $languageModel->getLanguages()); + $this->assertArrayNotHasKey('', $languageModel->getLanguages()); + + $this->assertArrayHasKey('', $languageModel->getLanguages(true)); + $this->assertContains('Application default', $languageModel->getLanguages(true)); + } +} diff --git a/tests/units/Model/ProjectTest.php b/tests/units/Model/ProjectTest.php index b3dcd2e5..6c50744b 100644 --- a/tests/units/Model/ProjectTest.php +++ b/tests/units/Model/ProjectTest.php @@ -15,10 +15,10 @@ class ProjectTest extends Base { public function testCreationForAllLanguages() { - $c = new Config($this->container); $p = new Project($this->container); - foreach ($c->getLanguages() as $locale => $language) { + foreach ($this->container['language']->getLanguages() as $locale => $language) { + Translator::unload(); Translator::load($locale); $this->assertNotFalse($p->create(array('name' => 'UnitTest '.$locale)), 'Unable to create project with '.$locale.':'.$language); } diff --git a/tests/units/Model/TimezoneTest.php b/tests/units/Model/TimezoneTest.php new file mode 100644 index 00000000..ac2cd6a1 --- /dev/null +++ b/tests/units/Model/TimezoneTest.php @@ -0,0 +1,32 @@ +<?php + +require_once __DIR__.'/../Base.php'; + +use Kanboard\Model\Timezone; + +class TimezoneTest extends Base +{ + public function testGetTimezones() + { + $timezoneModel = new Timezone($this->container); + $this->assertNotEmpty($timezoneModel->getTimezones()); + $this->assertArrayHasKey('Europe/Paris', $timezoneModel->getTimezones()); + $this->assertContains('Europe/Paris', $timezoneModel->getTimezones()); + $this->assertArrayNotHasKey('', $timezoneModel->getTimezones()); + + $this->assertArrayHasKey('', $timezoneModel->getTimezones(true)); + $this->assertContains('Application default', $timezoneModel->getTimezones(true)); + } + + public function testGetCurrentTimezone() + { + $timezoneModel = new Timezone($this->container); + $this->assertEquals('UTC', $timezoneModel->getCurrentTimezone()); + + $this->container['sessionStorage']->user = array('timezone' => 'Europe/Paris'); + $this->assertEquals('Europe/Paris', $timezoneModel->getCurrentTimezone()); + + $this->container['sessionStorage']->user = array('timezone' => 'Something'); + $this->assertEquals('Something', $timezoneModel->getCurrentTimezone()); + } +} |