diff --git a/plugins/indikator/blogstat/LICENCE.md b/plugins/indikator/blogstat/LICENCE.md new file mode 100644 index 000000000..38cee799e --- /dev/null +++ b/plugins/indikator/blogstat/LICENCE.md @@ -0,0 +1,19 @@ +# MIT license + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/plugins/indikator/blogstat/Plugin.php b/plugins/indikator/blogstat/Plugin.php new file mode 100644 index 000000000..b29a425f4 --- /dev/null +++ b/plugins/indikator/blogstat/Plugin.php @@ -0,0 +1,64 @@ + 'indikator.blogstat::lang.plugin.name', + 'description' => 'indikator.blogstat::lang.plugin.description', + 'author' => 'indikator.blogstat::lang.plugin.author', + 'icon' => 'icon-area-chart', + 'homepage' => 'https://github.com/gergo85/oc-blogstat' + ]; + } + + public function boot() + { + Event::listen('backend.menu.extendItems', function($manager) + { + $manager->addSideMenuItems('RainLab.Blog', 'blog', [ + 'statistics' => [ + 'label' => 'indikator.blogstat::lang.menu.statistics', + 'icon' => 'icon-area-chart', + 'code' => 'statistics', + 'owner' => 'Indikator.BlogStat', + 'url' => Backend::url('indikator/blogstat/statistics') + ] + ]); + }); + } + + public function registerReportWidgets() + { + return [ + 'Indikator\BlogStat\ReportWidgets\Posts' => [ + 'label' => 'indikator.blogstat::lang.widget.posts', + 'context' => 'dashboard', + 'permissions' => ['indikator.blogstat.statistics'] + ], + 'Indikator\BlogStat\ReportWidgets\Categories' => [ + 'label' => 'indikator.blogstat::lang.widget.categories', + 'context' => 'dashboard', + 'permissions' => ['indikator.blogstat.statistics'] + ] + ]; + } + + public function registerPermissions() + { + return [ + 'indikator.blogstat.statistics' => [ + 'tab' => 'rainlab.blog::lang.blog.tab', + 'label' => 'indikator.blogstat::lang.permission.statistics', + 'roles' => ['publisher'] + ] + ]; + } +} diff --git a/plugins/indikator/blogstat/README.md b/plugins/indikator/blogstat/README.md new file mode 100644 index 000000000..4698ddd70 --- /dev/null +++ b/plugins/indikator/blogstat/README.md @@ -0,0 +1,37 @@ +# Statistics and Graphs for Blog +This plugin extend the [RainLab Blog](https://github.com/rainlab/blog-plugin) to beautiful graphs and useful dashboard widgets. + +## Main features +* Add interactive graphs +* Add dashboard widgets + +## Statistics and graphs +* Graph - Posts in this year +* Graph - Posts in last year +* List - TOP 10 longest posts +* List - TOP 10 shortest posts + +## Available widgets +* Post statistics +* Category statistics + +## Available languages +* en - English +* de - Deutsch +* ru - Pу́сский +* hu - Magyar +* pl - Polski + +## Installation +1. Go to the __Settings > Updates & Plugins__ page in the Backend. +1. Click on the __Install plugins__ button. +1. Type the __Blog Stat__ text in the search field. + +## Add backend widgets +1. Go to the __Dashboard__ page in the Backend. +1. Click on the __Manage widgets > Add widget__ button. +1. Select the any __Blog widgets__ from the list. + +## Credits +* [Morris.js](http://morrisjs.github.io/morris.js) +* [Raphaël JS](http://dmitrybaranovskiy.github.io/raphael) diff --git a/plugins/indikator/blogstat/assets/css/statistics.css b/plugins/indikator/blogstat/assets/css/statistics.css new file mode 100644 index 000000000..e0d25eba9 --- /dev/null +++ b/plugins/indikator/blogstat/assets/css/statistics.css @@ -0,0 +1,40 @@ +.statboard .statbox { + background: #fff; + -webkit-box-shadow: 3px 3px 11px 0 rgba(217, 217, 217, 1); + -moz-box-shadow: 3px 3px 11px 0 rgba(217, 217, 217, 1); + box-shadow: 3px 3px 11px 0 rgba(217, 217, 217, 1); + margin: 10px 0 20px 0; + padding: 0 20px; +} + +.statboard h4 { + border-bottom: 1px solid #cae1e2; + margin: 25px 0; + padding-bottom: 5px; +} + +.morris-hover { + position: absolute; + z-index: 1000 +} + +.morris-hover.morris-default-style { + background: rgba(255,255,255,0.8); + border: solid 2px rgba(230,230,230,0.8); + border-radius: 10px; + color: #666; + font-family: sans-serif; + font-size: 12px; + padding: 6px; + text-align:center; +} + +.morris-hover.morris-default-style .morris-hover-row-label { + font-weight: bold; + margin: 0.25em 0; +} + +.morris-hover.morris-default-style .morris-hover-point { + margin: 0.1em 0; + white-space: nowrap; +} diff --git a/plugins/indikator/blogstat/composer.json b/plugins/indikator/blogstat/composer.json new file mode 100644 index 000000000..79d9ffeab --- /dev/null +++ b/plugins/indikator/blogstat/composer.json @@ -0,0 +1,11 @@ +{ + "name": "indikator/blogstat-plugin", + "type": "october-plugin", + "description": "This plugin extend the RainLab Blog to beautiful graphs and useful dashboard widgets.", + "homepage": "https://octobercms.com/plugin/indikator-blogstat", + "keywords": ["october", "octobercms", "blog"], + "license": "MIT", + "require": { + "composer/installers": "~1.0" + } +} \ No newline at end of file diff --git a/plugins/indikator/blogstat/controllers/Statistics.php b/plugins/indikator/blogstat/controllers/Statistics.php new file mode 100644 index 000000000..145cde794 --- /dev/null +++ b/plugins/indikator/blogstat/controllers/Statistics.php @@ -0,0 +1,130 @@ +pageTitle = 'indikator.blogstat::lang.menu.statistics'; + + $this->addCss('/plugins/indikator/blogstat/assets/css/statistics.css'); + + $this->vars['countPost'] = Post::count(); + $this->vars['countCategory'] = Category::count(); + + $this->getGraphs(); + $this->getPostsInfo(); + $this->getLongestPosts(); + $this->getShortestPosts(); + } + + public function getGraphs() + { + $this->vars['thisYear'] = $this->vars['lastYear'] = array_fill(0, 13, 0); + $this->vars['now'] = date('Y'); + + $blog = Post::where('published_at', '>', 0)->get(); + + foreach ($blog as $item) { + $year = substr($item->published_at, 0, 4); + + if ($year == $this->vars['now']) { + $this->vars['thisYear'][(int)substr($item->published_at, 5, 2)]++; + } + + else if ($year == $this->vars['now'] - 1) { + $this->vars['lastYear'][(int)substr($item->published_at, 5, 2)]++; + $this->vars['lastYear'][0]++; + } + } + } + + public function getPostsInfo() + { + $blog = Post::get(); + $this->vars['length'] = $this->vars['title'] = []; + + foreach ($blog as $item) { + $this->vars['length'][$item->id] = strlen(trim(preg_replace('/\s+/', ' ', strip_tags($item->excerpt.$item->content)))); + $this->vars['title'][$item->id] = $item->title; + } + } + + public function getLongestPosts() + { + $length = $this->vars['length']; + $title = $this->vars['title']; + + arsort($length); + + $this->vars['longest'] = ''; + $index = 1; + + foreach ($length as $id => $value) { + $this->vars['longest'] .= ' +
+ '.$index.'. +
+
+ '.$title[$id].' +
+
+ '.number_format($value, 0, '.', ' ').' +
+
+ '; + + if ($index == 10) { + break; + } + + $index++; + } + } + + public function getShortestPosts() + { + $length = $this->vars['length']; + $title = $this->vars['title']; + + asort($length); + + $this->vars['shortest'] = ''; + $index = 1; + + foreach ($length as $id => $value) { + $this->vars['shortest'] .= ' +
+ '.$index.'. +
+
+ '.$title[$id].' +
+
+ '.number_format($value, 0, '.', ' ').' +
+
+ '; + + if ($index == 10) { + break; + } + + $index++; + } + } +} diff --git a/plugins/indikator/blogstat/controllers/statistics/index.htm b/plugins/indikator/blogstat/controllers/statistics/index.htm new file mode 100644 index 000000000..4a7a9b610 --- /dev/null +++ b/plugins/indikator/blogstat/controllers/statistics/index.htm @@ -0,0 +1,372 @@ +
+ +
+ +
+
+
+
+
+ +
+
+ 0): ?> + +
+ +
+
+
+
+
+ +

+ +
+ +

+ +
+
+
+
+
+ + + + diff --git a/plugins/indikator/blogstat/lang/de/lang.php b/plugins/indikator/blogstat/lang/de/lang.php new file mode 100644 index 000000000..2096116ae --- /dev/null +++ b/plugins/indikator/blogstat/lang/de/lang.php @@ -0,0 +1,33 @@ + [ + 'name' => 'Blog Statistiken und Grafiken', + 'description' => 'Erweitertes Plugin für RainLab Blog.', + 'author' => 'Gergő Szabó' + ], + 'menu' => [ + 'statistics' => 'Statistiken', + 'posts' => 'Post|Post', + 'categories' => 'Kategorie|Kategorien' + ], + 'stat' => [ + 'longest' => 'Am längsten', + 'shortest' => 'Kürzeste' + ], + 'widget' => [ + 'posts' => 'Blog - Post', + 'categories' => 'Blog - Kategorien', + 'show_total' => 'Zeige gesamte', + 'show_active' => 'Zeige aktiv', + 'show_inactive' => 'Zeige inaktiv', + 'show_empty' => 'Zeige leer', + 'total' => 'Gesamt', + 'active' => 'Aktiv', + 'inactive' => 'Inaktiv', + 'empty' => 'Leer' + ], + 'permission' => [ + 'statistics' => 'Statistiken anzeigen' + ] +]; diff --git a/plugins/indikator/blogstat/lang/en/lang.php b/plugins/indikator/blogstat/lang/en/lang.php new file mode 100644 index 000000000..17cdad622 --- /dev/null +++ b/plugins/indikator/blogstat/lang/en/lang.php @@ -0,0 +1,33 @@ + [ + 'name' => 'Blog Stats & Graphs', + 'description' => 'Extended plugin for RainLab Blog.', + 'author' => 'Gergő Szabó' + ], + 'menu' => [ + 'statistics' => 'Statistics', + 'posts' => 'Post|Posts', + 'categories' => 'Category|Categories' + ], + 'stat' => [ + 'longest' => 'Longest', + 'shortest' => 'Shortest' + ], + 'widget' => [ + 'posts' => 'Blog - Posts', + 'categories' => 'Blog - Categories', + 'show_total' => 'Show total', + 'show_active' => 'Show active', + 'show_inactive' => 'Show inactive', + 'show_empty' => 'Show empty', + 'total' => 'Total', + 'active' => 'Active', + 'inactive' => 'Inactive', + 'empty' => 'Empty' + ], + 'permission' => [ + 'statistics' => 'View statistics' + ] +]; diff --git a/plugins/indikator/blogstat/lang/hu/lang.php b/plugins/indikator/blogstat/lang/hu/lang.php new file mode 100644 index 000000000..970d359c6 --- /dev/null +++ b/plugins/indikator/blogstat/lang/hu/lang.php @@ -0,0 +1,33 @@ + [ + 'name' => 'Blog statisztika', + 'description' => 'Kiegészítő a hivatalos Blog bővítményhez.', + 'author' => 'Szabó Gergő' + ], + 'menu' => [ + 'statistics' => 'Statisztika', + 'posts' => 'Bejegyzés|Bejegyzés', + 'categories' => 'Kategória|Kategória' + ], + 'stat' => [ + 'longest' => 'Leghosszabb', + 'shortest' => 'Legrövidebb' + ], + 'widget' => [ + 'posts' => 'Blog - Bejegyzések', + 'categories' => 'Blog - Kategóriák', + 'show_total' => 'Összes mutatása', + 'show_active' => 'Aktívak mutatása', + 'show_inactive' => 'Inaktívak mutatása', + 'show_empty' => 'Üresek mutatása', + 'total' => 'Összes', + 'active' => 'Aktív', + 'inactive' => 'Inaktív', + 'empty' => 'Üres' + ], + 'permission' => [ + 'statistics' => 'Statisztika megtekintése' + ] +]; diff --git a/plugins/indikator/blogstat/lang/pl/lang.php b/plugins/indikator/blogstat/lang/pl/lang.php new file mode 100644 index 000000000..7544066b0 --- /dev/null +++ b/plugins/indikator/blogstat/lang/pl/lang.php @@ -0,0 +1,33 @@ + [ + 'name' => 'Blog Statystyki i wykresy', + 'description' => 'Extended plugin for RainLab Blog.', + 'author' => 'Gergő Szabó' + ], + 'menu' => [ + 'statistics' => 'Statystyka', + 'posts' => 'post|blogach', + 'categories' => 'kategoria|Kategorie' + ], + 'stat' => [ + 'longest' => 'Najdłuższy', + 'shortest' => 'Najkrótsza' + ], + 'widget' => [ + 'posts' => 'Aktualności - Posty', + 'categories' => 'Aktualności - Kategorie', + 'show_total' => 'Pokaż wszystkie', + 'show_active' => 'Pokaż aktywne', + 'show_inactive' => 'Pokaż nieaktywne', + 'show_empty' => 'Pokaż pusty', + 'total' => 'Razem', + 'active' => 'Aktywny', + 'inactive' => 'Nieaktywny', + 'empty' => 'Pusty' + ], + 'permission' => [ + 'statistics' => 'Zobacz statystyki' + ] +]; diff --git a/plugins/indikator/blogstat/lang/ru/lang.php b/plugins/indikator/blogstat/lang/ru/lang.php new file mode 100644 index 000000000..404fa657a --- /dev/null +++ b/plugins/indikator/blogstat/lang/ru/lang.php @@ -0,0 +1,33 @@ + [ + 'name' => 'Блог Статистика и Графики', + 'description' => 'Extended plugin for RainLab Blog.', + 'author' => 'Gergő Szabó' + ], + 'menu' => [ + 'statistics' => 'Статистика', + 'posts' => '{0} Записей|{1} Запись|[2,4] Записи|[5,Inf] Записей', + 'categories' => '{1} категория|[2,4] категории|[5,Inf] категорий' + ], + 'stat' => [ + 'longest' => 'Cамый длинный', + 'shortest' => 'Cамый короткий' + ], + 'widget' => [ + 'posts' => 'Блог - Посты', + 'categories' => 'Блог - Категории', + 'show_total' => 'Показать все', + 'show_active' => 'Показать активные', + 'show_inactive' => 'Показать неактивные', + 'show_empty' => 'Показать пустой', + 'total' => 'Всего', + 'active' => 'Активных', + 'inactive' => 'Неактивных', + 'empty' => 'пустой' + ], + 'permission' => [ + 'statistics' => 'Просмотр статистики' + ] +]; diff --git a/plugins/indikator/blogstat/reportwidgets/Categories.php b/plugins/indikator/blogstat/reportwidgets/Categories.php new file mode 100644 index 000000000..da4b0eeec --- /dev/null +++ b/plugins/indikator/blogstat/reportwidgets/Categories.php @@ -0,0 +1,60 @@ +loadData(); + } + catch (Exception $ex) { + $this->vars['error'] = $ex->getMessage(); + } + + return $this->makePartial('widget'); + } + + public function defineProperties() + { + return [ + 'title' => [ + 'title' => 'backend::lang.dashboard.widget_title_label', + 'default' => 'rainlab.blog::lang.blog.categories', + 'type' => 'string', + 'validationPattern' => '^.+$', + 'validationMessage' => 'backend::lang.dashboard.widget_title_error' + ], + 'total' => [ + 'title' => 'indikator.blogstat::lang.widgets.show_total', + 'default' => true, + 'type' => 'checkbox' + ], + 'empty' => [ + 'title' => 'indikator.blogstat::lang.widgets.show_empty', + 'default' => true, + 'type' => 'checkbox' + ] + ]; + } + + protected function loadData() + { + $this->vars['total'] = Category::count(); + + $empty = 0; + $categories = Category::all(); + + foreach ($categories as $category) { + if (Db::table('rainlab_blog_posts_categories')->where('category_id', $category->id)->count() == 0) { + $empty++; + } + } + + $this->vars['empty'] = $empty; + } +} diff --git a/plugins/indikator/blogstat/reportwidgets/Posts.php b/plugins/indikator/blogstat/reportwidgets/Posts.php new file mode 100644 index 000000000..4c72fc3db --- /dev/null +++ b/plugins/indikator/blogstat/reportwidgets/Posts.php @@ -0,0 +1,55 @@ +loadData(); + } + catch (Exception $ex) { + $this->vars['error'] = $ex->getMessage(); + } + + return $this->makePartial('widget'); + } + + public function defineProperties() + { + return [ + 'title' => [ + 'title' => 'backend::lang.dashboard.widget_title_label', + 'default' => 'rainlab.blog::lang.blog.posts', + 'type' => 'string', + 'validationPattern' => '^.+$', + 'validationMessage' => 'backend::lang.dashboard.widget_title_error' + ], + 'total' => [ + 'title' => 'indikator.blogstat::lang.widgets.show_total', + 'default' => true, + 'type' => 'checkbox' + ], + 'active' => [ + 'title' => 'indikator.blogstat::lang.widgets.show_active', + 'default' => true, + 'type' => 'checkbox' + ], + 'inactive' => [ + 'title' => 'indikator.blogstat::lang.widgets.show_inactive', + 'default' => true, + 'type' => 'checkbox' + ] + ]; + } + + protected function loadData() + { + $this->vars['active'] = Post::where('published', true)->count(); + $this->vars['inactive'] = Post::where('published', false)->count(); + $this->vars['total'] = $this->vars['active'] + $this->vars['inactive']; + } +} diff --git a/plugins/indikator/blogstat/reportwidgets/categories/partials/_widget.htm b/plugins/indikator/blogstat/reportwidgets/categories/partials/_widget.htm new file mode 100644 index 000000000..3f34152de --- /dev/null +++ b/plugins/indikator/blogstat/reportwidgets/categories/partials/_widget.htm @@ -0,0 +1,25 @@ +
+

property('title'))) ?>

+ + +
+ +
+ + +

+ +
diff --git a/plugins/indikator/blogstat/reportwidgets/posts/partials/_widget.htm b/plugins/indikator/blogstat/reportwidgets/posts/partials/_widget.htm new file mode 100644 index 000000000..44f62365a --- /dev/null +++ b/plugins/indikator/blogstat/reportwidgets/posts/partials/_widget.htm @@ -0,0 +1,31 @@ +
+

property('title'))) ?>

+ + +
+ +
+ + +

+ +
diff --git a/plugins/indikator/blogstat/updates/version.yaml b/plugins/indikator/blogstat/updates/version.yaml new file mode 100644 index 000000000..59853b139 --- /dev/null +++ b/plugins/indikator/blogstat/updates/version.yaml @@ -0,0 +1,7 @@ +1.0.0: First version of Blog Stats & Graphs. +1.0.1: Added more post statistics. +1.0.2: Minor improvements and bugfix. +1.0.3: Redesigned the report widgets. +1.0.4: !!! Updated for October 420+. +1.0.5: Minor visual and code improvements. +1.0.6: Added permission to Dashboard widgets. diff --git a/plugins/rainlab/blog/controllers/posts/config_filter.yaml b/plugins/rainlab/blog/controllers/posts/config_filter.yaml index 7c8b36851..49e6e5612 100644 --- a/plugins/rainlab/blog/controllers/posts/config_filter.yaml +++ b/plugins/rainlab/blog/controllers/posts/config_filter.yaml @@ -4,6 +4,13 @@ scopes: + id: + label: Id Post + type: text + modelClass: RainLab\Blog\Models\Post + scope: FilterId + # conditions: id in (:filtered) + category: # Filter name @@ -41,7 +48,7 @@ scopes: # SQL Conditions conditions: created_at >= ':after' AND created_at <= ':before' - + language: # Filter name @@ -55,9 +62,9 @@ scopes: # Apply query scope scope: FilterLocale - + # options options: ru: RU en: EN - tm: TM \ No newline at end of file + tm: TM diff --git a/plugins/rainlab/blog/models/Post.php b/plugins/rainlab/blog/models/Post.php index 7dc2cd337..57b67c694 100644 --- a/plugins/rainlab/blog/models/Post.php +++ b/plugins/rainlab/blog/models/Post.php @@ -176,13 +176,13 @@ class Post extends Model }else{ $fields->type_post->hidden = true; } - + if($this->category_groups->where('type', 'media')->count()){ $fields->video_file->hidden = false; }else{ $fields->video_file->hidden = true; } - + if($this->category_groups->where('type', 'afisha')->count()){ $fields->afisha_phone->hidden = false; $fields->afisha_address->hidden = false; @@ -386,10 +386,10 @@ class Post extends Model if ($typePost !==null) { $typePost = is_array($typePost) ? $typePost : [$typePost]; - + $query->whereIn('type_post',$typePost); } - + // if ($groupId !==null) { @@ -400,11 +400,11 @@ class Post extends Model if(isset($featured)){ $query-> where('featured',$featured); } - + if(isset($morque)){ $query-> where('on_morque',$morque); } - + $date = trim($date); if(strtotime($date)){ @@ -532,6 +532,11 @@ class Post extends Model }); } + public function scopeFilterId($query, $id) + { + return $query->where('id', $id); + } + public function scopeFilterLocale($query, array $types) { foreach ($types as $type) { switch ($type) {