diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..48e341a09 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,3 @@ +{ + "lockfileVersion": 1 +} diff --git a/www/application/classes/Controller/Admin.php b/www/application/classes/Controller/Admin.php index 4c7f35d3d..99a287072 100644 --- a/www/application/classes/Controller/Admin.php +++ b/www/application/classes/Controller/Admin.php @@ -207,12 +207,28 @@ public function scripts_resetArticlesTimeline() $articles[$key] = $article; } + $courses = Model_Courses::getActiveCourses(); + + /** rebuld array*/ + foreach ($courses as $key => $value) { + $course = array( + 'id' => $courses[$key]->id, + 'dt_create' => $courses[$key]->dt_publish, + ); + $courses[$key] = $course; + } + // #TODO add to $feed array with courses later - $feed = new Model_Feed_Articles('article'); - $feed->clear(); - $feed->init($articles); + $feed_articles = new Model_Feed_Articles('article'); + $feed_courses = new Model_Feed_Articles('course'); + + $feed_articles->clear(); + $feed_courses->clear(); + + $feed_articles->init($articles); + $feed_courses->init($courses); - return 'Articles timeline was successfully updated'; + return 'Articles and Courses timeline was successfully updated'; } /** diff --git a/www/application/classes/Controller/Articles/Index.php b/www/application/classes/Controller/Articles/Index.php index 7ac4a1175..e86bb35a3 100644 --- a/www/application/classes/Controller/Articles/Index.php +++ b/www/application/classes/Controller/Articles/Index.php @@ -127,20 +127,27 @@ public function action_show() */ public function getFeed() { + $cacheKey = LANG . ':articles-feed'; + $cached = $this->memcache->get($cacheKey); + + if ($cached) { + return $cached; + } + /** * Prepare Feed model */ $feed = new Model_Feed_Articles(); /** - * Get all published articles + * Get articles and courses feed items */ $feed_items = $feed->get(); /** - * List of published articles ids + * List of published feed items ids */ - $published_articles_id_array = array(); + $published_feed_items_ids = array(); /** * Items to be removed from articles list @@ -152,9 +159,9 @@ public function getFeed() $feed_item->coauthor = Model_User::get($coauthorship->user_id); /** - * Fill up list of available articles + * Fill up list of available feed items */ - array_push($published_articles_id_array, $feed_item->id); + array_push($published_feed_items_ids, $feed_item->id); /** * If article was linked to another one and it's lang is not equal @@ -170,11 +177,13 @@ public function getFeed() * Remove copies of articles if eng and rus version are available */ foreach ($items_to_be_deleted as $index => $item_to_be_deleted) { - if (!empty($item_to_be_deleted->linked_article) && in_array($item_to_be_deleted->linked_article, $published_articles_id_array)) { + if (!empty($item_to_be_deleted->linked_article) && in_array($item_to_be_deleted->linked_article, $published_feed_items_ids)) { unset($feed_items[$index]); } } + $this->memcache->set($cacheKey, $feed_items); + return $feed_items; } @@ -227,10 +236,12 @@ private function getArticlesFromCourse($articleId, $courseId) * search in array of article ids the position of current article */ $counter = 0; + $position = 0; + foreach ($course_articles as $articles) { - $articleList[] = Model_Article::get($articles['article_id']); + $articleList[] = Model_Article::get($articles->id); - if ($articles['article_id'] == $articleId) { + if ($articles->id == $articleId) { $position = $counter; } @@ -242,14 +253,14 @@ private function getArticlesFromCourse($articleId, $courseId) * If next or previous article exists, then we send it to view */ if ($position + 1 < count($course_articles)) { - $nextArticleId = $course_articles[$position + 1]['article_id']; + $nextArticleId = $course_articles[$position + 1]->id; $nextArticle = Model_Article::get($nextArticleId); $this->view["nextArticle"] = $nextArticle; } if ($position - 1 >= 0) { - $previousArticleId = $course_articles[$position - 1]['article_id']; + $previousArticleId = $course_articles[$position - 1]->id; $previousArticle = Model_Article::get($previousArticleId); $this->view["previousArticle"] = $previousArticle; diff --git a/www/application/classes/Controller/Articles/Modify.php b/www/application/classes/Controller/Articles/Modify.php index 38129d646..e0a2a6cd8 100644 --- a/www/application/classes/Controller/Articles/Modify.php +++ b/www/application/classes/Controller/Articles/Modify.php @@ -243,7 +243,9 @@ public function action_save() $courses_to_delete = array_diff($current_courses, $courses_ids); $courses_to_add = array_diff($courses_ids, $current_courses); - Model_Courses::deleteArticles($article->id, $courses_to_delete); + if ($courses_to_delete) { + Model_Courses::deleteArticles($article->id, $courses_to_delete); + } foreach ($courses_to_add as $course_id) { Model_Courses::addArticle($article->id, $course_id); @@ -267,6 +269,10 @@ public function action_save() $recentArticlesFeed->remove($article->id); } + // Очистка кэша фидов + $this->memcache->delete('en:articles-feed'); + $this->memcache->delete('ru:articles-feed'); + // Если поле uri пустое, то редиректить на обычный роут /article/id $redirect = ($uri) ? '/' . $article->uri : '/article/' . $article->id; diff --git a/www/application/classes/Controller/Courses/Index.php b/www/application/classes/Controller/Courses/Index.php index 53c94d45f..a698d39de 100644 --- a/www/application/classes/Controller/Courses/Index.php +++ b/www/application/classes/Controller/Courses/Index.php @@ -5,6 +5,7 @@ class Controller_Courses_Index extends Controller_Base_preDispatch public function action_show() { $courseId = $this->request->param('id') ?: $this->request->query('id'); + $isAlias = $this->request->query('id'); $course = Model_Courses::get($courseId); @@ -12,6 +13,12 @@ public function action_show() throw new HTTP_Exception_404(); } + if (!empty($courseId)) { + if ($course->uri && !$isAlias) { + $this->redirect($course->uri); + } + } + $this->view["course"] = $course; $this->title = $course->title; @@ -19,4 +26,4 @@ public function action_show() $this->template->content = View::factory('templates/courses/course', $this->view); } -} +} \ No newline at end of file diff --git a/www/application/classes/Controller/Courses/Modify.php b/www/application/classes/Controller/Courses/Modify.php index 246001bb7..35b1e960e 100644 --- a/www/application/classes/Controller/Courses/Modify.php +++ b/www/application/classes/Controller/Courses/Modify.php @@ -77,6 +77,9 @@ public function action_save() } else { $insertedId = $course->insert(); $course->uri = Model_Aliases::addAlias($alias, Aliases_Controller::COURSE, $insertedId); + // If course is published right after creation set 'dt_publish' immediately + $course->dt_publish = $course->is_published ? date('Y-m-d H:i:s') : null; + $course->update(); } if ($course->is_published && !$course->is_removed) { diff --git a/www/application/classes/Model/Article.php b/www/application/classes/Model/Article.php index 1aced6d74..921f30dde 100644 --- a/www/application/classes/Model/Article.php +++ b/www/application/classes/Model/Article.php @@ -199,6 +199,16 @@ public static function get($id = 0, $needClearCache = false) return $model->fillByRow($article); } + /** + * Checks whether or not article is included in any course + * @param int $article_id - article's id + * @return bool + */ + public static function isIncludedInCourse(int $article_id) { + $article = self::get($article_id); + return (bool) Model_Courses::getCoursesByArticleId($article); + } + /** * Links article to other one * @param integer $idArticleToLink - articles's ID to link if empty, unlink article diff --git a/www/application/classes/Model/Courses.php b/www/application/classes/Model/Courses.php index aa0ad373a..ced8fd801 100644 --- a/www/application/classes/Model/Courses.php +++ b/www/application/classes/Model/Courses.php @@ -15,6 +15,8 @@ class Model_Courses extends Model public $description; public $cover; public $is_big_cover; + public $course_articles = []; + public $course_authors = []; public $dt_publish; public $dt_create; public $dt_update; @@ -83,6 +85,9 @@ private function fillByRow($course_row) } } + $this->course_articles = self::getArticles($this->id); + $this->course_authors = $this->getUniqueCourseAuthors(); + return $this; } @@ -182,7 +187,7 @@ public static function deleteArticles($article_id, $courses_ids = 0) { $deleteQuery = Dao_CoursesArticles::delete()->where('article_id', '=', $article_id); - if (!$courses_ids) { + if ($courses_ids === 0) { return $deleteQuery->execute(); } @@ -215,13 +220,32 @@ public static function get($id = 0, $needClearCache = false) } /** - * Получить все активные (опубликованные и не удалённые курсы) в порядке убывания ID. + * Return + * a) All published courses to output them on Article editing page + * b) All published courses, containing at least one Article to show in feed + * + * @return Model_Courses[] - array of Model_Courses */ - public static function getActiveCourses($clearCache = false) + public static function getActiveCourses($clearCache = false, $excludeCoursesWithoutArticles = false) { - return Model_Courses::getCourses(false, false, !$clearCache ? Date::MINUTE * 5 : null); - } + $active_courses = Model_Courses::getCourses(false, false, !$clearCache ? Date::MINUTE * 5 : null); + $courses_with_articles = array(); + + if ($excludeCoursesWithoutArticles) { + + foreach ($active_courses as $course) { + if (self::getArticles($course->id)) { + $courses_with_articles[] = $course; + } + } + + return $courses_with_articles; + + } else { + return $active_courses; + } + } /** * Получить все неудалённые курсы в порядке убывания ID. @@ -284,10 +308,9 @@ private static function rowsToModels($course_rows) } /** - * Получить id статей, входящих в курс - * - * @param $course_id - * @return bool|object + * Get Articles from Course + * @param [int] $courseId - ID of Course + * @return Model_Article[] - Array of Articles */ public static function getArticles($course_id) { @@ -295,6 +318,64 @@ public static function getArticles($course_id) return false; } - return Dao_CoursesArticles::select('article_id')->where('course_id', '=', $course_id)->execute(); + $articles_ids = Dao_CoursesArticles::select('article_id')->where('course_id', '=', $course_id)->execute(); + + /** $articleList - empty array. Needs to fill by article ids */ + $articleList = array(); + + /** + * If Course has Articles + */ + if ($articles_ids) { + foreach ($articles_ids as $article) { + $course_article = Model_Article::get($article['article_id']); + + /** + * Show only published Articles in Course + */ + if ($course_article->is_published) { + $articleList[] = $course_article; + } + } + /** Get Articles with Coauthors to display on Course Page */ + foreach ($articleList as $article) { + $coauthorship = new Model_Coauthors($article->id); + $article->coauthor = Model_User::get($coauthorship->user_id); + } + } + + return $articleList; + } + + /** + * Checks whether or not course contains any articles + * @param $course_id - course's id + * @return bool + */ + public static function containsArticles(int $course_id) { + return (bool) self::getArticles($course_id); + } + + /** + * Return unique article authors from the Course + * @param Model_Article[] - Articles included in specific Course + * @return Model_User[] - Array of unique Course authors + */ + public function getUniqueCourseAuthors() + { + $course_articles = self::getArticles($this->id); + $course_authors_ids = array(); + $course_authors = array(); + + foreach ($course_articles as $article) { + $author_id = $article->author->id; + + if (!in_array($author_id, $course_authors_ids)) + { + $course_authors_ids[] = $author_id; + $course_authors[] = Model_User::get($author_id); + } + } + return $course_authors; } } diff --git a/www/application/classes/Model/Feed/Articles.php b/www/application/classes/Model/Feed/Articles.php index db1ff8500..d52bbe535 100644 --- a/www/application/classes/Model/Feed/Articles.php +++ b/www/application/classes/Model/Feed/Articles.php @@ -38,11 +38,15 @@ public function get($numberOfItems = 0, $offset = 0) switch ($prefix) { case Model_Article::FEED_PREFIX: - $models_list[] = Model_Article::get($id); + if (!Model_Article::isIncludedInCourse($id)) { + $models_list[] = Model_Article::get($id); + } break; case Model_Courses::FEED_PREFIX: - $models_list[] = Model_Courses::get($id); + if (Model_Courses::containsArticles($id)) { + $models_list[] = Model_Courses::get($id); + } break; default: diff --git a/www/application/config/system-aliases.php b/www/application/config/system-aliases.php index a145c1205..d10624cca 100644 --- a/www/application/config/system-aliases.php +++ b/www/application/config/system-aliases.php @@ -9,6 +9,7 @@ '', 'ajax', 'admin', + 'ajax', 'article', 'articles', 'auth', diff --git a/www/application/views/templates/admin/articles/feed.php b/www/application/views/templates/admin/articles/feed.php index 17917f9d4..c6c7a522c 100644 --- a/www/application/views/templates/admin/articles/feed.php +++ b/www/application/views/templates/admin/articles/feed.php @@ -2,14 +2,14 @@ $link = ($mode == 'list')?'cards':'list' ?>
-= View::factory('templates/admin/articles/feed_list', array( 'feed' => $feed )); ?> \ No newline at end of file += View::factory('templates/admin/articles/feed_list', array( 'feed' => $feed )); ?> diff --git a/www/application/views/templates/admin/users/list.php b/www/application/views/templates/admin/users/list.php index bb1417de9..b11a15915 100644 --- a/www/application/views/templates/admin/users/list.php +++ b/www/application/views/templates/admin/users/list.php @@ -59,7 +59,7 @@ endif; ?>