From 0684518bf80ff1b7da4bbfe7a75931d3164f225f Mon Sep 17 00:00:00 2001 From: Fuze Date: Sat, 23 Sep 2017 18:15:37 +0300 Subject: [PATCH] =?UTF-8?q?=D0=BF=D1=80=D0=B8=20=D0=BE=D0=B1=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B8=20=D0=BF=D0=B0=D0=BA=D0=B5?= =?UTF-8?q?=D1=82=D0=BE=D0=B2,=20=D1=83=D1=87=D0=B8=D1=82=D1=8B=D0=B2?= =?UTF-8?q?=D0=B0=D0=B5=D1=82=D1=81=D1=8F=20addon=5Fid,=20=D0=B0=D0=BA?= =?UTF-8?q?=D1=82=D1=83=D0=B0=D0=BB=D0=B8=D0=B7=D0=B8=D1=80=D1=83=D1=8E?= =?UTF-8?q?=D1=82=D1=81=D1=8F=20=D1=84=D0=B0=D0=B9=D0=BB=D1=8B=20=D0=B4?= =?UTF-8?q?=D0=BE=D0=BF=D0=BE=D0=BB=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F.=20?= =?UTF-8?q?=D0=92=20=D0=BD=D0=B0=D1=81=D1=82=D1=80=D0=BE=D0=B9=D0=BA=D0=B0?= =?UTF-8?q?=D1=85=20=D0=BF=D0=BE=D0=BB=D0=B5=D0=B9=20=D0=B8=D0=B7=D0=BE?= =?UTF-8?q?=D0=B1=D1=80=D0=B0=D0=B6=D0=B5=D0=BD=D0=B8=D0=B9=20=D0=BA=D1=80?= =?UTF-8?q?=D0=BE=D0=BC=D0=B5=20=D0=BD=D0=B0=D0=B7=D0=B2=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B9=20=D0=BF=D1=80=D0=B5=D1=81=D0=B5=D1=82=D0=BE=D0=B2=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=BA=D0=B0=D0=B7=D1=8B=D0=B2=D0=B0=D1=8E=D1=82?= =?UTF-8?q?=D1=81=D1=8F=20=D0=B8=20=D0=B8=D1=85=20=D0=BF=D0=B0=D1=80=D0=B0?= =?UTF-8?q?=D0=BC=D0=B5=D1=82=D1=80=D1=8B.=20=D0=92=20=D0=BF=D0=BE=D0=BB?= =?UTF-8?q?=D1=8F=D1=85=20=D0=BC=D0=BE=D0=B6=D0=BD=D0=BE=20=D1=80=D0=B5?= =?UTF-8?q?=D0=B0=D0=BB=D0=B8=D0=B7=D0=BE=D0=B2=D1=8B=D0=B2=D0=B0=D1=82?= =?UTF-8?q?=D1=8C=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D1=8B=20hookAfterAdd,?= =?UTF-8?q?=20hookAfterUpdate=20=D0=B8=20hookAfterRemove,=20=D0=BA=D0=BE?= =?UTF-8?q?=D1=82=D0=BE=D1=80=D1=8B=D0=B5=20=D0=B2=D1=8B=D0=B7=D1=8B=D0=B2?= =?UTF-8?q?=D0=B0=D1=8E=D1=82=D1=81=D1=8F=20=D1=81=D0=BE=D0=BE=D1=82=D0=B2?= =?UTF-8?q?=D0=B5=D1=82=D1=81=D1=82=D0=B2=D0=B5=D0=BD=D0=BD=D0=BE=20=D0=BF?= =?UTF-8?q?=D1=80=D0=B8=20=D1=81=D0=BE=D0=B7=D0=B4=D0=B0=D0=BD=D0=B8=D0=B8?= =?UTF-8?q?/=D1=80=D0=B5=D0=B4=D0=B0=D0=BA=D1=82=D0=B8=D1=80=D0=BE=D0=B2?= =?UTF-8?q?=D0=B0=D0=BD=D0=B8/=D1=83=D0=B4=D0=B0=D0=BB=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B8=20=D0=BF=D0=BE=D0=BB=D1=8F.=20Mobile=20Detect=20=D0=BE?= =?UTF-8?q?=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD=20=D0=B4=D0=BE=20?= =?UTF-8?q?=D0=BA=D1=80=D0=B0=D0=B9=D0=BD=D0=B5=D0=B9=20=D0=B2=D0=B5=D1=80?= =?UTF-8?q?=D1=81=D0=B8=D0=B8.=20PHPMailer=20=D0=BE=D0=B1=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=20=D0=B4=D0=BE=20=D0=BA=D1=80=D0=B0?= =?UTF-8?q?=D0=B9=D0=BD=D0=B5=D0=B9=20=D0=B2=D0=B5=D1=80=D1=81=D0=B8=D0=B8?= =?UTF-8?q?.=20=D0=9C=D0=B5=D0=BB=D0=BA=D0=B8=D0=B5=20=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=BA=D0=B8=20=D0=BF=D0=BE=20=D0=B2=D0=B8=D0=B4=D0=B6?= =?UTF-8?q?=D0=B5=D1=82=D0=B0=D0=BC.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- system/config/version.ini | 4 +- .../admin/actions/install_finish.php | 57 ++++++++-- system/controllers/admin/model.php | 1 + .../hooks/rss_content_controller_form.php | 2 +- system/controllers/content/model.php | 6 ++ .../content/widgets/slider/options.form.php | 2 +- system/controllers/images/model.php | 7 +- system/core/formfield.php | 100 ++++++++++++++++-- system/core/template.php | 3 +- system/fields/image.php | 6 +- system/fields/images.php | 6 +- system/libs/mobile_detect.class.php | 13 +-- system/libs/phpmailer/class.phpmailer.php | 2 +- system/libs/phpmailer/class.pop3.php | 2 +- system/libs/phpmailer/class.smtp.php | 52 ++++++--- .../phpmailer/language/phpmailer.lang-ba.php | 26 +++++ system/libs/strings.helper.php | 16 ++- templates/default/admin.tpl.php | 16 ++- templates/default/widgets/menu/menu.tpl.php | 2 +- .../default/widgets/wrapper_tabbed.tpl.php | 16 ++- 20 files changed, 278 insertions(+), 61 deletions(-) create mode 100644 system/libs/phpmailer/language/phpmailer.lang-ba.php diff --git a/system/config/version.ini b/system/config/version.ini index 8fb2c0919..6f993f6c7 100755 --- a/system/config/version.ini +++ b/system/config/version.ini @@ -1,5 +1,5 @@ [version] major = 2 minor = 8 -build = 1 -date = 20170907 \ No newline at end of file +build = 2 +date = 20170000 \ No newline at end of file diff --git a/system/controllers/admin/actions/install_finish.php b/system/controllers/admin/actions/install_finish.php index 11540a4db..148c0723a 100755 --- a/system/controllers/admin/actions/install_finish.php +++ b/system/controllers/admin/actions/install_finish.php @@ -157,14 +157,34 @@ private function componentUpdate($manifest) { $options = null; } - $model->filterEqual('name', $manifest['package']['name'])->updateFiltered('controllers', array( + $update_data = array( 'title' => $manifest['info']['title'], 'options' => $options, 'author' => (isset($manifest['author']['name']) ? $manifest['author']['name'] : LANG_CP_PACKAGE_NONAME), 'url' => (isset($manifest['author']['url']) ? $manifest['author']['url'] : null), 'version' => $manifest['version']['major'] . '.' . $manifest['version']['minor'] . '.' . $manifest['version']['build'], 'is_backend' => file_exists($controller_root_path.'backend.php') - )); + ); + + $installed_controller = $this->model->getControllerInfo($manifest['package']['name']); + + if(!empty($manifest['contents'])){ + if(!empty($installed_controller['files'])){ + + $update_data['files'] = multi_array_unique(array_merge_recursive($installed_controller['files'], $manifest['contents'])); + + } else { + + $update_data['files'] = $manifest['contents']; + + } + } + + if(!empty($manifest['info']['addon_id'])){ + $update_data['files'] = (int)$manifest['info']['addon_id']; + } + + $model->filterEqual('name', $manifest['package']['name'])->updateFiltered('controllers', $update_data); return 'controllers'; @@ -194,14 +214,39 @@ private function widgetUpdate($manifest) { $model = new cmsModel(); - $model->filterEqual('name', $manifest['package']['name'])-> - filterEqual('controller', $manifest['package']['controller'])-> - updateFiltered('widgets', array( + $update_data = array( 'title' => $manifest['info']['title'], 'author' => (isset($manifest['author']['name']) ? $manifest['author']['name'] : LANG_CP_PACKAGE_NONAME), 'url' => (isset($manifest['author']['url']) ? $manifest['author']['url'] : null), 'version' => $manifest['version']['major'] . '.' . $manifest['version']['minor'] . '.' . $manifest['version']['build'] - )); + ); + + $installed_widget = $model->filterEqual('name', $manifest['package']['name'])-> + filterEqual('controller', $manifest['package']['controller'])-> + getItem('widgets', function($item){ + $item['files'] = cmsModel::yamlToArray($item['files']); + return $item; + }); + + if(!empty($manifest['contents'])){ + if(!empty($installed_widget['files'])){ + + $update_data['files'] = multi_array_unique(array_merge_recursive($installed_widget['files'], $manifest['contents'])); + + } else { + + $update_data['files'] = $manifest['contents']; + + } + } + + if(!empty($manifest['info']['addon_id'])){ + $update_data['files'] = (int)$manifest['info']['addon_id']; + } + + $model->filterEqual('name', $manifest['package']['name'])-> + filterEqual('controller', $manifest['package']['controller'])-> + updateFiltered('widgets', $update_data); return 'widgets'; diff --git a/system/controllers/admin/model.php b/system/controllers/admin/model.php index 842777650..499793bfa 100755 --- a/system/controllers/admin/model.php +++ b/system/controllers/admin/model.php @@ -29,6 +29,7 @@ public function getInstalledControllersCount(){ public function getControllerInfo($controller_name){ return $this->getItemByField('controllers', 'name', $controller_name, function($item){ $item['options'] = cmsModel::yamlToArray($item['options']); + $item['files'] = cmsModel::yamlToArray($item['files']); $item['title'] = string_lang($item['name'].'_CONTROLLER', $item['title']); return $item; }); diff --git a/system/controllers/content/hooks/rss_content_controller_form.php b/system/controllers/content/hooks/rss_content_controller_form.php index 4e36c04da..177682483 100755 --- a/system/controllers/content/hooks/rss_content_controller_form.php +++ b/system/controllers/content/hooks/rss_content_controller_form.php @@ -38,7 +38,7 @@ public function run($data){ new fieldList('mapping:image_size', array( 'title' => LANG_RSS_FEED_MAP_IMAGE_SIZE, 'generator' => function($item) { - return array('original' => LANG_PARSER_IMAGE_SIZE_ORIGINAL) + cmsCore::getModel('images')->getPresetsList(); + return array('original' => LANG_PARSER_IMAGE_SIZE_ORIGINAL) + cmsCore::getModel('images')->getPresetsList(true); } )) diff --git a/system/controllers/content/model.php b/system/controllers/content/model.php index 1d243dfea..ab6930d26 100755 --- a/system/controllers/content/model.php +++ b/system/controllers/content/model.php @@ -453,6 +453,8 @@ public function addContentField($ctype_name, $field, $is_virtual=false){ $sql = "ALTER TABLE {#}{$content_table_name} ADD `{$field['name']}` {$field_parser->getSQL()}"; $this->db->query($sql); + $field_parser->hookAfterAdd($content_table_name, $field, $this); + if($field_parser->is_denormalization){ $cfield_name = $field['name'].cmsFormField::FIELD_CACHE_POSTFIX; @@ -669,6 +671,8 @@ public function updateContentField($ctype_name, $id, $field){ $sql = "ALTER TABLE `{#}{$content_table_name}` CHANGE `{$field_old['name']}` `{$field['name']}` {$field_handler->getSQL()}"; $this->db->query($sql); + $field_handler->hookAfterUpdate($content_table_name, $field, $field_old, $this); + if(($field_old['name'] != $field['name']) || ($field_old['type'] != $field['type'])){ // поля денормализации @@ -853,6 +857,8 @@ public function deleteContentField($ctype_name_or_id, $id, $by_field='id', $isFo $this->db->dropTableField($content_table_name, $field['name']); + $field['parser']->hookAfterRemove($content_table_name, $field, $this); + if($field['parser']->is_denormalization){ $this->db->dropTableField($content_table_name, $field['parser']->getDenormalName()); } diff --git a/system/controllers/content/widgets/slider/options.form.php b/system/controllers/content/widgets/slider/options.form.php index 2853c0969..fa6c01a7f 100755 --- a/system/controllers/content/widgets/slider/options.form.php +++ b/system/controllers/content/widgets/slider/options.form.php @@ -100,7 +100,7 @@ public function init($options=false) { new fieldList('options:big_image_preset', array( 'title' => LANG_WD_CONTENT_SLIDER_BIG_IMAGE_PRESET, 'generator' => function($item) { - return cmsCore::getModel('images')->getPresetsList()+array('original' => LANG_PARSER_IMAGE_SIZE_ORIGINAL); + return cmsCore::getModel('images')->getPresetsList(true)+array('original' => LANG_PARSER_IMAGE_SIZE_ORIGINAL); }, )), diff --git a/system/controllers/images/model.php b/system/controllers/images/model.php index 0fed1422b..c2e27a401 100755 --- a/system/controllers/images/model.php +++ b/system/controllers/images/model.php @@ -13,10 +13,13 @@ public function getPresets(){ }); } - public function getPresetsList(){ + public function getPresetsList($with_params = false){ return $this->filterIsNull('is_internal')-> orderBy('width')-> - get('images_presets', function($item, $model){ + get('images_presets', function($item, $model) use($with_params){ + if($with_params){ + return $item['title'].', '.$item['name'].', '.($item['width'] ? $item['width'] : LANG_AUTO).'X'.($item['height'] ? $item['height'] : LANG_AUTO).'px'; + } return $item['title']; }, 'name'); } diff --git a/system/core/formfield.php b/system/core/formfield.php index 2eddc7fb9..abbd3d28e 100755 --- a/system/core/formfield.php +++ b/system/core/formfield.php @@ -2,29 +2,93 @@ class cmsFormField { + /** + * Префикс названия ячейки БД поля для кэширования + */ const FIELD_CACHE_POSTFIX = '_cache'; + /** + * Имя поля, как было задано в форме + * @var string + */ public $name; + /** + * Имя поля, как должно быть в HTML теге + * @var string + */ public $element_name = ''; + /** + * Тип фильтрации для поля + * true, false, int, str или date + * @var string || boolean + */ public $filter_type = false; + /** + * Краткое описания поля фильтрации для простых фильтров в админке + * @var string + */ public $filter_hint = false; - + /** + * Название поля + * @var string + */ public $title; public $element_title = ''; - + /** + * Флаг, указывающий, что поле может быть использовано для создания в полях типов контента, конструкторе форм и т.п. + * @var boolean + */ public $is_public = true; - + /** + * Последняя часть строки SQL запроса для создания поля в базе данных + * @var string + */ public $sql; + /** + * Последняя часть строки SQL запроса для создания поля в базе данных, в котором будет храниться кэшированное значение + * @var string + */ public $cache_sql; + /** + * Флаг, указывающий, что при создании поля в базе данных (например, при добавлении поля в типах контента) + * необходимо также добавить SQL индекс к этому полю + * @var boolean + */ public $allow_index = true; + /** + * Флаг, указывающий, что нам нужна денормализация данных, полученных из поля формы + * @var boolean + */ public $is_denormalization = false; - + /** + * Массив записи, в которой это поле используется + * @var array + */ public $item = null; - + /** + * ID поля, если запись о нём есть в таблице + * @var integer + */ + public $field_id = 0; + /** + * Флаг, что поле виртуальное + * @var boolean + */ public $is_virtual = false; + /** + * Флаг скрытого поля + * @var boolean + */ public $is_hidden = false; - + /** + * Массив правил валидации + * @var array + */ public $rules = array(); + /** + * Массив опций поля + * @var array + */ public $options = array(); protected $default_options_loaded = false; @@ -36,8 +100,11 @@ class cmsFormField { * @var string */ public $var_type = null; - - public $data = array(); // массив для данных в шаблоне + /** + * Массив для данных в шаблоне + * @var array + */ + public $data = array(); public function __construct($name, $options=false){ @@ -107,7 +174,10 @@ public function getOption($key) { public function setOptions($options){ if (is_array($options)){ foreach($options as $option=>$value){ - if ($option == 'id') { continue; } + if ($option == 'id') { + $this->field_id = $value; + continue; + } $this->{$option} = $value; } if (isset($options['title'])){ @@ -221,4 +291,16 @@ public function delete($value){ return true; } + public function hookAfterAdd($content_table_name, $field, $model){ + return $this; + } + + public function hookAfterUpdate($content_table_name, $field, $field_old, $model){ + return $this; + } + + public function hookAfterRemove($content_table_name, $field, $model){ + return $this; + } + } diff --git a/system/core/template.php b/system/core/template.php index 7cf321be4..44ce0c8c1 100755 --- a/system/core/template.php +++ b/system/core/template.php @@ -283,7 +283,7 @@ public function hasMenu($menu_name){ * @param int $max_items Максимальное количество видимых пунктов * @param bool $is_allow_multiple_active Определять все активные пункты меню * @param string $template Название файла шаблона меню в assets/ui/ - * @param string $menu_name Название(подпись) меню + * @param string $menu_title Название(подпись) меню */ public function menu($menu_name, $detect_active_id=true, $css_class='menu', $max_items=0, $is_allow_multiple_active=false, $template='menu', $menu_title=''){ @@ -1635,6 +1635,7 @@ public function renderPermissionsGrid($rules, $groups, $values, $submit_url){ * @param string $css_class CSS класс контейнера пунктов меню * @param int $max_items Максимальное количество видимых пунктов * @param string $template Название файла шаблона меню в assets/ui/ + * @param string $menu_title Название(подпись) меню */ public function renderMenu($menu, $active_ids=array(), $css_class='menu', $max_items=0, $template = 'menu', $menu_title=''){ diff --git a/system/fields/image.php b/system/fields/image.php index 9032cc45f..3b9aeffa2 100755 --- a/system/fields/image.php +++ b/system/fields/image.php @@ -15,7 +15,7 @@ public function getOptions(){ 'title' => LANG_PARSER_IMAGE_SIZE_TEASER, 'default' => 'small', 'generator' => function (){ - $presets = cmsCore::getModel('images')->getPresetsList(); + $presets = cmsCore::getModel('images')->getPresetsList(true); $presets['original'] = LANG_PARSER_IMAGE_SIZE_ORIGINAL; return $presets; } @@ -24,7 +24,7 @@ public function getOptions(){ 'title' => LANG_PARSER_IMAGE_SIZE_FULL, 'default' => 'big', 'generator' => function (){ - $presets = cmsCore::getModel('images')->getPresetsList(); + $presets = cmsCore::getModel('images')->getPresetsList(true); $presets['original'] = LANG_PARSER_IMAGE_SIZE_ORIGINAL; return $presets; } @@ -33,7 +33,7 @@ public function getOptions(){ 'title' => LANG_PARSER_IMAGE_SIZE_MODAL, 'default' => '', 'generator' => function (){ - $presets = cmsCore::getModel('images')->getPresetsList(); + $presets = cmsCore::getModel('images')->getPresetsList(true); $presets['original'] = LANG_PARSER_IMAGE_SIZE_ORIGINAL; return array('' => '') + $presets; } diff --git a/system/fields/images.php b/system/fields/images.php index 7586a1dd5..82fae2a21 100755 --- a/system/fields/images.php +++ b/system/fields/images.php @@ -14,7 +14,7 @@ public function getOptions(){ 'title' => LANG_PARSER_IMAGE_SIZE_TEASER, 'default' => 'small', 'generator' => function (){ - $presets = cmsCore::getModel('images')->getPresetsList(); + $presets = cmsCore::getModel('images')->getPresetsList(true); $presets['original'] = LANG_PARSER_IMAGE_SIZE_ORIGINAL; return $presets; } @@ -23,7 +23,7 @@ public function getOptions(){ 'title' => LANG_PARSER_IMAGE_SIZE_FULL, 'default' => 'big', 'generator' => function (){ - $presets = cmsCore::getModel('images')->getPresetsList(); + $presets = cmsCore::getModel('images')->getPresetsList(true); $presets['original'] = LANG_PARSER_IMAGE_SIZE_ORIGINAL; return $presets; } @@ -32,7 +32,7 @@ public function getOptions(){ 'title' => LANG_PARSER_SMALL_IMAGE_PRESET, 'default' => 'small', 'generator' => function (){ - $presets = cmsCore::getModel('images')->getPresetsList(); + $presets = cmsCore::getModel('images')->getPresetsList(true); $presets['original'] = LANG_PARSER_IMAGE_SIZE_ORIGINAL; return $presets; } diff --git a/system/libs/mobile_detect.class.php b/system/libs/mobile_detect.class.php index 4e44ff367..6d0a36d5d 100755 --- a/system/libs/mobile_detect.class.php +++ b/system/libs/mobile_detect.class.php @@ -22,7 +22,7 @@ * README: https://github.com/serbanghita/Mobile-Detect/blob/master/README.md * HOWTO: https://github.com/serbanghita/Mobile-Detect/wiki/Code-examples * - * @version 2.8.25 + * @version 2.8.26 */ class Mobile_Detect @@ -66,7 +66,7 @@ class Mobile_Detect /** * Stores the version number of the current release. */ - const VERSION = '2.8.25'; + const VERSION = '2.8.26'; /** * A type for the version() method indicating a string return value. @@ -220,7 +220,7 @@ class Mobile_Detect // Removed |^.*Android.*Nexus(?!(?:Mobile).)*$ // @see #442 'NexusTablet' => 'Android.*Nexus[\s]+(7|9|10)', - 'SamsungTablet' => 'SAMSUNG.*Tablet|Galaxy.*Tab|SC-01C|GT-P1000|GT-P1003|GT-P1010|GT-P3105|GT-P6210|GT-P6800|GT-P6810|GT-P7100|GT-P7300|GT-P7310|GT-P7500|GT-P7510|SCH-I800|SCH-I815|SCH-I905|SGH-I957|SGH-I987|SGH-T849|SGH-T859|SGH-T869|SPH-P100|GT-P3100|GT-P3108|GT-P3110|GT-P5100|GT-P5110|GT-P6200|GT-P7320|GT-P7511|GT-N8000|GT-P8510|SGH-I497|SPH-P500|SGH-T779|SCH-I705|SCH-I915|GT-N8013|GT-P3113|GT-P5113|GT-P8110|GT-N8010|GT-N8005|GT-N8020|GT-P1013|GT-P6201|GT-P7501|GT-N5100|GT-N5105|GT-N5110|SHV-E140K|SHV-E140L|SHV-E140S|SHV-E150S|SHV-E230K|SHV-E230L|SHV-E230S|SHW-M180K|SHW-M180L|SHW-M180S|SHW-M180W|SHW-M300W|SHW-M305W|SHW-M380K|SHW-M380S|SHW-M380W|SHW-M430W|SHW-M480K|SHW-M480S|SHW-M480W|SHW-M485W|SHW-M486W|SHW-M500W|GT-I9228|SCH-P739|SCH-I925|GT-I9200|GT-P5200|GT-P5210|GT-P5210X|SM-T311|SM-T310|SM-T310X|SM-T210|SM-T210R|SM-T211|SM-P600|SM-P601|SM-P605|SM-P900|SM-P901|SM-T217|SM-T217A|SM-T217S|SM-P6000|SM-T3100|SGH-I467|XE500|SM-T110|GT-P5220|GT-I9200X|GT-N5110X|GT-N5120|SM-P905|SM-T111|SM-T2105|SM-T315|SM-T320|SM-T320X|SM-T321|SM-T520|SM-T525|SM-T530NU|SM-T230NU|SM-T330NU|SM-T900|XE500T1C|SM-P605V|SM-P905V|SM-T337V|SM-T537V|SM-T707V|SM-T807V|SM-P600X|SM-P900X|SM-T210X|SM-T230|SM-T230X|SM-T325|GT-P7503|SM-T531|SM-T330|SM-T530|SM-T705|SM-T705C|SM-T535|SM-T331|SM-T800|SM-T700|SM-T537|SM-T807|SM-P907A|SM-T337A|SM-T537A|SM-T707A|SM-T807A|SM-T237|SM-T807P|SM-P607T|SM-T217T|SM-T337T|SM-T807T|SM-T116NQ|SM-P550|SM-T350|SM-T550|SM-T9000|SM-P9000|SM-T705Y|SM-T805|GT-P3113|SM-T710|SM-T810|SM-T815|SM-T360|SM-T533|SM-T113|SM-T335|SM-T715|SM-T560|SM-T670|SM-T677|SM-T377|SM-T567|SM-T357T|SM-T555|SM-T561|SM-T713|SM-T719|SM-T813|SM-T819|SM-T580|SM-T355Y|SM-T280|SM-T817A|SM-T820|SM-W700|SM-P580|SM-T587', // SCH-P709|SCH-P729|SM-T2558|GT-I9205 - Samsung Mega - treat them like a regular phone. + 'SamsungTablet' => 'SAMSUNG.*Tablet|Galaxy.*Tab|SC-01C|GT-P1000|GT-P1003|GT-P1010|GT-P3105|GT-P6210|GT-P6800|GT-P6810|GT-P7100|GT-P7300|GT-P7310|GT-P7500|GT-P7510|SCH-I800|SCH-I815|SCH-I905|SGH-I957|SGH-I987|SGH-T849|SGH-T859|SGH-T869|SPH-P100|GT-P3100|GT-P3108|GT-P3110|GT-P5100|GT-P5110|GT-P6200|GT-P7320|GT-P7511|GT-N8000|GT-P8510|SGH-I497|SPH-P500|SGH-T779|SCH-I705|SCH-I915|GT-N8013|GT-P3113|GT-P5113|GT-P8110|GT-N8010|GT-N8005|GT-N8020|GT-P1013|GT-P6201|GT-P7501|GT-N5100|GT-N5105|GT-N5110|SHV-E140K|SHV-E140L|SHV-E140S|SHV-E150S|SHV-E230K|SHV-E230L|SHV-E230S|SHW-M180K|SHW-M180L|SHW-M180S|SHW-M180W|SHW-M300W|SHW-M305W|SHW-M380K|SHW-M380S|SHW-M380W|SHW-M430W|SHW-M480K|SHW-M480S|SHW-M480W|SHW-M485W|SHW-M486W|SHW-M500W|GT-I9228|SCH-P739|SCH-I925|GT-I9200|GT-P5200|GT-P5210|GT-P5210X|SM-T311|SM-T310|SM-T310X|SM-T210|SM-T210R|SM-T211|SM-P600|SM-P601|SM-P605|SM-P900|SM-P901|SM-T217|SM-T217A|SM-T217S|SM-P6000|SM-T3100|SGH-I467|XE500|SM-T110|GT-P5220|GT-I9200X|GT-N5110X|GT-N5120|SM-P905|SM-T111|SM-T2105|SM-T315|SM-T320|SM-T320X|SM-T321|SM-T520|SM-T525|SM-T530NU|SM-T230NU|SM-T330NU|SM-T900|XE500T1C|SM-P605V|SM-P905V|SM-T337V|SM-T537V|SM-T707V|SM-T807V|SM-P600X|SM-P900X|SM-T210X|SM-T230|SM-T230X|SM-T325|GT-P7503|SM-T531|SM-T330|SM-T530|SM-T705|SM-T705C|SM-T535|SM-T331|SM-T800|SM-T700|SM-T537|SM-T807|SM-P907A|SM-T337A|SM-T537A|SM-T707A|SM-T807A|SM-T237|SM-T807P|SM-P607T|SM-T217T|SM-T337T|SM-T807T|SM-T116NQ|SM-T116BU|SM-P550|SM-T350|SM-T550|SM-T9000|SM-P9000|SM-T705Y|SM-T805|GT-P3113|SM-T710|SM-T810|SM-T815|SM-T360|SM-T533|SM-T113|SM-T335|SM-T715|SM-T560|SM-T670|SM-T677|SM-T377|SM-T567|SM-T357T|SM-T555|SM-T561|SM-T713|SM-T719|SM-T813|SM-T819|SM-T580|SM-T355Y|SM-T280|SM-T817A|SM-T820|SM-W700|SM-P580|SM-T587|SM-P350|SM-P555M|SM-P355M|SM-T113NU|SM-T815Y', // SCH-P709|SCH-P729|SM-T2558|GT-I9205 - Samsung Mega - treat them like a regular phone. // http://docs.aws.amazon.com/silk/latest/developerguide/user-agent.html 'Kindle' => 'Kindle|Silk.*Accelerated|Android.*\b(KFOT|KFTT|KFJWI|KFJWA|KFOTE|KFSOWI|KFTHWI|KFTHWA|KFAPWI|KFAPWA|WFJWAE|KFSAWA|KFSAWI|KFASWI|KFARWI|KFFOWI|KFGIWI|KFMEWI)\b|Android.*Silk/[0-9.]+ like Chrome/[0-9.]+ (?!Mobile)', // Only the Surface tablets with Windows RT are considered mobile. @@ -230,7 +230,7 @@ class Mobile_Detect 'HPTablet' => 'HP Slate (7|8|10)|HP ElitePad 900|hp-tablet|EliteBook.*Touch|HP 8|Slate 21|HP SlateBook 10', // Watch out for PadFone, see #132. // http://www.asus.com/de/Tablets_Mobile/Memo_Pad_Products/ - 'AsusTablet' => '^.*PadFone((?!Mobile).)*$|Transformer|TF101|TF101G|TF300T|TF300TG|TF300TL|TF700T|TF700KL|TF701T|TF810C|ME171|ME301T|ME302C|ME371MG|ME370T|ME372MG|ME172V|ME173X|ME400C|Slider SL101|\bK00F\b|\bK00C\b|\bK00E\b|\bK00L\b|TX201LA|ME176C|ME102A|\bM80TA\b|ME372CL|ME560CG|ME372CG|ME302KL| K010 | K011 | K017 | K01E |ME572C|ME103K|ME170C|ME171C|\bME70C\b|ME581C|ME581CL|ME8510C|ME181C|P01Y|PO1MA|P01Z', + 'AsusTablet' => '^.*PadFone((?!Mobile).)*$|Transformer|TF101|TF101G|TF300T|TF300TG|TF300TL|TF700T|TF700KL|TF701T|TF810C|ME171|ME301T|ME302C|ME371MG|ME370T|ME372MG|ME172V|ME173X|ME400C|Slider SL101|\bK00F\b|\bK00C\b|\bK00E\b|\bK00L\b|TX201LA|ME176C|ME102A|\bM80TA\b|ME372CL|ME560CG|ME372CG|ME302KL| K010 | K011 | K017 | K01E |ME572C|ME103K|ME170C|ME171C|\bME70C\b|ME581C|ME581CL|ME8510C|ME181C|P01Y|PO1MA|P01Z|\bP027\b', 'BlackBerryTablet' => 'PlayBook|RIM Tablet', 'HTCtablet' => 'HTC_Flyer_P512|HTC Flyer|HTC Jetstream|HTC-P715a|HTC EVO View 4G|PG41200|PG09410', 'MotorolaTablet' => 'xoom|sholest|MZ615|MZ605|MZ505|MZ601|MZ602|MZ603|MZ604|MZ606|MZ607|MZ608|MZ609|MZ615|MZ616|MZ617', @@ -252,7 +252,7 @@ class Mobile_Detect // Prestigio Tablets http://www.prestigio.com/support 'PrestigioTablet' => 'PMP3170B|PMP3270B|PMP3470B|PMP7170B|PMP3370B|PMP3570C|PMP5870C|PMP3670B|PMP5570C|PMP5770D|PMP3970B|PMP3870C|PMP5580C|PMP5880D|PMP5780D|PMP5588C|PMP7280C|PMP7280C3G|PMP7280|PMP7880D|PMP5597D|PMP5597|PMP7100D|PER3464|PER3274|PER3574|PER3884|PER5274|PER5474|PMP5097CPRO|PMP5097|PMP7380D|PMP5297C|PMP5297C_QUAD|PMP812E|PMP812E3G|PMP812F|PMP810E|PMP880TD|PMT3017|PMT3037|PMT3047|PMT3057|PMT7008|PMT5887|PMT5001|PMT5002', // http://support.lenovo.com/en_GB/downloads/default.page?# - 'LenovoTablet' => 'Lenovo TAB|Idea(Tab|Pad)( A1|A10| K1|)|ThinkPad([ ]+)?Tablet|YT3-X90L|YT3-X90F|YT3-X90X|Lenovo.*(S2109|S2110|S5000|S6000|K3011|A3000|A3500|A1000|A2107|A2109|A1107|A5500|A7600|B6000|B8000|B8080)(-|)(FL|F|HV|H|)', + 'LenovoTablet' => 'Lenovo TAB|Idea(Tab|Pad)( A1|A10| K1|)|ThinkPad([ ]+)?Tablet|YT3-850M|YT3-X90L|YT3-X90F|YT3-X90X|Lenovo.*(S2109|S2110|S5000|S6000|K3011|A3000|A3500|A1000|A2107|A2109|A1107|A5500|A7600|B6000|B8000|B8080)(-|)(FL|F|HV|H|)', // http://www.dell.com/support/home/us/en/04/Products/tab_mob/tablets 'DellTablet' => 'Venue 11|Venue 8|Venue 7|Dell Streak 10|Dell Streak 7', // http://www.yarvik.com/en/matrix/tablets/ @@ -451,6 +451,7 @@ class Mobile_Detect // http://www.nbru.cn/index.html 'NibiruTablet' => 'Nibiru M1|Nibiru Jupiter One', // http://navroad.com/products/produkty/tablety/ + // http://navroad.com/products/produkty/tablety/ 'NexoTablet' => 'NEXO NOVA|NEXO 10|NEXO AVIO|NEXO FREE|NEXO GO|NEXO EVO|NEXO 3G|NEXO SMART|NEXO KIDDO|NEXO MOBI', // http://leader-online.com/new_site/product-category/tablets/ // http://www.leader-online.net.au/List/Tablet @@ -467,7 +468,7 @@ class Mobile_Detect 'Hudl' => 'Hudl HT7S3|Hudl 2', // http://www.telstra.com.au/home-phone/thub-2/ 'TelstraTablet' => 'T-Hub2', - 'GenericTablet' => 'Android.*\b97D\b|Tablet(?!.*PC)|BNTV250A|MID-WCDMA|LogicPD Zoom2|\bA7EB\b|CatNova8|A1_07|CT704|CT1002|\bM721\b|rk30sdk|\bEVOTAB\b|M758A|ET904|ALUMIUM10|Smartfren Tab|Endeavour 1010|Tablet-PC-4|Tagi Tab|\bM6pro\b|CT1020W|arc 10HD|\bTP750\b' + 'GenericTablet' => 'Android.*\b97D\b|Tablet(?!.*PC)|BNTV250A|MID-WCDMA|LogicPD Zoom2|\bA7EB\b|CatNova8|A1_07|CT704|CT1002|\bM721\b|rk30sdk|\bEVOTAB\b|M758A|ET904|ALUMIUM10|Smartfren Tab|Endeavour 1010|Tablet-PC-4|Tagi Tab|\bM6pro\b|CT1020W|arc 10HD|\bTP750\b|\bQTAQZ3\b' ); /** diff --git a/system/libs/phpmailer/class.phpmailer.php b/system/libs/phpmailer/class.phpmailer.php index acc006d6b..8042b3849 100755 --- a/system/libs/phpmailer/class.phpmailer.php +++ b/system/libs/phpmailer/class.phpmailer.php @@ -31,7 +31,7 @@ class PHPMailer * The PHPMailer Version number. * @var string */ - public $Version = '5.2.24'; + public $Version = '5.2.25'; /** * Email priority. diff --git a/system/libs/phpmailer/class.pop3.php b/system/libs/phpmailer/class.pop3.php index 330c73a13..f2c4e3744 100755 --- a/system/libs/phpmailer/class.pop3.php +++ b/system/libs/phpmailer/class.pop3.php @@ -34,7 +34,7 @@ class POP3 * @var string * @access public */ - public $Version = '5.2.24'; + public $Version = '5.2.25'; /** * Default POP3 port number. diff --git a/system/libs/phpmailer/class.smtp.php b/system/libs/phpmailer/class.smtp.php index 79c762be8..d8af427e8 100755 --- a/system/libs/phpmailer/class.smtp.php +++ b/system/libs/phpmailer/class.smtp.php @@ -30,7 +30,7 @@ class SMTP * The PHPMailer SMTP version number. * @var string */ - const VERSION = '5.2.24'; + const VERSION = '5.2.25'; /** * SMTP line break constant. @@ -81,7 +81,7 @@ class SMTP * @deprecated Use the `VERSION` constant instead * @see SMTP::VERSION */ - public $Version = '5.2.24'; + public $Version = '5.2.25'; /** * SMTP server port number. @@ -151,9 +151,8 @@ class SMTP public $Timelimit = 300; /** - * @var array patterns to extract smtp transaction id from smtp reply - * Only first capture group will be use, use non-capturing group to deal with it - * Extend this class to override this property to fulfil your needs. + * @var array Patterns to extract an SMTP transaction id from reply to a DATA command. + * The first capture group in each regex will be used as the ID. */ protected $smtp_transaction_id_patterns = array( 'exim' => '/[0-9]{3} OK id=(.*)/', @@ -161,6 +160,12 @@ class SMTP 'postfix' => '/[0-9]{3} 2.0.0 Ok: queued as (.*)/' ); + /** + * @var string The last transaction ID issued in response to a DATA command, + * if one was detected + */ + protected $last_smtp_transaction_id; + /** * The socket for the server connection. * @var resource @@ -709,6 +714,7 @@ public function data($msg_data) $savetimelimit = $this->Timelimit; $this->Timelimit = $this->Timelimit * 2; $result = $this->sendCommand('DATA END', '.', 250); + $this->recordLastTransactionID(); //Restore timelimit $this->Timelimit = $savetimelimit; return $result; @@ -1231,26 +1237,40 @@ protected function errorHandler($errno, $errmsg, $errfile = '', $errline = 0) } /** - * Will return the ID of the last smtp transaction based on a list of patterns provided - * in SMTP::$smtp_transaction_id_patterns. + * Extract and return the ID of the last SMTP transaction based on + * a list of patterns provided in SMTP::$smtp_transaction_id_patterns. + * Relies on the host providing the ID in response to a DATA command. * If no reply has been received yet, it will return null. - * If no pattern has been matched, it will return false. + * If no pattern was matched, it will return false. * @return bool|null|string */ - public function getLastTransactionID() + protected function recordLastTransactionID() { $reply = $this->getLastReply(); if (empty($reply)) { - return null; - } - - foreach ($this->smtp_transaction_id_patterns as $smtp_transaction_id_pattern) { - if (preg_match($smtp_transaction_id_pattern, $reply, $matches)) { - return $matches[1]; + $this->last_smtp_transaction_id = null; + } else { + $this->last_smtp_transaction_id = false; + foreach ($this->smtp_transaction_id_patterns as $smtp_transaction_id_pattern) { + if (preg_match($smtp_transaction_id_pattern, $reply, $matches)) { + $this->last_smtp_transaction_id = $matches[1]; + } } } - return false; + return $this->last_smtp_transaction_id; + } + + /** + * Get the queue/transaction ID of the last SMTP transaction + * If no reply has been received yet, it will return null. + * If no pattern was matched, it will return false. + * @return bool|null|string + * @see recordLastTransactionID() + */ + public function getLastTransactionID() + { + return $this->last_smtp_transaction_id; } } diff --git a/system/libs/phpmailer/language/phpmailer.lang-ba.php b/system/libs/phpmailer/language/phpmailer.lang-ba.php new file mode 100644 index 000000000..095dee3e2 --- /dev/null +++ b/system/libs/phpmailer/language/phpmailer.lang-ba.php @@ -0,0 +1,26 @@ + + */ + +$PHPMAILER_LANG['authenticate'] = 'SMTP Greška: Neuspjela prijava.'; +$PHPMAILER_LANG['connect_host'] = 'SMTP Greška: Ne moguće se spojiti sa SMTP serverom.'; +$PHPMAILER_LANG['data_not_accepted'] = 'SMTP Greška: Podatci nisu prihvaćeni.'; +$PHPMAILER_LANG['empty_message'] = 'Sadržaj poruke je prazan.'; +$PHPMAILER_LANG['encoding'] = 'Nepoznata kriptografija: '; +$PHPMAILER_LANG['execute'] = 'Nije moguće izvršiti naredbu: '; +$PHPMAILER_LANG['file_access'] = 'Nije moguće pristupiti datoteci: '; +$PHPMAILER_LANG['file_open'] = 'Nije moguće otvoriti datoteku: '; +$PHPMAILER_LANG['from_failed'] = 'SMTP Greška: Slanje sa navedenih e-mail adresa nije uspjelo: '; +$PHPMAILER_LANG['recipients_failed'] = 'SMTP Greška: Slanje na navedene e-mail adrese nije uspjelo: '; +$PHPMAILER_LANG['instantiate'] = 'Ne mogu pokrenuti mail funkcionalnost.'; +$PHPMAILER_LANG['invalid_address'] = 'E-mail nije poslan. Neispravna e-mail adresa: '; +$PHPMAILER_LANG['mailer_not_supported'] = ' mailer nije podržan.'; +$PHPMAILER_LANG['provide_address'] = 'Definišite barem jednu adresu primaoca.'; +$PHPMAILER_LANG['signing'] = 'Greška prilikom prijave: '; +$PHPMAILER_LANG['smtp_connect_failed'] = 'Spajanje na SMTP server nije uspjelo.'; +$PHPMAILER_LANG['smtp_error'] = 'SMTP greška: '; +$PHPMAILER_LANG['variable_set'] = 'Nije moguće postaviti varijablu ili je vratiti nazad: '; +$PHPMAILER_LANG['extension_missing'] = 'Nedostaje ekstenzija: '; \ No newline at end of file diff --git a/system/libs/strings.helper.php b/system/libs/strings.helper.php index ba62d011d..1d38eba05 100755 --- a/system/libs/strings.helper.php +++ b/system/libs/strings.helper.php @@ -781,7 +781,7 @@ function array_order_by(&$array, $fields, $direction = 'asc') { foreach ($list as $order) { - $args[$key][$k] = $item[$order['by']]; + $args[$key][$k] = $item[$order['by']]; $key++; $args[$key] = constant('SORT_'.strtoupper($order['to'])); $key++; @@ -796,6 +796,20 @@ function array_order_by(&$array, $fields, $direction = 'asc') { } +function multi_array_unique($array) { + + $result = array_map('unserialize', array_unique(array_map('serialize', $array))); + + foreach ($result as $key => $value) { + if (is_array($value)) { + $result[$key] = multi_array_unique($value); + } + } + + return $result; + +} + //============================================================================// /** diff --git a/templates/default/admin.tpl.php b/templates/default/admin.tpl.php index 409080c36..a41e301ca 100755 --- a/templates/default/admin.tpl.php +++ b/templates/default/admin.tpl.php @@ -108,17 +108,18 @@ - - + \ No newline at end of file diff --git a/templates/default/widgets/menu/menu.tpl.php b/templates/default/widgets/menu/menu.tpl.php index 868fd8bd7..9715ab672 100755 --- a/templates/default/widgets/menu/menu.tpl.php +++ b/templates/default/widgets/menu/menu.tpl.php @@ -1,3 +1,3 @@ menu($widget->options['menu'], $widget->options['is_detect'], 'menu', $widget->options['max_items'], true, (!empty($widget->options['template']) ? $widget->options['template'] : 'menu')); + $this->menu($widget->options['menu'], $widget->options['is_detect'], 'menu', $widget->options['max_items'], true, (!empty($widget->options['template']) ? $widget->options['template'] : 'menu'), $widget->title); diff --git a/templates/default/widgets/wrapper_tabbed.tpl.php b/templates/default/widgets/wrapper_tabbed.tpl.php index d96f46768..2dbd9f0b6 100755 --- a/templates/default/widgets/wrapper_tabbed.tpl.php +++ b/templates/default/widgets/wrapper_tabbed.tpl.php @@ -1,5 +1,17 @@ - -
+ +
    $widget) { ?>