diff --git a/.gitignore b/.gitignore index 3b98d313a..c0a3a9bf5 100755 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ /system/controllers/api/ /system/languages/ru/controllers/api/ /system/languages/en/controllers/api/ -/templates/default/controllers/api/ \ No newline at end of file +/templates/default/controllers/api/ +/cache/rsscache/ \ No newline at end of file diff --git a/credits.txt b/credits.txt index bb9ced12c..66aa299b5 100755 --- a/credits.txt +++ b/credits.txt @@ -97,3 +97,7 @@ Third-party plugins, libraries and resources included in InstantCMS: jQuery UI Touch Punch by David Furfero http://touchpunch.furf.com/ + + jQuery CSS Customizable Scrollbar + by Yuriy Khabarov + https://github.com/gromo/jquery.scrollbar/ diff --git a/install/steps/php.php b/install/steps/php.php index f4b245838..3604d0044 100755 --- a/install/steps/php.php +++ b/install/steps/php.php @@ -16,9 +16,9 @@ function step($is_submit){ function check_requirements(){ - $min_php_version = '5.3.0'; - $vars = array('magic_quotes_gpc' => 0, 'register_globals' => 0); - $extensions = array('date', 'gd', 'json', 'mbstring', 'mysqli', 'session', 'filter'); + $min_php_version = '5.4.0'; + $vars = array('magic_quotes_gpc' => 0, 'register_globals' => 0); + $extensions = array('date', 'gd', 'json', 'mbstring', 'mysqli', 'session', 'filter'); $extensions_extra = array('ftp', 'memcache', 'zip', 'curl'); sort($extensions); @@ -30,7 +30,7 @@ function check_requirements(){ $info['php'] = array( 'version' => PHP_VERSION, - 'valid' => (version_compare(PHP_VERSION, $min_php_version) >= 0) + 'valid' => (version_compare(PHP_VERSION, $min_php_version) >= 0) ); $info['valid'] = $info['valid'] && $info['php']['valid']; @@ -56,4 +56,4 @@ function check_requirements(){ return $info; -} \ No newline at end of file +} diff --git a/system/controllers/admin/actions/index.php b/system/controllers/admin/actions/index.php index 3faa43ea2..59290160c 100755 --- a/system/controllers/admin/actions/index.php +++ b/system/controllers/admin/actions/index.php @@ -56,6 +56,11 @@ public function run(){ LANG_CP_DASHBOARD_SI_ZENDG => in_array('Zend Guard Loader', $extensions) ); + $dashboard_blocks[] = array( + 'title' => LANG_CP_DASHBOARD_NEWS, + 'html' => $this->cms_template->getRenderedChild('index_news', array()) + ); + $dashboard_blocks[] = array( 'title' => LANG_CP_DASHBOARD_SYSINFO, 'html' => $this->cms_template->getRenderedChild('index_sysinfo', array( diff --git a/system/controllers/admin/actions/load_icms_news.php b/system/controllers/admin/actions/load_icms_news.php new file mode 100755 index 000000000..8c7000d0b --- /dev/null +++ b/system/controllers/admin/actions/load_icms_news.php @@ -0,0 +1,57 @@ + 'http://www.instantcms.ru/rss/content/2/feed.rss', + 'icms_addons' => 'http://addons.instantcms.ru/rss/feed/addons', + 'icms_docs' => 'http://docs.instantcms.ru/feed.php' + ); + + private $news_count = 10; + + public function run($target){ + + if (!$this->request->isAjax()) { cmsCore::error404(); } + + if (!$target || !in_array($target, array_keys($this->news_link))) { cmsCore::error404(); } + + cmsCore::loadLib('lastrss.class'); + + $rss = new lastRSS; + + $rss->cache_dir = cmsConfig::get('cache_path'); + $rss->cache_time = 3600; + $rss->stripHTML = true; + $rss->cp = 'UTF-8'; + $rss->items_limit = $this->news_count; + + $items = array(); + + $res = $rss->get($this->news_link[$target]); + + if(!empty($res['items'])){ + foreach ($res['items'] as $item) { + + $item['target_title'] = empty($res['title']) ? + (empty($res['image_title']) ? '' : $res['image_title']) : + $res['title']; + + $item['target_description'] = empty($res['description']) ? + (empty($res['image_description']) ? '' : $res['image_description']) : + $res['description']; + + $items[] = $item; + + } + } + + if(!$items){ $this->halt(LANG_NO_ITEMS); } + + $this->cms_template->renderPlain('index_news_data', array( + 'items' => $items + )); + + } + +} diff --git a/system/controllers/content/frontend.php b/system/controllers/content/frontend.php index 28a8fa04a..31bf4260e 100755 --- a/system/controllers/content/frontend.php +++ b/system/controllers/content/frontend.php @@ -196,7 +196,8 @@ public function renderItemsList($ctype, $page_url, $hide_filter=false, $category // Получаем количество и список записей $total = $this->model->getContentItemsCount($ctype['name']); - $items = $this->model->getContentItems($ctype['name'], function ($item, $model) use ($ctype, $hide_except_title){ + $items = $this->model->getContentItems($ctype['name'], function ($item, $model, $ctype_name, $user) + use ($ctype, $hide_except_title, $fields){ $item['ctype'] = $ctype; $item['ctype_name'] = $ctype['name']; @@ -210,6 +211,32 @@ public function renderItemsList($ctype, $page_url, $hide_filter=false, $category $item['private_item_hint'] = LANG_PRIVACY_PRIVATE_HINT; } + // строим поля списка + foreach($fields as $field){ + + if ($field['is_system'] || !$field['is_in_list'] || !isset($item[$field['name']])) { continue; } + if ($field['groups_read'] && !$user->isInGroups($field['groups_read'])) { continue; } + if (!$item[$field['name']] && $item[$field['name']] !== '0') { continue; } + + if (!isset($field['options']['label_in_list'])) { + $label_pos = 'none'; + } else { + $label_pos = $field['options']['label_in_list']; + } + + $field_html = $field['handler']->setItem($item)->parseTeaser($item[$field['name']]); + if (!$field_html) { continue; } + + $item['fields'][$field['name']] = array( + 'label_pos' => $label_pos, + 'type' => $field['type'], + 'name' => $field['name'], + 'title' => $field['title'], + 'html' => $field_html + ); + + } + return $item; }); diff --git a/system/controllers/content/model.php b/system/controllers/content/model.php index a9e42741b..1d243dfea 100755 --- a/system/controllers/content/model.php +++ b/system/controllers/content/model.php @@ -2298,7 +2298,7 @@ public function getContentItems($ctype_name, $callback = null){ ); if (is_callable($callback)){ - $item = $callback($item, $model, $ctype_name); + $item = $callback($item, $model, $ctype_name, $user); } return $item; diff --git a/system/controllers/groups/frontend.php b/system/controllers/groups/frontend.php index f1db124be..13ee860a6 100755 --- a/system/controllers/groups/frontend.php +++ b/system/controllers/groups/frontend.php @@ -405,12 +405,15 @@ public function renderGroupsList($page_url, $dataset_name = false){ $label_pos = $field['options']['label_in_list']; } - $groups[$key]['fields'][] = array( + $field_html = $field['handler']->setItem($group)->parseTeaser($group[$field['name']]); + if (!$field_html) { continue; } + + $groups[$key]['fields'][$field['name']] = array( 'label_pos' => $label_pos, 'type' => $field['type'], 'name' => $field['name'], 'title' => $field['title'], - 'html' => $field['handler']->setItem($group)->parseTeaser($group[$field['name']]) + 'html' => $field_html ); } diff --git a/system/languages/en/controllers/admin/admin.php b/system/languages/en/controllers/admin/admin.php index b6d023d6f..4bec14212 100755 --- a/system/languages/en/controllers/admin/admin.php +++ b/system/languages/en/controllers/admin/admin.php @@ -7,6 +7,9 @@ define('LANG_CP_DASHBOARD_STATS', 'Site Stats'); define('LANG_CP_DASHBOARD_SYSINFO', 'System Info'); define('LANG_CP_DASHBOARD_RESOURCES', 'Useful Resources'); + define('LANG_CP_DASHBOARD_NEWS', 'InstantCMS news'); + define('LANG_CP_DASHBOARD_NEWS_O', 'Official'); + define('LANG_CP_DASHBOARD_NEWS_A', 'Addons'); define('LANG_CP_DASHBOARD_SI_ICMS', 'InstantCMS version'); define('LANG_CP_DASHBOARD_SI_PHP', 'PHP version'); diff --git a/system/languages/ru/controllers/admin/admin.php b/system/languages/ru/controllers/admin/admin.php index 364b0eb10..d6154cf36 100755 --- a/system/languages/ru/controllers/admin/admin.php +++ b/system/languages/ru/controllers/admin/admin.php @@ -7,6 +7,9 @@ define('LANG_CP_DASHBOARD_STATS', 'Статистика'); define('LANG_CP_DASHBOARD_SYSINFO', 'Информация о системе'); define('LANG_CP_DASHBOARD_RESOURCES', 'Полезные ресурсы'); + define('LANG_CP_DASHBOARD_NEWS', 'Новости InstantCMS'); + define('LANG_CP_DASHBOARD_NEWS_O', 'Официальные'); + define('LANG_CP_DASHBOARD_NEWS_A', 'Дополнения'); define('LANG_CP_DASHBOARD_SI_ICMS', 'Версия InstantCMS'); define('LANG_CP_DASHBOARD_SI_PHP', 'Версия PHP'); diff --git a/system/libs/lastrss.class.php b/system/libs/lastrss.class.php new file mode 100644 index 000000000..14b4af15a --- /dev/null +++ b/system/libs/lastrss.class.php @@ -0,0 +1,288 @@ +getCached($rss_url); + + if(!$result){ + + $result = $this->parse($rss_url); + + if ($result) { + + $this->cacheResult($rss_url, $result); + + $result['cached'] = 0; + + } + + } + + return $result; + + } + + private function getCached($rss_url) { + + if (!$this->cache_dir) { return false; } + + $cache_dir = $this->cache_dir . '/rsscache/'; + + if(!is_dir($cache_dir)){ mkdir($cache_dir, 0777); } + + $cache_file = $cache_dir.md5($rss_url); + + if(!is_readable($cache_file)){ + return false; + } + + $timedif = (time() - filemtime($cache_file)); + + if ($timedif < $this->cache_time) { + + $result = include $cache_file; + + if ($result) { + + $result['cached'] = 1; + + return $result; + + } else { + unlink($cache_file); + } + + } else { + unlink($cache_file); + } + + return false; + + } + + private function cacheResult($rss_url, $result) { + + if (!$this->cache_dir) { return false; } + + $cache_dir = $this->cache_dir . '/rsscache/'; + + if(!is_dir($cache_dir)){ mkdir($cache_dir, 0777); } + + $cache_file = $cache_dir.md5($rss_url); + + file_put_contents($cache_file, 'CDATA == 'content') { // Get CDATA content (without CDATA tag) + $out[1] = strtr($out[1], array(''', ']]>'=>'')); + } elseif ($this->CDATA == 'strip') { // Strip CDATA + $out[1] = strtr($out[1], array(''', ']]>'=>'')); + } + + // If code page is set convert character encoding to required + if ($this->cp != '') { + $out[1] = iconv($this->rsscp, $this->cp.'//TRANSLIT', $out[1]); + } + // Return result + return trim($out[1]); + } else { + // if there is NO result, return empty string + return ''; + } + } + + // ------------------------------------------------------------------- + // Replace HTML entities &something; by real characters + // ------------------------------------------------------------------- + private function unhtmlentities ($string) { + // Get HTML entities table + $trans_tbl = get_html_translation_table (HTML_ENTITIES, ENT_QUOTES); + // Flip keys<==>values + $trans_tbl = array_flip ($trans_tbl); + // Add support for ' entity (missing in HTML_ENTITIES) + $trans_tbl += array(''' => "'"); + // Replace entities by values + return strtr ($string, $trans_tbl); + } + + // ------------------------------------------------------------------- + // Parse() is private method used by get() to load and parse RSS file. + // Don't use parse() in your scripts - use get($rss_file) instead. + // ------------------------------------------------------------------- + public function parse ($rss_url) { + + $rss_content = $this->getRssFromUrl($rss_url); + if(!$rss_content){ return false; } + + // Parse document encoding + $result['encoding'] = $this->my_preg_match("'encoding=[\'\"](.*?)[\'\"]'si", $rss_content); + // if document codepage is specified, use it + if ($result['encoding'] != '') + { $this->rsscp = $result['encoding']; } // This is used in my_preg_match() + // otherwise use the default codepage + else + { $this->rsscp = $this->default_cp; } // This is used in my_preg_match() + + // Parse CHANNEL info + preg_match("'(.*)'si", $rss_content, $out_channel); + foreach($this->channeltags as $channeltag) { + $temp = $this->my_preg_match("'<$channeltag.*?>(.*?)'si", @$out_channel[1]); + if ($temp != '') { $result[$channeltag] = $temp; } // Set only if not empty + } + // If date_format is specified and lastBuildDate is valid + if ($this->date_format != '' && ($timestamp = strtotime($result['lastBuildDate'])) !==-1) { + // convert lastBuildDate to specified date format + $result['lastBuildDate'] = date($this->date_format, $timestamp); + } + + // Parse TEXTINPUT info + preg_match("']*[^/])>(.*?)'si", $rss_content, $out_textinfo); + // This a little strange regexp means: + // Look for tag with or without any attributes, but skip truncated version (it's not beggining tag) + if (isset($out_textinfo[2])) { + foreach($this->textinputtags as $textinputtag) { + $temp = $this->my_preg_match("'<$textinputtag.*?>(.*?)'si", $out_textinfo[2]); + if ($temp != '') { $result['textinput_'.$textinputtag] = $temp; } // Set only if not empty + } + } + // Parse IMAGE info + preg_match("'(.*?)'si", $rss_content, $out_imageinfo); + if (isset($out_imageinfo[1])) { + foreach($this->imagetags as $imagetag) { + $temp = $this->my_preg_match("'<$imagetag.*?>(.*?)'si", $out_imageinfo[1]); + if ($temp != '') { $result['image_'.$imagetag] = $temp; } // Set only if not empty + } + } + // Parse ITEMS + preg_match_all("'(.*?)'si", $rss_content, $items); + $rss_items = $items[2]; + $i = 0; + $result['items'] = array(); // create array even if there are no items + foreach($rss_items as $rss_item) { + // If number of items is lower then limit: Parse one item + if ($i < $this->items_limit || $this->items_limit == 0) { + foreach($this->itemtags as $itemtag) { + $temp = $this->my_preg_match("'<$itemtag.*?>(.*?)'si", $rss_item); + if ($temp != '') { $result['items'][$i][$itemtag] = $temp; } // Set only if not empty + } + $temp = $this->my_preg_match('#stripHTML && !empty($result['items'][$i]['description'])){ + $result['items'][$i]['description'] = strip_tags(str_replace('><', '> <', $this->unhtmlentities(strip_tags(str_replace('><', '> <', $result['items'][$i]['description']))))); + } + // Strip HTML tags and other bullshit from TITLE + if ($this->stripHTML && $result['items'][$i]['title']){ + $result['items'][$i]['title'] = strip_tags($this->unhtmlentities(strip_tags($result['items'][$i]['title']))); + } + // If date_format is specified and pubDate is valid + if ($this->date_format != '' && ($timestamp = strtotime($result['items'][$i]['pubDate'])) !==-1) { + // convert pubDate to specified date format + $result['items'][$i]['pubDate'] = date($this->date_format, $timestamp); + } + // Item counter + $i++; + } + } + + $result['items_count'] = $i; + + return $result; + + } + + private function getRssFromUrl($url){ + + $data = @file_get_contents($url); + + if ($data===false){ + + if (function_exists('curl_init')){ + + $curl = curl_init(); + + if(strpos($url, 'https') === 0){ + curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); + } + curl_setopt($curl, CURLOPT_URL, $url); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_HEADER, false); + curl_setopt($curl, CURLOPT_TIMEOUT, 3); + $data = curl_exec($curl); + curl_close($curl); + + } + + } + + return $data; + + } + +} diff --git a/templates/default/assets/ui/grid-data.tpl.php b/templates/default/assets/ui/grid-data.tpl.php index 7061bae2a..32c35892f 100755 --- a/templates/default/assets/ui/grid-data.tpl.php +++ b/templates/default/assets/ui/grid-data.tpl.php @@ -70,6 +70,11 @@
+
+
+
+
+
diff --git a/templates/default/content/albums_list.tpl.php b/templates/default/content/albums_list.tpl.php index ba10d85d2..2cf7a5ac3 100755 --- a/templates/default/content/albums_list.tpl.php +++ b/templates/default/content/albums_list.tpl.php @@ -40,7 +40,6 @@ style="background-image: url();"> -
@@ -61,52 +60,38 @@
- +
- isInGroups($fields['content']['groups_read'])) { ?> - - - setItem($item)->parseTeaser($item['content']); ?> - - +
- +
- + - - isInGroups($field['groups_read'])) { continue; } ?> - - -
- -
+ +
+ +
- setItem($item)->parseTeaser($item[$field['name']]); ?> +
diff --git a/templates/default/content/default_list.tpl.php b/templates/default/content/default_list.tpl.php index acedf742d..dc6533085 100755 --- a/templates/default/content/default_list.tpl.php +++ b/templates/default/content/default_list.tpl.php @@ -23,7 +23,7 @@
- +
@@ -32,34 +32,24 @@ - +
- + - - isInGroups($field['groups_read'])) { continue; } ?> - - -
- -
+ +
+ +
-

@@ -81,7 +71,7 @@
- setItem($item)->parseTeaser($item[$field['name']]); ?> +

diff --git a/templates/default/content/default_list_featured.tpl.php b/templates/default/content/default_list_featured.tpl.php index 5f0cf6137..7f53797dd 100755 --- a/templates/default/content/default_list_featured.tpl.php +++ b/templates/default/content/default_list_featured.tpl.php @@ -29,7 +29,7 @@
- +
@@ -38,32 +38,21 @@ - +
- + - - isInGroups($field['groups_read'])) { continue; } ?> - - -
- -
- + +
+
@@ -88,7 +77,7 @@
- setItem($item)->parseTeaser($item[$field['name']]); ?> +
diff --git a/templates/default/content/default_list_table.tpl.php b/templates/default/content/default_list_table.tpl.php index 48a71fb21..0fe6ef018 100755 --- a/templates/default/content/default_list_table.tpl.php +++ b/templates/default/content/default_list_table.tpl.php @@ -45,7 +45,6 @@ - class="is_vip"> diff --git a/templates/default/content/default_list_tiles.tpl.php b/templates/default/content/default_list_tiles.tpl.php index b56c5fd52..889b77394 100755 --- a/templates/default/content/default_list_tiles.tpl.php +++ b/templates/default/content/default_list_tiles.tpl.php @@ -25,7 +25,7 @@
- +
@@ -38,31 +38,22 @@ - +
- + - - isInGroups($field['groups_read'])) { continue; } ?> - - -
- -
+ +
+ +
@@ -87,7 +78,7 @@
- setItem($item)->parseTeaser($item[$field['name']]); ?> +
diff --git a/templates/default/controllers/admin/index_news.tpl.php b/templates/default/controllers/admin/index_news.tpl.php new file mode 100755 index 000000000..cfb5d12ef --- /dev/null +++ b/templates/default/controllers/admin/index_news.tpl.php @@ -0,0 +1,33 @@ +addJS('templates/default/js/jquery.scrollbar.js'); ?> +
    +
  • +
  • +
  • +
+
+
+
+
+
+
+
+
+
+
+ \ No newline at end of file diff --git a/templates/default/controllers/admin/index_news_data.tpl.php b/templates/default/controllers/admin/index_news_data.tpl.php new file mode 100755 index 000000000..9a28319bd --- /dev/null +++ b/templates/default/controllers/admin/index_news_data.tpl.php @@ -0,0 +1,26 @@ + \ No newline at end of file diff --git a/templates/default/controllers/admin/index_resources.tpl.php b/templates/default/controllers/admin/index_resources.tpl.php index 1f533cfac..35d5c05b4 100755 --- a/templates/default/controllers/admin/index_resources.tpl.php +++ b/templates/default/controllers/admin/index_resources.tpl.php @@ -8,7 +8,6 @@
-*/ ?> +*/ ?>