diff --git a/classes/Controller/API/Page/Tags.php b/classes/Controller/API/Page/Tags.php new file mode 100644 index 0000000..111d117 --- /dev/null +++ b/classes/Controller/API/Page/Tags.php @@ -0,0 +1,3 @@ + + * @link http://kodicms.ru + * @copyright (c) 2012-2014 butschster + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt + */ +class KodiCMS_Controller_API_Page_Tags extends Controller_System_Api { + + public function get_get() + { + $uids = $this->param('uids'); + + $tags = Model_API::factory('api_page_tag') + ->get_all($uids, $this->fields); + + $this->response($tags); + } + +} \ No newline at end of file diff --git a/classes/KodiCMS/Model/API/Page/Tag.php b/classes/KodiCMS/Model/API/Page/Tag.php new file mode 100644 index 0000000..310afcb --- /dev/null +++ b/classes/KodiCMS/Model/API/Page/Tag.php @@ -0,0 +1,44 @@ + + * @link http://kodicms.ru + * @copyright (c) 2012-2014 butschster + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt + */ +class KodiCMS_Model_API_Page_Tag extends Model_API { + + protected $_table_name = 'tags'; + + public function get_all($uids, $fields = array(), $page_id = NULL) + { + $uids = $this->prepare_param($uids, array('Valid', 'numeric')); + $fields = $this->prepare_param($fields); + + $tags = DB::select('id', 'name') + ->select_array($this->filtered_fields($fields)) + ->from($this->table_name()); + + if (!empty($uids)) + { + $tags->where('id', 'in', $uids); + } + + if ($page_id !== NULL) + { + $tags + ->join('page_tags', 'left') + ->on('page_tags.tag_id', '=', $this->table_name() . '.id') + ->where('page_tags.page_id', '=', (int) $page_id); + } + + return $tags + ->cache_tags(array('page_tags')) + ->cached((int) Config::get('cache', 'tags')) + ->execute() + ->as_array(); + } + +} \ No newline at end of file diff --git a/classes/KodiCMS/Model/Page/Tag.php b/classes/KodiCMS/Model/Page/Tag.php new file mode 100644 index 0000000..e2dc32d --- /dev/null +++ b/classes/KodiCMS/Model/Page/Tag.php @@ -0,0 +1,135 @@ + + * @link http://kodicms.ru + * @copyright (c) 2012-2014 butschster + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt + */ +class KodiCMS_Model_Page_Tag extends Record +{ + const TABLE_NAME = 'page_tags'; + + /** + * + * @param integer|Model_Page_Front $page_id + * @return array + */ + public static function find_by_page($page_id) + { + if ($page_id instanceof Model_Page_Front) + { + $page_id = $page_id->id(); + } + + return DB::select(array('tags.id', 'id'), array('tags.name', 'tag')) + ->from(array(self::tableName(), 'page_tags')) + ->join(array(self::tableName('Model_Tag'), 'tags'), 'left') + ->on('page_tags.tag_id', '=', 'tags.id') + ->where('page_tags.page_id', '=', (int) $page_id) + ->cache_tags(array('page_tags')) + ->cached((int) Config::get('cache', 'tags')) + ->execute() + ->as_array('id', 'tag'); + } + + /** + * + * @param integer|Model_Page_Front $page_id + * @param array $tags + */ + public static function save_by_page($page_id, $tags) + { + if (is_string($tags)) + { + $tags = explode(Model_Tag::SEPARATOR, $tags); + } + + $tags = array_unique(array_map('trim', $tags)); + + $current_tags = Model_Page_Tag::find_by_page($page_id); + + if ($page_id instanceof Model_Page_Front) + { + $page_id = $page_id->id(); + } + + // no tag before! no tag now! ... nothing to do! + if (empty($tags) AND empty($current_tags)) + { + return NULL; + } + + // delete all tags + if (empty($tags)) + { + // update count (-1) of those tags + foreach ($current_tags as $tag) + { + DB::update(Model_Tag::tableName()) + ->set(array('count' => DB::expr('count - 1'))) + ->where('name', '=', $tag) + ->execute(); + } + + Record::deleteWhere(self::tableName(), array( + 'where' => array(array('page_id', '=', (int) $page_id)))); + + Cache::instance()->delete_tag('page_tags'); + } + else + { + $old_tags = array_diff($current_tags, $tags); + $new_tags = array_diff($tags, $current_tags); + + // insert all tags in the tag table and then populate the page_tag table + foreach ($new_tags as $index => $tag_name) + { + if (empty($tag_name)) + { + continue; + } + + $tag = Record::findOneFrom('Model_Tag', array( + 'where' => array( + array('name', '=', $tag_name) + ) + )); + + // try to get it from tag list, if not we add it to the list + if (!($tag instanceof Model_Tag)) + { + $tag = new Model_Tag(array('name' => trim($tag_name))); + } + + $tag->count++; + $tag->save(); + + // create the relation between the page and the tag + $page_tag = new Model_Page_Tag(array('page_id' => (int) $page_id, 'tag_id' => $tag->id)); + $page_tag->save(); + } + + // remove all old tag + foreach ($old_tags as $index => $tag_name) + { + // get the id of the tag + $tag = Record::findOneFrom('Model_Tag', array('where' => array(array('name', '=', $tag_name)))); + + Record::deleteWhere(self::tableName(), array( + 'where' => array( + array('page_id', '=', (int) $page_id), + array('tag_id', '=', $tag->id) + ) + )); + + $tag->count--; + $tag->save(); + } + + Cache::instance()->delete_tag('page_tags'); + } + } +} \ No newline at end of file diff --git a/classes/KodiCMS/Model/Tag.php b/classes/KodiCMS/Model/Tag.php new file mode 100644 index 0000000..30cd15f --- /dev/null +++ b/classes/KodiCMS/Model/Tag.php @@ -0,0 +1,32 @@ + + * @link http://kodicms.ru + * @copyright (c) 2012-2014 butschster + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt + */ +class KodiCMS_Model_Tag extends Record +{ + const TABLE_NAME = 'tags'; + const SEPARATOR = ','; + +// protected $_primary_key = 'name'; + + public static function findAllLike($tag) + { + return Record::findAllFrom(static::calledClass(), array( + 'or_where' => array( + array('name', 'like', '%:query%') + ), + 'order_by' => array( + array('count', 'desc'), + ) + ), + array( + ':query' => DB::expr($tag) + )); + } +} \ No newline at end of file diff --git a/classes/Model/API/Page/Tag.php b/classes/Model/API/Page/Tag.php new file mode 100644 index 0000000..78684fb --- /dev/null +++ b/classes/Model/API/Page/Tag.php @@ -0,0 +1,3 @@ + Date::DAY +); diff --git a/i18n/ru.php b/i18n/ru.php new file mode 100644 index 0000000..1ab1439 --- /dev/null +++ b/i18n/ru.php @@ -0,0 +1,6 @@ + 'Теги (разделитель ":sep")', + 'Tags' => 'Тэги', +); \ No newline at end of file diff --git a/init.php b/init.php new file mode 100644 index 0000000..a3f551e --- /dev/null +++ b/init.php @@ -0,0 +1,40 @@ +post('page_tags'); + + if ($tags !== NULL) + { + Model_Page_Tag::save_by_page($page->id, $tags); + } +}); + +// Загрузка шаблона с тегами в блок с метатегами в редактор страницы +Observer::observe('view_page_edit_meta', function($page) { + echo View::factory('page/tags', array( + 'tags' => Model_Page_Tag::find_by_page($page->id) + )); +}); + +Observer::observe('layout_backend_head_before', function() { + echo ''; +}); + +// При выводе списка стран запускается метод custom_filter и передача в него +// Database_query_builder, в этом обсервере можно дополнять этот запрос +Observer::observe( 'frontpage_custom_filter', function($sql, $page) { + $tags = Context::instance()->get('tag'); + + if (empty($tags)) + { + return; + } + + $sql->join(array(Model_Page_Tag::TABLE_NAME, 'pts'), 'inner') + ->distinct(TRUE) + ->on('pts.page_id', '=', 'page.id') + ->join(array(Model_Tag::TABLE_NAME, 'ts')) + ->on('pts.tag_id', '=', 'ts.id') + ->where('ts.name', 'in', explode(',', $tags)); +}); \ No newline at end of file diff --git a/install/schema.sql b/install/schema.sql new file mode 100644 index 0000000..0d74814 --- /dev/null +++ b/install/schema.sql @@ -0,0 +1,16 @@ +CREATE TABLE IF NOT EXISTS `__TABLE_PREFIX__tags` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(40) NOT NULL, + `count` int(11) unsigned NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `name` (`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `__TABLE_PREFIX__page_tags` ( + `page_id` int(11) unsigned NOT NULL, + `tag_id` int(11) unsigned NOT NULL, + UNIQUE KEY `page_id` (`page_id`,`tag_id`), + KEY `tag_id` (`tag_id`), + CONSTRAINT `__TABLE_PREFIX__page_tags_ibfk_1` FOREIGN KEY (`page_id`) REFERENCES `__TABLE_PREFIX__pages` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `__TABLE_PREFIX__page_tags_ibfk_2` FOREIGN KEY (`tag_id`) REFERENCES `__TABLE_PREFIX__tags` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; \ No newline at end of file diff --git a/views/page/tags.php b/views/page/tags.php new file mode 100644 index 0000000..7e8b41a --- /dev/null +++ b/views/page/tags.php @@ -0,0 +1,8 @@ +
+ Model_Tag::SEPARATOR)); ?> +
+
+ 'tags', 'id' => 'page_tags' + )); ?> +
\ No newline at end of file diff --git a/views/tags/js.php b/views/tags/js.php new file mode 100644 index 0000000..80ffa0b --- /dev/null +++ b/views/tags/js.php @@ -0,0 +1 @@ + \ No newline at end of file