Changeset 3114

Show
Ignore:
Timestamp:
04/13/08 09:33:59 (3 months ago)
Author:
pmjones
Message:

Solar_Model_Nodes


* [DEL] Method _newSelectByTags() is now entirely unnecessary, because the

new Solar_Sql_Model::newSelect() method now adds all types of eager joins
for us via $params.

* [REF] Refactored method fetchAllByTags() to use only fetchAll($params),

instead of building a custom SELECT and running it through the previous
model _fetchAll() support method.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/Solar/Model/Nodes.php

    r3039 r3114  
    173173     * Fetches a collection of nodes with certain tags. 
    174174     *  
    175      * @param array $tag_list Fetch only nodes with all of these tags. 
     175     * @param array $tag_list Fetch only nodes with all of these tags. If 
     176     * empty, will fetch all nodes. 
    176177     *  
    177178     * @param array $params Added parameters for the SELECT. 
     
    182183    public function fetchAllByTags($tag_list, $params = null) 
    183184    { 
    184         // no tags? fetch all to pre-empt errors related to "IN()" not 
    185         // having a list to work with. 
    186185        $tag_list = $this->_fixTagList($tag_list); 
    187         if (! $tag_list) { 
    188             return $this->fetchAll($params); 
     186        if ($tag_list) { 
     187            // use this so we can inherit different model names 
     188            $native_primary = "{$this->_model_name}.{$this->_primary_col}"; 
     189             
     190            // eager-join to tags 
     191            $params['eager'][] = 'tags'; 
     192             
     193            // find tags in this list 
     194            $params['where']['tags.name in (?)'] = $tag_list; 
     195             
     196            // group by the model primary key so that multiple tag matches 
     197            // only return one row 
     198            $params['group'][] = $native_primary; 
     199             
     200            // make sure that all tags match 
     201            $params['having']["COUNT($native_primary) = ?"] = count($tag_list); 
    189202        } 
    190203         
    191         // fetch 
    192         $select = $this->_newSelectByTags($tag_list, $params); 
    193         return $this->_fetchAll($select, $params); 
     204        return $this->fetchAll($params); 
    194205    } 
    195206     
     
    213224        $tag_list = array_unique($tag_list); 
    214225         
    215         // if the string tag-list is empty, the preg-split leaves one empty 
     226        // if the string tag-list was empty, the preg-split leaves one empty 
    216227        // element in the array. 
    217         if ($tag_list[0] == '') { 
     228        if (count($tag_list) == 1 && reset($tag_list) == '') { 
    218229            $tag_list = array(); 
    219230        } 
     
    222233        return $tag_list; 
    223234    } 
    224      
    225     /** 
    226      *  
    227      * Support method to create a new selection tool based on tag lists. 
    228      *  
    229      * @param array $tag_list The list of tags to select by. 
    230      *  
    231      * @param array &$params A reference to added parameters for the SELECT. 
    232      *  
    233      * @return Solar_Sql_Select 
    234      *  
    235      */ 
    236     protected function _newSelectByTags($tag_list, &$params) 
    237     { 
    238         // setup 
    239         $params = $this->fixSelectParams($params); 
    240         $select = $this->newSelect($params['eager']); 
    241          
    242         // catalog entries for joining 
    243         $taggings = $this->_related['taggings']; 
    244         $tags     = $this->_related['tags']; 
    245          
    246         // primary key on the nodes table as an alias; e.g., "nodes.id" 
    247         $native_primary = "{$this->_model_name}.{$this->_primary_col}"; 
    248          
    249         // http://forge.mysql.com/wiki/TagSchema 
    250         // build the select differently from other fetchAll() statements 
    251         $select->distinct($params['distinct']) 
    252                ->from("{$this->_table_name} AS {$this->_model_name}", $params['cols']) 
    253                // join taggings on nodes 
    254                ->join( 
    255                    "{$taggings->foreign_table} AS {$taggings->foreign_alias}", 
    256                    "{$taggings->foreign_alias}.node_id = $native_primary" 
    257                ) 
    258                // join tags on taggings 
    259                ->join( 
    260                    "{$tags->foreign_table} AS {$tags->foreign_alias}", 
    261                    "{$tags->foreign_alias}.id = {$taggings->foreign_alias}.tag_id" 
    262                ) 
    263                // select for the listed tags 
    264                ->where("{$tags->foreign_alias}.name IN (?)", $tag_list) 
    265                // user-provided WHERE 
    266                ->multiWhere($params['where']) 
    267                // group by nodes.id to collapse multiple nodes (1 for each tag) 
    268                ->group($native_primary) 
    269                // make sure the tag-count matches 
    270                ->having("COUNT($native_primary) = ?", count($tag_list)) 
    271                // user-provided ORDER, paging, etc 
    272                ->order($params['order']) 
    273                ->setPaging($params['paging']) 
    274                ->limitPage($params['page']) 
    275                ->bind($params['bind']); 
    276          
    277         // done! 
    278         return $select; 
    279     } 
    280      
    281     /** 
    282      *  
    283      * Gets a count of nodes and pages-of-nodes with certain tags. 
    284      *  
    285      * @param array $tag_list Count only nodes with all of these tags. 
    286      *  
    287      * @param array $params Added parameters for the SELECT. 
    288      *  
    289      * @return array An array with elemets 'count' (the number of nodes) and 
    290      * 'pages' (the number of pages-of-nodes). 
    291      *  
    292      */ 
    293     public function countPagesByTags($tag_list, $params = null) 
    294     { 
    295         $tag_list = $this->_fixTagList($tag_list); 
    296         if (! $tag_list) { 
    297             return $this->countPages($params); 
    298         } 
    299          
    300         // we need to select the nodes + tags as an "inner" sub-select; 
    301         // clear any limits on it. 
    302         $inner = $this->_newSelectByTags($tag_list, $params); 
    303         $inner->clear('limit'); 
    304          
    305         // set up the outer select, which will wrap the inner sub-select 
    306         $outer = Solar::factory($this->_select_class, array( 
    307             'sql' => $this->_sql 
    308         )); 
    309          
    310         // wrap the sub-select and make sure paging is correct 
    311         $outer->fromSelect($inner, $this->_model_name); 
    312         $outer->setPaging($this->_paging); 
    313          
    314         // *now* get the count of pages with the tags requested 
    315         return $outer->countPages("{$this->_model_name}.{$this->_primary_col}"); 
    316     } 
    317235}