Вход Регистрация
Файл: system/core/model.php
Строк: 930
<?php
class cmsModel{

    public 
$name;

    public 
$db;

    
//условия для выборок
    
public $table      '';
    public 
$select     = array('i.*');
    public 
$join       '';
    public 
$where      '';
    public 
$where_separator  'AND';
    public 
$group_by   '';
    public 
$order_by   '';
    public 
$limit      1000;
    public 
$perpage    50;

    public 
$keep_filters false;
    public 
$filter_on  false;

    protected 
$privacy_filter_disabled false;
    protected 
$privacy_filtered false;

    private 
$cache_key false;

    public function 
__construct(){

        
$core cmsCore::getInstance();

        
$this->name str_replace('model_'''get_called_class());

        
$this->db $core->db;

    }

//============================================================================//
//============================================================================//

    
protected function useCache($key){
        
$this->cache_key $key;
    }

    protected function 
stopCache(){
        
$this->cache_key false;
    }

//============================================================================//
//============================================================================//

    
public function getContentTableStruct(){

        return array(
            
'id'                    => array('type' => 'primary'),
            
'title'                 => array('type' => 'varchar''size' => 100),
            
'content'               => array('type' => 'text'),
            
'photo'                 => array('type' => 'text'),
            
'slug'                  => array('type' => 'varchar''size' => 100),
            
'seo_keys'              => array('type' => 'text'),
            
'seo_desc'              => array('type' => 'text'),
            
'seo_title'             => array('type' => 'varchar''size' => 256),
            
'tags'                  => array('type' => 'varchar''size' => 1000),
            
'date_pub'              => array('type' => 'timestamp''default_current' => true),
            
'date_last_modified'    => array('type' => 'timestamp'),
            
'date_pub_end'            => array('type' => 'timestamp'),
            
'is_pub'                => array('type' => 'bool''index'=>true'default' => 1),
            
'hits_count'            => array('type' => 'int''index'=>true'default' => 0),
            
'user_id'               => array('type' => 'int''index'=>true),
            
'parent_id'             => array('type' => 'int''index'=>true),
            
'parent_type'           => array('type' => 'varchar''size'=>32'index'=>true),
            
'parent_title'          => array('type' => 'varchar''size' => 100),
            
'parent_url'            => array('type' => 'varchar''size' => 255),
            
'is_parent_hidden'      => array('type' => 'bool''index'=>true),
            
'category_id'           => array('type' => 'int''index'=>true'default' => 1),
            
'folder_id'             => array('type' => 'int''index'=>true),
            
'is_comments_on'        => array('type' => 'bool'),
            
'comments'              => array('type' => 'int''index'=>true'default' => 0),
            
'rating'                => array('type' => 'int''index'=>true'default' => 0),
            
'is_approved'           => array('type' => 'tinyint''index'=>true'default' => 1),
            
'approved_by'           => array('type' => 'int''index'=>true),
            
'date_approved'         => array('type' => 'timestamp'),
            
'is_private'            => array('type' => 'bool''index'=>true'default' => 0),
        );

    }

    public function 
getFieldsTableStruct(){

        return array(
            
'id'            => array('type' => 'primary'),
            
'ctype_id'      => array('type' => 'int'),
            
'name'          => array('type' => 'varchar''size' => 20),
            
'title'         => array('type' => 'varchar''size' => 100),
            
'hint'          => array('type' => 'varchar''size' => 200),
            
'ordering'      => array('type' => 'int''index'=>true),
            
'fieldset'      => array('type' => 'varchar''size' => 32),
            
'type'          => array('type' => 'varchar''size' => 16),
            
'is_in_list'    => array('type' => 'bool'),
            
'is_in_item'    => array('type' => 'bool'),
            
'is_in_filter'  => array('type' => 'bool'),
            
'is_private'    => array('type' => 'bool'),
            
'is_fixed'      => array('type' => 'bool'),
            
'is_fixed_type' => array('type' => 'bool'),
            
'is_system'     => array('type' => 'bool'),
            
'values'        => array('type' => 'text'),
            
'options'       => array('type' => 'text'),
            
'groups_read'   => array('type' => 'text'),
            
'groups_edit'   => array('type' => 'text'),
        );

    }

    public function 
getPropsTableStruct(){

        return array(
            
'id'            => array('type' => 'primary'),
            
'ctype_id'      => array('type' => 'int'),
            
'title'         => array('type' => 'varchar''size' => 100),
            
'fieldset'      => array('type' => 'varchar''size' => 32),
            
'type'          => array('type' => 'varchar''size' => 16),
            
'is_in_filter'  => array('type' => 'bool''index'=>true),
            
'values'        => array('type' => 'text'),
            
'options'       => array('type' => 'text'),
        );

    }

    public function 
getPropsBindTableStruct(){

        return array(
            
'id'        => array('type' => 'primary'),
            
'prop_id'   => array('type' => 'int''index'=>true),
            
'cat_id'    => array('type' => 'int''index'=>true),
            
'ordering'  => array('type' => 'int''index'=>true),
        );

    }

    public function 
getPropsValuesTableStruct(){

        return array(
            
'prop_id'   => array('type' => 'int''index'=>true),
            
'item_id'   => array('type' => 'int''index'=>true),
            
'value'     => array('type' => 'varchar''size' => 255),
        );

    }

//============================================================================//
//============================================================================//

    
public function getRootCategory($ctype_name){

        
$table_name $this->table_prefix $ctype_name '_cats';

        return 
$this->db->getFields($table_name'parent_id=0');

    }

    public function 
getCategory($ctype_name$id$by_field='id'){

        
$table_name $this->table_prefix $ctype_name '_cats';

        
$this->useCache("content.categories");

        
$category $this->getItemByField($table_name$by_field$id);

        if (!
$category) { return false; }

        
$category['path'] = $this->getCategoryPath($ctype_name$category);

        return 
$category;

    }

    public function 
getCategoryBySLUG($ctype_name$slug){

        return 
$this->getCategory($ctype_name$slug'slug');

    }

    public function 
getCategorySLUG($category){

        
$slug '';

        foreach(
$category['path'] as $c){
            if (
$c['id'] == 1) { continue; }
            if (
$slug) { $slug .= '/'; }
            
$slug .= lang_slug( empty($c['slug_key']) ? $c['title'] : $c['slug_key'] );
        }

        return 
$slug;

    }

//============================================================================//
//============================================================================//

    
public function getCategoriesTree($ctype_name$is_show_root=true) {

        
$table_name $this->table_prefix $ctype_name '_cats';

        if (!
$is_show_root){
            
$this->filterGt('parent_id'0);
        }

        
$this->orderBy('ns_left');

        
$this->useCache("content.categories");

        return 
$this->get($table_name, function($node$model){
            if (
$node['ns_level']==0) { $node['title'] = LANG_ROOT_CATEGORY; }
            return 
$node;
        });

    }

//============================================================================//
//============================================================================//

    
public function getSubCategories($ctype_name$parent_id=1) {

        
$table_name $this->table_prefix $ctype_name '_cats';

        
$this->filterEqual('parent_id'$parent_id);
        
$this->orderBy('ns_left');

        return 
$this->get($table_name);

    }

    public function 
getSubCategoriesTree($ctype_name$parent_id=1$level=1) {

        
$table_name $this->table_prefix $ctype_name '_cats';

        
$parent $this->getCategory($ctype_name$parent_id);

        
$this->
            
filterGt('ns_left'$parent['ns_left'])->
            
filterLt('ns_right'$parent['ns_right']);

        if (
$level){
            
$this->filterLtEqual('ns_level'$parent['ns_level'] + $level);
        }

        
$this->orderBy('ns_left');

        
$this->useCache("content.categories");

        return 
$this->get($table_name);

    }

//============================================================================//
//============================================================================//

    
public function getCategoryPath($ctype_name$category) {

        
$table_name $this->table_prefix $ctype_name '_cats';

        if (!isset(
$category['ns_left'])){
            
$category $this->getCategory($ctype_name$category['id']);
        }

        
$this->
            
filterLtEqual('ns_left'$category['ns_left'])->
            
filterGtEqual('ns_right'$category['ns_right'])->
            
filterLtEqual('ns_level'$category['ns_level'])->
            
filterGt('ns_level'0)->
            
orderBy('ns_left');

        
$this->useCache("content.categories");

        return 
$this->get($table_name);

    }

//============================================================================//
//============================================================================//

    
public function addCategory($ctype_name$category){

        
$table_name $this->table_prefix $ctype_name '_cats';

        
$this->db->nestedSets->setTable($table_name);

        
$category['id'] = $this->db->nestedSets->addNode($category['parent_id']);

        if (!
$category['id']){ return false; }

        
$category['title'] = $this->db->escape($category['title']);

        
$this->update($table_name$category['id'], $category);

        
$category['path'] = $this->getCategoryPath($ctype_name$category);

        
$category['slug'] = $this->getCategorySLUG($category);

        
$this->update($table_name$category['id'], array(
            
'slug' => $category['slug']
        ));

        
cmsCache::getInstance()->clean("content.categories");

        return 
$category;

    }

//============================================================================//
//============================================================================//

    
public function updateCategory($ctype_name$id$category){

        
cmsCache::getInstance()->clean("content.categories");

        
$table_name $this->table_prefix $ctype_name '_cats';

        
$category_old $this->getCategory($ctype_name$id);                

        if (
$category_old['parent_id'] != $category['parent_id']){            
            
$this->db->nestedSets->setTable($table_name);
            
$this->db->nestedSets->moveNode($id$category['parent_id']);            
        }
        
        
$this->update($table_name$id$category);

        
$category['id'] = $id;
        
$category['path'] = $this->getCategoryPath($ctype_name, array('id' => $id));
        
$category['slug'] = $this->getCategorySLUG($category);

        
$this->update($table_name$id, array(
            
'slug' => $category['slug']
        ));

        
$subcats $this->getSubCategoriesTree($ctype_name$idfalse);

        if (
$subcats){
            foreach(
$subcats as $subcat){
                
$subcat['path'] = $this->getCategoryPath($ctype_name, array('id' => $subcat['id']));
                
$subcat['slug'] = $this->getCategorySLUG($subcat);
                
$this->update($table_name$subcat['id'], array('slug' => $subcat['slug']));
            }
        }

        return 
$category;

    }

//============================================================================//
//============================================================================//

    
public function updateCategoryTree($ctype_name$tree$categories_count){

        
cmsCache::getInstance()->clean("content.categories");

        
$table_name $this->table_prefix $ctype_name '_cats';

        
$this->updateCategoryTreeNode($ctype_name$tree);
        
$this->updateCategoryTreeNodeSlugs($ctype_name$tree);

        
$root_keys = array(
            
'ns_left' => 1,
            
'ns_right' => + ($categories_count*2) + 1
        
);

        
$this->update($table_name1$root_keys);

        return 
true;

    }

    public function 
updateCategoryTreeNode($ctype_name$tree){

        
$table_name $this->table_prefix $ctype_name '_cats';
        
        foreach(
$tree as $node){

            
$this->update($table_name$node['key'], array(
                
'parent_id' => $node['parent_key'],
                
'ns_left' => $node['left'],
                
'ns_right' => $node['right'],
                
'ns_level' => $node['level'],
            ));

            if (!empty(
$node['children'])){
                
$this->updateCategoryTreeNode($ctype_name$node['children']);
            }

        }
        
        return 
true;

    }

    public function 
updateCategoryTreeNodeSlugs($ctype_name$tree){

        
$table_name $this->table_prefix $ctype_name '_cats';
        
        foreach(
$tree as $node){
            
            
$path $this->getCategoryPath($ctype_name, array(
                
'id' => $node['key'],
                
'parent_id' => $node['parent_key'],
                
'ns_left' => $node['left'],
                
'ns_right' => $node['right'],
                
'ns_level' => $node['level']
            ));

            
$slug $this->getCategorySLUG(array(
                
'path' => $path,
                
'title' => $node['title']
            ));

            
$this->update($table_name$node['key'], array(
                
'slug' => $slug
            
));

            if (!empty(
$node['children'])){
                
$this->updateCategoryTreeNodeSlugs($ctype_name$node['children']);
            }

        }
        
        return 
true;

    }

//============================================================================//
//============================================================================//

    
public function deleteCategory($ctype_name$id){

        
//
        // Эта функция должна быть переопределена и вызываться
        // из дочернего класса чтобы после нее удалять все записи
        // из категории
        //

        
$table_name $this->table_prefix $ctype_name '_cats';

        
$this->db->nestedSets->setTable($table_name);
        
$this->db->nestedSets->deleteNode($id);

        
cmsCache::getInstance()->clean("content.categories");

        return 
true;

    }

//============================================================================//
//============================================================================//

    
public function delete($table_name$id$by_field='id'){
        
$this->filterEqual($by_field$id);
        return 
$this->deleteFiltered($table_name);
    }

    public function 
deleteFiltered($table_name){
        
$where $this->where;
        
$this->resetFilters();
        return 
$this->db->delete($table_name$where);
    }

//============================================================================//
//============================================================================//

    
public function update($table_name$id$data){
        
$this->filterEqual('id'$id);
        return 
$this->updateFiltered($table_name$data);
    }

    public function 
updateFiltered($table_name$data){
        
$where $this->where;
        
$this->resetFilters();
        return 
$this->db->update($table_name$where$data);
    }

//============================================================================//
//============================================================================//

    
public function insert($table_name$data){
        return 
$this->db->insert($table_name$data);
    }

    public function 
insertOrUpdate($table_name$insert_data$update_data false){
        return 
$this->db->insertOrUpdate($table_name$insert_data$update_data);
    }

//============================================================================//
//============================================================================//

    
public function lockFilters(){
        
$this->keep_filters true;
        return 
$this;
    }

    public function 
unlockFilters(){
        
$this->keep_filters false;
        return 
$this;
    }

    public function 
resetFilters(){

        
$this->select       = array('i.*');        
        
$this->group_by     '';
        
$this->order_by     '';
        
$this->limit        '';
        
$this->join         '';
        
        if (
$this->keep_filters) { return; }
        
        
$this->filter_on    false;
        
$this->where        '';
        
$this->privacy_filtered false;

        return 
$this;

    }

    public function 
filter($condition){
        if (
$this->filter_on){
            
$this->where .= {$this->where_separator} ({$condition})";
        } else {
            
$this->where .= "({$condition})";
            
$this->filter_on true;
        }
        
$this->where_separator ' AND ';
        return 
$this;
    }

    public function 
filterStart(){
        if (
$this->filter_on){
            
$this->where .= {$this->where_separator} (";
        } else {
            
$this->where .= "(";
        }
        
$this->filter_on false;
        return 
$this;
    }

    public function 
filterEnd(){
        
$this->where .= ' ) ';
        return 
$this;
    }

    public function 
filterAnd(){
        
$this->where_separator ' AND ';
        return 
$this;
    }

    public function 
filterOr(){
        
$this->where_separator ' OR ';
        return 
$this;
    }

    public function 
filterNotNull($field){
        if (!
strstr($field'.')){ $field 'i.' $field; }
        
$this->filter("$field IS NOT NULL");
        return 
$this;
    }

    public function 
filterIsNull($field){
        if (!
strstr($field'.')){ $field 'i.' $field; }
        
$this->filter("$field IS NULL");
        return 
$this;
    }

    public function 
filterEqual($field$value){
        if (!
strstr($field'.')){ $field 'i.' $field; }
        if (
is_null($value)){
            
$this->filter("$field IS NULL");
        } else {
            
$value $this->db->escape($value);
            
$this->filter("$field = '$value'");
        }
        return 
$this;
    }

    public function 
filterFunc($field$value){
        if (!
strstr($field'.')){ $field 'i.' $field; }
        
$this->filter("$field = $value");
        return 
$this;
    }

    public function 
filterNotEqual($field$value){
        if (!
strstr($field'.')){ $field 'i.' $field; }
        if (
is_null($value)){
            
$this->filter("$field NOT IS NULL");
        } else {
            
$value $this->db->escape($value);
            
$this->filter("$field <> '$value'");
        }
        return 
$this;
    }

    public function 
filterGt($field$value){
        if (!
strstr($field'.')){ $field 'i.' $field; }
        
$value $this->db->escape($value);
        
$this->filter("$field > '$value'");
        return 
$this;
    }

    public function 
filterLt($field$value){
        if (!
strstr($field'.')){ $field 'i.' $field; }
        
$value $this->db->escape($value);
        
$this->filter("$field < '$value'");
        return 
$this;
    }

    public function 
filterGtEqual($field$value){
        if (!
strstr($field'.')){ $field 'i.' $field; }
        
$value $this->db->escape($value);
        
$this->filter("$field >= '$value'");
        return 
$this;
    }

    public function 
filterLtEqual($field$value){
        if (!
strstr($field'.')){ $field 'i.' $field; }
        
$value $this->db->escape($value);
        
$this->filter("$field <= '$value'");
        return 
$this;
    }

    public function 
filterLike($field$value){
        if (!
strstr($field'.')){ $field 'i.' $field; }
        
$value $this->db->escape($value);
        
$this->filter("$field LIKE '$value'");
        return 
$this;
    }

    public function 
filterBetween($field$start$end){
        if (!
strstr($field'.')){ $field 'i.' $field; }
        
$start $this->db->escape($start);
        
$end $this->db->escape($end);
        
$this->filter("$field BETWEEN '$start' AND '$end'");
        return 
$this;
    }

    public function 
filterDateYounger($field$value$interval='DAY'){
        if (!
strstr($field'.')){ $field 'i.' $field; }
        
$value $this->db->escape($value);
        
$interval $this->db->escape($interval);
        
$this->filter("$field >= DATE_SUB(NOW(), INTERVAL {$value} {$interval})");
        return 
$this;
    }

    public function 
filterDateOlder($field$value$interval='DAY'){
        if (!
strstr($field'.')){ $field 'i.' $field; }
        
$value $this->db->escape($value);
        
$interval $this->db->escape($interval);
        
$this->filter("$field < DATE_SUB(NOW(), INTERVAL {$value} {$interval})");
        return 
$this;
    }

    public function 
filterTimestampGt($field$value){
        if (!
strstr($field'.')){ $field 'i.' $field; }
        
$field "UNIX_TIMESTAMP({$field})";
        
$value $this->db->escape($value);
        
$this->filter("{$field} > '{$value}'");
        return 
$this;
    }

    public function 
filterTimestampLt($field$value){
        if (!
strstr($field'.')){ $field 'i.' $field; }
        
$field "UNIX_TIMESTAMP({$field})";
        
$value $this->db->escape($value);
        
$this->filter("{$field} < '{$value}'");
        return 
$this;
    }

    public function 
filterIn($field$value){
        if (!
strstr($field'.')){ $field 'i.' $field; }
        if (
is_array($value)){
            foreach(
$value as $k=>$v){
                
$v $this->db->escape($v);
                
$value[$k] = "'{$v}'";
            }
            
$value implode(','$value);
        } else {
            
$value $this->db->escape($value);
            
$value "'{$value}'";
        }
        
$this->filter("{$field} IN ({$value})");
        return 
$this;
    }

    public function 
filterNotIn($field$value){
        if (!
strstr($field'.')){ $field 'i.' $field; }
        if (
is_array($value)){
            foreach(
$value as $k=>$v){
                
$v $this->db->escape($v);
                
$value[$k] = "'{$v}'";
            }
            
$value implode(','$value);
        } else {
            
$value $this->db->escape($value);
            
$value "'{$value}'";
        }
        
$this->filter("{$field} NOT IN ({$value})");
        return 
$this;
    }

    public function 
filterCategory($ctype_name$category$is_recursive=false){

        
$table_name $this->table_prefix $ctype_name '_cats';
        
$bind_table_name $table_name '_bind';
        
        if (!
$is_recursive){

            
$this->join($bind_table_name'b'"b.item_id = i.id AND b.category_id = '{$category['id']}'");

        } else {

            
$this->join($bind_table_name'b''b.item_id = i.id');
            
$this->join($table_name'c'"c.id = b.category_id AND c.ns_left >= '{$category['ns_left']}' AND c.ns_right <= '{$category['ns_right']}'");

        }
        
//        dump($this->getSQL());
        
        
return $this;

    }
    
    public function 
filterCategoryId($ctype_name$category_id$is_recursive=false){
        
        if (!
$is_recursive){
            
            return 
$this->filterCategory($ctype_name, array('id'=>$category_id));
            
        } else {
            
            
$category $this->getCategory($ctype_name$category_id);
            return 
$this->filterCategory($ctype_name$categorytrue);
            
        }
        
    }

    public function 
disablePrivacyFilter(){
        
$this->privacy_filter_disabled true;
        return 
$this;
    }

    public function 
enablePrivacyFilter(){
        
$this->privacy_filter_disabled false;
        return 
$this;
    }

    public function 
filterPrivacy(){

        
$user cmsUser::getInstance();

        if (
$this->privacy_filtered) { return $this; }

        
// Этот фильтр может применяться при подсчете числа записей
        // и при выборке самих записей
        // используем флаг чтобы фильтр не применился дважды
        
$this->privacy_filtered true;

        return 
$this->filter("(i.is_private = 0 OR i.user_id = '{$user->id}' OR (i.is_private = 1 AND EXISTS (SELECT id FROM {users}_friends WHERE user_id='{$user->id}' AND friend_id=i.user_id AND is_mutual=1)))");

    }

    public function 
filterHiddenParents(){
        return 
$this->filterIsNull('is_parent_hidden');
    }

    public function 
filterFriends($user_id){

        
$user_id intval($user_id);

        
$this->joinInner('{users}_friends''f'"friend_id = i.user_id AND f.is_mutual = 1 AND f.user_id = '{$user_id}'");

        return 
$this;

    }

    public function 
applyDatasetFilters($dataset$ignore_sorting=false){

        if (!empty (
$dataset['filters'])){

            foreach(
$dataset['filters'] as $filter){

                if ((
$filter['value'] === '') && !in_array($filter['condition'], array('nn''ni'))) { continue; }
                if (empty(
$filter['condition'])) { continue; }

                if (
$filter['value'] !== '') { $filter['value'] = string_replace_user_properties($filter['value']); }

                switch(
$filter['condition']){

                    
// общие условия
                    
case 'eq'$this->filterEqual($filter['field'], $filter['value']); break;
                    case 
'gt'$this->filterGt($filter['field'], $filter['value']); break;
                    case 
'lt'$this->filterLt($filter['field'], $filter['value']); break;
                    case 
'ge'$this->filterGtEqual($filter['field'], $filter['value']); break;
                    case 
'le'$this->filterLtEqual($filter['field'], $filter['value']); break;
                    case 
'nn'$this->filterNotNull($filter['field']); break;
                    case 
'ni'$this->filterIsNull($filter['field']); break;

                    
// строки
                    
case 'lk'$this->filterLike($filter['field'], '%'.$filter['value'].'%'); break;
                    case 
'lb'$this->filterLike($filter['field'], $filter['value'] . '%'); break;
                    case 
'lf'$this->filterLike($filter['field'], '%' $filter['value']); break;

                    
// даты
                    
case 'dy'$this->filterDateYounger($filter['field'], $filter['value']); break;
                    case 
'do'$this->filterDateOlder($filter['field'], $filter['value']); break;

                }

            }

        }

        if (!empty (
$dataset['sorting']) && !$ignore_sorting){
            
$this->orderByList($dataset['sorting']);
        }

        return 
true;

    }

    public function 
select($field$as=false){
        
$this->select[] = $as "{$field} as {$as}$field;
        return 
$this;
    }

    public function 
selectOnly($field$as=false){
        
$this->select = array();
        
$this->select[] = $as "{$field} as {$as}$field;
        return 
$this;
    }

    public function 
join($table_name$as$on){
        
$this->join .= "JOIN {#}{$table_name} as {$as} ON {$on}n";
        return 
$this;
    }

    public function 
joinLeft($table_name$as$on){
        
$this->join .= "LEFT JOIN {#}{$table_name} as {$as} ON {$on}n";
        return 
$this;
    }

    public function 
joinLeftInner($table_name$as$on){
        
$this->join .= "LEFT INNER JOIN {#}{$table_name} as {$as} ON {$on}n";
        return 
$this;
    }

    public function 
joinLeftOuter($table_name$as$on){
        
$this->join .= "LEFT OUTER JOIN {#}{$table_name} as {$as} ON {$on}n";
        return 
$this;
    }

    public function 
joinRight($table_name$as$on){
        
$this->join .= "RIGHT JOIN {#}{$table_name} as {$as} ON {$on}n";
        return 
$this;
    }

    public function 
joinRightInner($table_name$as$on){
        
$this->join .= "RIGHT INNER JOIN {#}{$table_name} as {$as} ON {$on}n";
        return 
$this;
    }

    public function 
joinRightOuter($table_name$as$on){
        
$this->join .= "RIGHT OUTER JOIN {#}{$table_name} as {$as} ON {$on}n";
        return 
$this;
    }

    public function 
joinInner($table_name$as$on){
        
$this->join .= "INNER JOIN {#}{$table_name} as {$as} ON {$on}n";
        return 
$this;
    }

    public function 
joinOuter($table_name$as$on){
        
$this->join .= "OUTER JOIN {#}{$table_name} as {$as} ON {$on}n";
        return 
$this;
    }

    public function 
joinUser($on_field='user_id'$user_fields=array(), $join_direction=false){

        if (!
$user_fields){
            
$user_fields = array(
                
'u.nickname' => 'user_nickname',
                
'u.avatar' => 'user_avatar',
            );
        }

        foreach(
$user_fields as $field => $alias){
            
$this->select($field$alias);
        }

        switch (
$join_direction){
            
            case 
'left'
                
$this->joinLeft('{users}''u'"u.id = i.{$on_field}"); 
                break;
            
            case 
'right'
                
$this->joinRight('{users}''u'"u.id = i.{$on_field}"); 
                break;
            
            default: 
                
$this->join('{users}''u'"u.id = i.{$on_field}"); 
                break;
            
        }
        
        return 
$this;

    }
    
    public function 
joinUserLeft($on_field='user_id'$user_fields=array()){
        return 
$this->joinUser($on_field$user_fields'left');
    }

    public function 
joinUserRight($on_field='user_id'$user_fields=array()){
        return 
$this->joinUser($on_field$user_fields'right');
    }

    public function 
groupBy($field){
        if (!
strstr($field'.')){ $field 'i.' $field; }
        
$this->group_by $field;
        return 
$this;
    }

    public function 
orderBy($field$direction=''){
        if (!
strstr($field'.')){ $field 'i.' $field; }
        
$this->order_by "{$field} {$direction}";
        return 
$this;
    }

    public function 
orderByList($list){
        
        
$this->order_by '';
        
        if (
is_array($list)){        
            foreach(
$list as $o){
                
$field $o['by'];
                
$direction $o['to'];
                if (!
strstr($field'.')){ $field 'i.' $field; }
                if (
$this->order_by) { $this->order_by .= ', '; }
                
$this->order_by .= "{$field} {$direction}";                            
            }        
        }
        
        return 
$this;
        
    }

    public function 
limit($from$howmany='') {
        
$this->limit = (int)$from;
        if (
$this->limit 0) { $this->limit 0; }
        if (
$howmany){
            if ((int)
$howmany <= 0){ $howmany 15; }
            
$this->limit .= ', '. (int)$howmany;
        }
        return 
$this;
    }

    public function 
limitPage($page$perpage=false) {
        if (!
$perpage) { $perpage $this->perpage; }
        
$this->limit(($page-1)*$perpage$perpage);
        return 
$this;
    }

    public function 
setPerPage($perpage){
        
$this->perpage $perpage;
        return 
$this;
    }

//============================================================================//
//============================================================================//

    
public function getField($table_name$row_id$field_name){

        
$this->filterEqual('id'$row_id);
        return 
$this->getFieldFiltered($table_name$field_name);

    }

    public function 
getFieldFiltered($table_name$field_name){

        
$this->select = array("i.{$field_name} as {$field_name}");

        
$this->table $table_name;

        
$this->limit(1);

        
$sql $this->getSQL();

        
$this->resetFilters();

        
$result $this->db->query($sql);

        if (!
$this->db->numRows($result)){ return false; }

        
$item $this->db->fetchAssoc($result);

        
$this->db->freeResult($result);

        return 
$item$field_name ];

    }

//============================================================================//
//============================================================================//

    
public function getItem($table_name$item_callback=false){

        
$select implode(', '$this->select);

        
$sql "SELECT {$select}
                FROM {#}
{$table_name} i
                "
;

        if (
$this->join){ $sql .= $this->join; }

        if (
$this->where){ $sql .= "WHERE {$this->where}n"; }
        
        if (
$this->order_by){ $sql .= "ORDER BY {$this->order_by}n"; }
        
        
$sql .= "LIMIT 1";

        
$this->resetFilters();

        
// если указан ключ кеша для этого запроса
        // то пробуем получить результаты из кеша
        
if ($this->cache_key){

            
$cache_key $this->cache_key '.' md5($sql);
            
$cache cmsCache::getInstance();

            if (
false !== ($item $cache->get($cache_key))){
                
$this->stopCache();
                return 
$item;
            }

        }

        
$result $this->db->query($sql);

        if (!
$this->db->numRows($result)){ return false; }

        
$item $this->db->fetchAssoc($result);

        if(
is_callable($item_callback)){
            
$item $item_callback$item$this );
        }

        
// если указан ключ кеша для этого запроса
        // то сохраняем результаты в кеше
        
if ($this->cache_key){
            
$cache->set($cache_key$item);
            
$this->stopCache();
        }

        
$this->db->freeResult($result);

        return 
$item;

    }

    public function 
getItemById($table_name$id$item_callback=false){
        
$this->filterEqual('id'$id);
        return 
$this->getItem($table_name$item_callback);
    }

    public function 
getItemByField($table_name$field_name$field_value$item_callback=false){
        
$this->filterEqual($field_name$field_value);
        return 
$this->getItem($table_name$item_callback);
    }

//============================================================================//
//============================================================================//

    
public function getCount($table_name$by_field='id'){

        
$sql "SELECT COUNT(i.{$by_field}) as count
                FROM {#}
{$table_name} i
                "
;

        if (
$this->join){ $sql .= $this->join; }

        if (
$this->where){ $sql .= "WHERE {$this->where}n"; }

        
// если указан ключ кеша для этого запроса
        // то пробуем получить результаты из кеша
        
if ($this->cache_key){

            
$cache_key $this->cache_key '.' md5($sql);
            
$cache cmsCache::getInstance();

            if (
false !== ($result $cache->get($cache_key))){
                
$this->stopCache();
                return 
$result;
            }

        }

        
$result $this->db->query($sql);

        if (!
$this->db->numRows($result)){
            
$count 0;
        } else {
            
$item $this->db->fetchAssoc($result);
            
$count = (int)$item['count'];
        }

        
// если указан ключ кеша для этого запроса
        // то сохраняем результаты в кеше
        
if ($this->cache_key){
            
$cache->set($cache_key$count);
            
$this->stopCache();
        }

        
$this->db->freeResult($result);

        return 
$count;

    }

//============================================================================//
//============================================================================//

    /**
     * Возвращает записи из базы, применяя все наложенные ранее фильтры
     * @return array
     */
    
public function get($table_name$item_callback=false$key_field='id'){

        
$this->table $table_name;

        
$sql $this->getSQL();

        
// сбрасываем фильтры
        
$this->resetFilters();

        
// если указан ключ кеша для этого запроса
        // то пробуем получить результаты из кеша
        
if ($this->cache_key){

            
$cache_key $this->cache_key '.' md5($sql);
            
$cache cmsCache::getInstance();

            if (
false !== ($items $cache->get($cache_key))){
                
$this->stopCache();
                return 
$items;
            }

        }

        
$result $this->db->query($sql);

        
// если запрос ничего не вернул, возвращаем ложь
        
if (!$this->db->numRows($result)){ return false; }

        
$items = array();

        
// перебираем все вернувшиеся строки
        
while($item $this->db->fetchAssoc($result)){

            
$key $key_field $item[$key_field] : false;

            
// если задан коллбек для обработки строк,
            // то пропускаем строку через него
            
if (is_callable($item_callback)){
                
$item $item_callback$item$this );
                if (
$item===false){ continue; }
            }

            
// добавляем обработанную строку в результирующий массив
            
if ($key){
                
$items[$key] = $item;
            } else {
                
$items[] = $item;
            }

        }

        
// если указан ключ кеша для этого запроса
        // то сохраняем результаты в кеше
        
if ($this->cache_key){
            
$cache->set($cache_key$items);
            
$this->stopCache();
        }

        
$this->db->freeResult($result);

        
// возвращаем строки
        
return $items;

    }

//============================================================================//
//============================================================================//

    
public function getSQL(){

        
$select implode(', '$this->select);

        
$sql "SELECT {$select}
                FROM {#}
{$this->table} i
                "
;

        if (
$this->join){ $sql .= $this->join; }

        if (
$this->where){ $sql .= "WHERE {$this->where}n"; }

        if (
$this->group_by){ $sql .= "GROUP BY {$this->group_by}n"; }

        if (
$this->order_by){ $sql .= "ORDER BY {$this->order_by}n"; }

        if (
$this->limit){ $sql .= "LIMIT {$this->limit}n"; }

        return 
$sql;

    }

//============================================================================//
//============================================================================//

    
public function getMax($table$field$default=0){

        
$sql "SELECT i.{$field} as {$field}
                FROM {#}
{$table} i
                "
;

        if (
$this->where) { $sql .= "WHERE {$this->where}n"; }

        
$sql .= "ORDER BY i.{$field} DESC
                 LIMIT 1"
;

        
$result $this->db->query($sql);

        
$this->resetFilters();

        if (!
$this->db->numRows($result)){ return $default; }

        
$max $this->db->fetchAssoc($result);

        
$this->db->freeResult($result);

        return 
$max[$field];

    }

    
/**
     * Возвращает максимальный порядковый номер в таблице
     * @param string $table
     * @param string $where
     * @return int
     */
    
public function getMaxOrdering($table){

        return 
$this->getMax($table'ordering');

    }

    
/**
     * Возращает следующий порядковый номер в таблице для новых записей
     * @param string $table
     * @param string $where
     * @return int
     */
    
public function getNextOrdering($table){

        return 
$this->getMaxOrdering($table) + 1;

    }

    
/**
     * Пересчитывает порядковые номера в таблице
     * @param string $table_name
     * @param string $where
     * @return bool
     */
    
public function reorder($table_name){

        
$sql "SELECT i.id as id, i.ordering as ordering
                FROM {#}
{$table_name} i
                "
;

        if (
$this->where) { $sql .= "WHERE {$this->where}n"; }

        
$sql .= "ORDER BY ordering";

        
$result $this->db->query($sql);

        
$this->resetFilters();

        if (!
$this->db->numRows($result)){
            
$this->db->freeResult($result);
            return 
false;
        }

        
$ordering 0;

        while(
$item $this->db->fetchAssoc($result)){

            
$ordering += 1;
            
$this->db->query("UPDATE {#}{$table_name} SET ordering = {$ordering} WHERE id = {$item['id']}");

        }

        
$this->db->freeResult($result);

        return 
true;

    }

    
/**
     * Расставляет порядковые номера для списка из ID записей
     * @param string $table_name
     * @param string $list
     * @param array $additional_fields Список дополнительных полей и их значений, которые нужно обновлять вместе с ordering
     * @return bool
     */
    
public function reorderByList($table_name$list$additional_fields=false){

        
$ordering 0;

        
$additional_set = array();

        if (
is_array($additional_fields)){
            foreach(
$additional_fields as $field=>$value){
                
$value $this->db->escape($value);
                
$additional_set[] = "{$field} = '{$value}'";
            }
        }

        if (
$additional_set){
            
$additional_set ', ' implode(', '$additional_set);
        } else {
            
$additional_set '';
        }

        foreach(
$list as $id){

            
$ordering += 1;

            
$id $this->db->escape($id);

            
$query "UPDATE {#}{$table_name}
                      SET ordering = '
{$ordering}{$additional_set}
                      WHERE id = '
{$id}'";

            
$this->db->query($query);

        }

        return 
true;

    }

//============================================================================//
//============================================================================//

    /**
     * Применяет к модели фильтры, переданные из просмотра
     * таблицы со списком записей
     * @param array $grid
     * @param array $filter
     * @return bool
     */
    
public function applyGridFilter($grid$filter){

        
// применяем сортировку
        
if (!empty($filter['order_by'])) {
            if (!empty(
$grid['columns'][$filter['order_by']]['order_by'])){
                
$filter['order_by'] = $grid['columns'][$filter['order_by']]['order_by'];
            }
            
$this->orderBy($filter['order_by'], $filter['order_to']);
        }

        
// устанавливаем страницу
        
if (!empty($filter['page'])){
            
$perpage = !empty($filter['perpage']) ? intval($filter['perpage']) : $this->perpage;
            
$this->limitPage(intval($filter['page']), $perpage);
        }

        
//
        // проходим по каждой колонке таблицы
        // и проверяем не передан ли фильтр для нее
        //
        
foreach($grid['columns'] as $field => $column){
            if (isset(
$column['filter']) && $column['filter'] != 'none' && $column['filter'] != false){

                if (!empty(
$filter[$field])){

                    if (!empty(
$column['filter_by'])){
                        
$filter_field $column['filter_by'];
                    } else {
                        
$filter_field $field;
                    }

                    switch (
$column['filter']){
                        case 
'exact'$this->filterEqual($filter_field$filter[$field]); break;
                        case 
'like'$this->filterLike($filter_field"%{$filter[$field]}%"); break;
                        case 
'date'
                            
$date date('Y-m-d'strtotime($filter[$field]));
                            
$this->filterLike($filter_field"%{$date}%"); break;
                    }

                }

            }
        }

        return;

    }

//============================================================================//
//============================================================================//

    /**
     * Сортирует элементы массива $items в виде плоского дерева
     * на основании связей через parent_id
     * @param array $items
     * @param array $result_tree
     * @param int $parent_id
     * @param int $level
     */
    
public function buildTreeRecursive($items, &$result_tree$parent_id=0$level=1){
        
$level++;

        foreach(
$items as $num=>$item){
            if (
$item['parent_id']==$parent_id){
                
$item['level'] = $level-1;
                if (!isset(
$result_tree[$item['id']])){
                    
$result_tree[$item['id']] = $item;
                }
                
$this->buildTreeRecursive($items$result_tree$item['id'], $level);
            }
        }
    }

//============================================================================//
//============================================================================//

    
public function increment($table$field$step=1){

        
$sign $step '+' '-';
        
$step abs($step);

        
$sql "UPDATE {#}{$table} i
                SET i.
{$field} = i.{$field} {$sign} {$step}
                "
;

        if (
$this->where) { $sql .= "WHERE {$this->where}"; }

        
$this->resetFilters();

        return 
$this->db->query($sql);

    }

    public function 
decrement($table$field$step=1){
        return 
$this->increment($table$field$step * -1);
    }

//============================================================================//
//============================================================================//

    /**
     * Преобразует массив в YAML
     * @param array $array
     * @return string
     */
    
static public function arrayToYaml($array) {

        
cmsCore::loadLib('spyc.class');

        
$yaml Spyc::YAMLDump($array,2,40);

        return 
$yaml;

    }

    
/**
     * Преобразует YAML в массив
     * @param string $yaml
     * @return array
     */
    
static public function yamlToArray($yaml) {

        
cmsCore::loadLib('spyc.class');

        
$array Spyc::YAMLLoadString($yaml);

        return 
$array;

    }

}
Онлайн: 0
Реклама