Файл: components/content/model.php
Строк: 560
<?php
/******************************************************************************/
// //
// InstantCMS v1.10 //
// http://www.instantcms.ru/ //
// //
// written by InstantCMS Team, 2007-2012 //
// produced by InstantSoft, (www.instantsoft.ru) //
// //
// LICENSED BY GNU/GPL v2 //
// //
/******************************************************************************/
if(!defined('VALID_CMS')) { die('ACCESS DENIED'); }
class cms_model_content{
public function __construct(){
$this->inDB = cmsDatabase::getInstance();
$this->config = cmsCore::getInstance()->loadComponentConfig('content');
cmsCore::loadLanguage('components/content');
cmsCore::loadLib('tags');
cmsCore::loadLib('karma');
}
/* ==================================================================================================== */
/* ==================================================================================================== */
public static function getDefaultConfig() {
$cfg = array (
'readdesc' => 0,
'is_url_cyrillic' => 0,
'rating' => 1,
'perpage' => 15,
'pt_show' => 1,
'pt_disp' => 1,
'pt_hide' => 1,
'autokeys' => 1,
'img_small_w' => 100,
'img_big_w' => 200,
'img_sqr' => 1,
'img_users' => 1,
'watermark' => 1
);
return $cfg;
}
/* ==================================================================================================== */
/* ==================================================================================================== */
public function getCommentTarget($target, $target_id) {
$result = array();
switch($target){
case 'article': $article = $this->inDB->get_fields('cms_content', "id='{$target_id}'", 'seolink, title');
if (!$article) { return false; }
$result['link'] = $this->getArticleURL(null, $article['seolink']);
$result['title'] = $article['title'];
break;
}
return ($result ? $result : false);
}
/* ==================================================================================================== */
/* ==================================================================================================== */
public function updateRatingHook($target, $item_id, $points) {
if (!$item_id || abs($points)!=1) { return false; }
switch($target){
case 'content':
$sql = "UPDATE cms_content
SET rating = rating + ({$points})
WHERE id = '{$item_id}'";
break;
}
$this->inDB->query($sql);
return true;
}
/* ==================================================================================================== */
/* ==================================================================================================== */
/**
* Возвращает подкатегории категории
* @return array
*/
public function getSubCats($parent_id, $recurse=false, $left_key=0, $right_key=0) {
if($recurse){
$where = "NSLeft > $left_key AND NSRight < $right_key";
} else {
$where = "parent_id = '$parent_id'";
}
$sql = "SELECT *
FROM cms_category
WHERE {$where} AND published = 1";
$result = $this->inDB->query($sql);
if (!$this->inDB->num_rows($result)) { return false; }
while($subcat = $this->inDB->fetch_assoc($result)){
$subcat['content_count'] = $this->getArticleCountFromCat($subcat['NSLeft'], $subcat['NSRight']);
$subcat['url'] = $this->getCategoryURL(null, $subcat['seolink']);
$subcats[] = $subcat;
}
$subcats = cmsCore::callEvent('GET_CONTENT_SUBCATS', $subcats);
return $subcats;
}
/* ==================================================================================================== */
/* ==================================================================================================== */
/**
* Возвращает количество статей в категории и подкатегориях
* @return int
*/
public function getArticleCountFromCat($left_key, $right_key) {
$sql = "SELECT con.id
FROM cms_content con
INNER JOIN cms_category cat ON cat.id = con.category_id AND cat.NSLeft >= '$left_key' AND cat.NSRight <= '$right_key'
WHERE con.published = 1 AND con.is_arhive = 0";
$result = $this->inDB->query($sql);
return $this->inDB->num_rows($result);
}
/* ==================================================================================================== */
/* ==================================================================================================== */
/**
* Возвращает дерево категорий
* @return array
*/
public function getCatsTree() {
$sql = "SELECT cat.id as id,
cat.title as title,
cat.NSLeft as NSLeft,
cat.NSRight as NSRight,
cat.NSLevel as NSLevel,
cat.seolink as seolink
FROM cms_category cat
WHERE cat.NSLevel>0
ORDER BY cat.NSLeft";
$result = $this->inDB->query($sql);
if (!$this->inDB->num_rows($result)) { return false; }
while($subcat = $this->inDB->fetch_assoc($result)){
$subcats[] = $subcat;
}
$subcats = cmsCore::callEvent('GET_CONTENT_CATS_TREE', $subcats);
return $subcats;
}
/* ==================================================================================================== */
/* ==================================================================================================== */
/**
* Возвращает категории, доступные для публикования в них
* @return array
*/
public function getPublicCats() {
$inCore = cmsCore::getInstance();
$inUser = cmsUser::getInstance();
$nested_sets = $inCore->nestedSetsInit('cms_category');
$rootid = $this->inDB->getNsRootCatId('cms_category');
$rs_rows = $nested_sets->SelectSubNodes($rootid);
if ($rs_rows){
while($node = $this->inDB->fetch_assoc($rs_rows)){
if($inUser->is_admin || (cmsCore::checkUserAccess('category', $node['id']) &&
($node['is_public'] ||
($node['modgrp_id'] && $node['modgrp_id'] == $inUser->group_id && cmsUser::isUserCan('content/autoadd'))))){
$subcats[] = $node;
}
}
}
$subcats = cmsCore::callEvent('GET_CONTENT_PUBCATS', $subcats);
return $subcats;
}
/* ==================================================================================================== */
/* ==================================================================================================== */
/**
* Условия выборки
*/
public function whereCatIs($category_id) {
$this->inDB->where("con.category_id = '{$category_id}'");
}
public function whereUserIs($user_id) {
$this->inDB->where("con.user_id = '{$user_id}'");
}
public function whereThisAndNestedCats($left_key, $right_key) {
$this->inDB->where("cat.NSLeft >= '$left_key' AND cat.NSRight <= '$right_key' AND cat.parent_id > 0");
}
/* ==================================================================================================== */
/* ==================================================================================================== */
/**
* Получаем статьи по заданным параметрам
* @return array
*/
public function getArticlesList($only_published=true) {
$today = date("Y-m-d H:i:s");
if ($only_published){
$this->inDB->where("con.published = 1 AND con.pubdate <= '$today' AND (con.is_end=0 OR (con.is_end=1 AND con.enddate >= '$today'))");
}
$sql = "SELECT con.*,
con.pubdate as fpubdate,
cat.title as cat_title, cat.seolink as catseolink,
cat.showdesc,
u.nickname as author,
u.login as user_login
FROM cms_content con
INNER JOIN cms_category cat ON cat.id = con.category_id
LEFT JOIN cms_users u ON u.id = con.user_id
WHERE con.is_arhive = 0
{$this->inDB->where}
{$this->inDB->group_by}
{$this->inDB->order_by}n";
if ($this->inDB->limit){
$sql .= "LIMIT {$this->inDB->limit}";
}
$result = $this->inDB->query($sql);
$this->inDB->resetConditions();
if (!$this->inDB->num_rows($result)) { return false; }
while($article = $this->inDB->fetch_assoc($result)){
$article['fpubdate'] = cmsCore::dateFormat($article['fpubdate']);
$article['tagline'] = cmsTagLine('content', $article['id'], true);
$article['comments'] = cmsCore::getCommentsCount('article', $article['id']);
$article['url'] = $this->getArticleURL(null, $article['seolink']);
$article['cat_url'] = $this->getCategoryURL(null, $article['catseolink']);
$article['image'] = (file_exists(PATH.'/images/photos/small/article'.$article['id'].'.jpg') ? 'article'.$article['id'].'.jpg' : '');
$articles[] = $article;
}
$articles = cmsCore::callEvent('GET_ARTICLES', $articles);
return $articles;
}
/* ==================================================================================================== */
/* ==================================================================================================== */
/**
* Возвращает количество статей по заданным параметрам
* @return int
*/
public function getArticlesCount($only_published=true) {
$today = date("Y-m-d H:i:s");
if ($only_published){
$this->inDB->where("con.published = 1 AND con.pubdate <= '$today'
AND (con.is_end=0 OR (con.is_end=1 AND con.enddate >= '$today'))");
}
$sql = "SELECT 1
FROM cms_content con
INNER JOIN cms_category cat ON cat.id = con.category_id
WHERE con.is_arhive = 0
{$this->inDB->where}
{$this->inDB->group_by} ";
$result = $this->inDB->query($sql);
return $this->inDB->num_rows($result);
}
/* ==================================================================================================== */
/* ==================================================================================================== */
/**
* Переносит просроченые статьи в архив
* @return bool
*/
public function moveArticlesToArchive() {
return $this->inDB->query("UPDATE cms_content SET is_arhive = 1 WHERE is_end = 1 AND enddate < NOW()");
}
/* ==================================================================================================== */
/* ==================================================================================================== */
/**
* Получает статью
* @return array
*/
public function getArticle($id_or_link) {
if(is_numeric($id_or_link)){
$where = "con.id = '$id_or_link'";
} else {
$where = "con.seolink = '$id_or_link'";
}
$sql = "SELECT con.*,
cat.title cat_title, cat.id cat_id, cat.NSLeft as leftkey, cat.NSRight as rightkey, cat.modgrp_id,
cat.showtags as showtags, cat.seolink as catseolink, cat.cost, u.nickname as author, u.login as user_login
FROM cms_content con
INNER JOIN cms_category cat ON cat.id = con.category_id
LEFT JOIN cms_users u ON u.id = con.user_id
WHERE {$where} LIMIT 1";
$result = $this->inDB->query($sql);
if (!$this->inDB->num_rows($result)) { return false; }
$article = $this->inDB->fetch_assoc($result);
return $article;
}
/* ==================================================================================================== */
/* ==================================================================================================== */
/**
* Изменяет порядок статей
* @return bool
*/
public function moveItem($item_id, $cat_id, $dir) {
$sign = $dir>0 ? '+' : '-';
$current = $this->inDB->get_field('cms_content', "id={$item_id}", 'ordering');
if($current === false){ return false; }
if ($dir>0){
//движение вверх
//у элемента следующего за текущим нужно уменьшить порядковый номер
$sql = "UPDATE cms_content
SET ordering = ordering-1
WHERE category_id='{$cat_id}' AND ordering = ({$current}+1)
LIMIT 1";
$this->inDB->query($sql);
}
if ($dir<0){
//движение вниз
//у элемента предшествующего текущему нужно увеличить порядковый номер
$sql = "UPDATE cms_content
SET ordering = ordering+1
WHERE category_id='{$cat_id}' AND ordering = ({$current}-1)
LIMIT 1";
$this->inDB->query($sql);
}
$sql = "UPDATE cms_content
SET ordering = ordering {$sign} 1
WHERE id='{$item_id}'";
$this->inDB->query($sql);
return true;
}
/* ==================================================================================================== */
/* ==================================================================================================== */
/**
* Обновляет ссылки на статьи в категории и вложенных в нее
* Подразумевается, что заголовок категории или поле url изменен заранее
* @return bool
*/
public function updateArticlesSeoLink($cat_id){
// получаем все статьи категории и вложенных в нее
$art = $this->getNestedArticles($cat_id);
if(!$art) { return false; }
foreach($art as $a){
$seolink = $this->getSeoLink($a);
$this->inDB->query("UPDATE cms_content SET seolink='{$seolink}' WHERE id = '{$a['id']}'");
$this->updateContentCommentsLink($a['id']);
}
// Обновляем ссылки меню на статьи
$this->updateContentMenu();
return true;
}
/* ==================================================================================================== */
/* ==================================================================================================== */
/**
* генерирует сеолинк для статьи
* @param array $article Полный массив данных, включая id
* @return str
*/
public function getSeoLink($article){
$seolink = '';
$cat = $this->inDB->getNsCategory('cms_category', $article['category_id']);
$path_list = $this->inDB->getNsCategoryPath('cms_category', $cat['NSLeft'], $cat['NSRight'], 'id, title, NSLevel, seolink, url');
if ($path_list){
foreach($path_list as $pcat){
$seolink .= cmsCore::strToURL(($pcat['url'] ? $pcat['url'] : $pcat['title']), $this->config['is_url_cyrillic']) . '/';
}
}
$seolink .= cmsCore::strToURL(($article['url'] ? $article['url'] : $article['title']), $this->config['is_url_cyrillic']);
if (!empty($article['id'])){
$where = ' AND id<>'.$article['id'];
} else {
$where = '';
}
$is_exists = $this->inDB->get_field('cms_content', "seolink='{$seolink}'".$where, 'id');
if ($is_exists) { $seolink .= '-'.(!empty($article['id']) ? $article['id'] : uniqid()); }
return $seolink;
}
/* ==================================================================================================== */
/* ==================================================================================================== */
/**
* Возвращает урл статьи
* параметр $menuid устаревший, оставлен для совместимости
* @return str
*/
public static function getArticleURL($menuid, $seolink, $page=1){
$page_section = ($page>1 ? '/page-'.$page : '');
$url = '/'.$seolink.$page_section.'.html';
return $url;
}
/* ==================================================================================================== */
/* ==================================================================================================== */
/**
* Возвращает урл категории
* параметр $menuid устаревший, оставлен для совместимости
* @return str
*/
public static function getCategoryURL($menuid, $seolink, $page=1, $pagetag = false){
if (!$pagetag){
$page_section = ($page>1 ? '/page-'.$page : '');
} else {
$page_section = '/page-%page%';
}
$url = '/'.$seolink.$page_section;
return $url;
}
/* ==================================================================================================== */
/* ==================================================================================================== */
/**
* Удаляет статью
* @return bool
*/
public function deleteArticle($id){
cmsCore::callEvent('DELETE_ARTICLE', $id);
$this->inDB->delete('cms_content', "id='$id'", 1);
$this->inDB->delete('cms_tags', "target='content' AND item_id='$id'");
cmsCore::clearAccess($id, 'material');
cmsActions::removeObjectLog('add_article', $id);
@unlink(PATH.'/images/photos/small/article'.$id.'.jpg');
@unlink(PATH.'/images/photos/medium/article'.$id.'.jpg');
cmsCore::deleteRatings('content', $id);
cmsCore::deleteComments('article', $id);
return true;
}
/**
* Удаляет список статей
* @param array $id_list
* @return bool
*/
public function deleteArticles($id_list){
foreach($id_list as $id){
$this->deleteArticle($id);
}
return true;
}
/* ==================================================================================================== */
/* ==================================================================================================== */
/**
* Добавляет статью
* @param array $article
* @return int
*/
public function addArticle($article){
$article = cmsCore::callEvent('ADD_ARTICLE', $article);
if ($article['url']) { $article['url'] = cmsCore::strToURL($article['url'], $this->config['is_url_cyrillic']); }
// получаем значение порядка последней статьи
$last_ordering = (int)$this->inDB->get_field('cms_content', "category_id = '{$article['category_id']}' ORDER BY ordering DESC", 'ordering');
$article['ordering'] = $last_ordering+1;
$article['id'] = $this->inDB->insert('cms_content', $article);
if ($article['id']){
$article['seolink'] = $this->getSeoLink($article);
$this->inDB->query("UPDATE cms_content SET seolink='{$article['seolink']}' WHERE id = '{$article['id']}'");
cmsInsertTags($article['tags'], 'content', $article['id']);
if ($article['published']) { cmsCore::callEvent('ADD_ARTICLE_DONE', $article); }
}
return $article['id'] ? $article['id'] : false;
}
/* ==================================================================================================== */
/* ==================================================================================================== */
/**
* Обновляет статью
* @return bool
*/
public function updateArticle($id, $article, $not_upd_seo = false){
$article['id']= $id;
if(!$not_upd_seo){
if (@$article['url']){
$article['url'] = cmsCore::strToURL($article['url'], $this->config['is_url_cyrillic']);
}
$article['seolink'] = $this->getSeoLink($article);
} else { unset($article['seolink']); unset($article['url']); }
if (!$article['user_id']) { $article['user_id'] = cmsUser::getInstance()->id; }
$article = cmsCore::callEvent('UPDATE_ARTICLE', $article);
$this->inDB->update('cms_content', $article, $id);
if(!$not_upd_seo){
$this->updateContentCommentsLink($id);
}
cmsInsertTags($article['tags'], 'content', $id);
return true;
}
/* ==================================================================================================== */
/* ==================================================================================================== */
/**
* Обновляет ссылки меню на категории
* @return bool
*/
public function updateCatMenu(){
return $this->inDB->query("UPDATE cms_menu m, cms_category cat SET m.link = CONCAT('/', cat.seolink) WHERE m.linkid = cat.id AND m.linktype = 'category'");
}
/**
* Обновляет ссылки меню на статьи
* @return bool
*/
public function updateContentMenu(){
return $this->inDB->query("UPDATE cms_menu m, cms_content con SET m.link = CONCAT('/', con.seolink, '.html') WHERE m.linkid = con.id AND m.linktype = 'content'");
}
/**
* Обновляет ссылки меню на статьи
* @return bool
*/
public function updateContentCommentsLink($article_id){
// Обновляем ссылки в комменатриях
$this->inDB->query("UPDATE cms_comments c, cms_content a SET
c.target_link = CONCAT('/', a.seolink, '.html')
WHERE a.id = '$article_id' AND c.target = 'article' AND c.target_id = a.id");
// Обновляем ссылки в action
$action = cmsActions::getAction('add_comment');
if($action){
$this->inDB->query("UPDATE cms_actions_log log, cms_content a SET
log.target_url = CONCAT('/', a.seolink, '.html'), log.object_url = CONCAT('/', a.seolink, '.html#c', log.object_id)
WHERE a.id = '$article_id' AND log.action_id='{$action['id']}' AND log.target_id='{$article_id}'");
}
return true;
}
/* ==================================================================================================== */
/* ==================================================================================================== */
/**
* Возвращает массив связанных статей с категорией
* @return array
*/
public function getNestedArticles($category_id) {
$cat = $this->inDB->getNsCategory('cms_category', $category_id);
$sql = "SELECT con.id, con.title, con.url, con.category_id
FROM cms_content con
JOIN cms_category cat ON cat.id = con.category_id AND cat.NSLeft >= {$cat['NSLeft']} AND cat.NSRight <= {$cat['NSRight']}";
$result = $this->inDB->query($sql);
if (!$this->inDB->num_rows($result)) { return false; }
$articles = array();
while($article = $this->inDB->fetch_assoc($result)){
$articles[] = $article;
}
return $articles ? $articles : false;
}
/* ==================================================================================================== */
/* ==================================================================================================== */
/**
* Удаляет категорию
* @return bool
*/
public function deleteCategory($id, $is_with_content = false) {
if ($is_with_content){
$articles = $this->getNestedArticles($id);
foreach($articles as $article){
$this->deleteArticle($article['id']);
}
}
$this->inDB->deleteNS('cms_category', $id);
return true;
}
/* ==================================================================================================== */
/* ==================================================================================================== */
/**
* Возвращает фотографии из привязанного альбома
* @param str $album
* @return array
*/
public function getCatPhotoAlbum($album){
if(!$album) { return array(); }
$album = @unserialize($album);
if(!$album || !is_array($album) || !@$album['id']) { return array(); }
cmsCore::loadClass('photo');
$inPhoto = cmsPhoto::getInstance();
$p_a = $this->inDB->getNsCategory('cms_photo_albums', (int)$album['id']);
if (!$p_a) { return array(); }
$p_a['title'] = $album['header'];
$p_a['maxcols'] = $album['maxcols'];
$inPhoto->whereAlbumIs((int)$album['id']);
if(!in_array($album['orderby'], array('title','pubdate','rating','hits'))) { $album['orderby'] = 'pubdate'; }
if(!in_array($album['orderto'], array('asc','desc'))) { $album['orderto'] = 'desc'; }
$this->inDB->orderBy('f.'.$album['orderby'], $album['orderto']);
$this->inDB->limit((int)$album['max']);
$photos = $inPhoto->getPhotos();
if (!$photos) { return array(); }
return array('album'=>$p_a, 'photos'=>$photos);
}
/* ==================================================================================================== */
/* ==================================================================================================== */
}