class Tag_Model extends Model { public function get_related_tags( $tags ) { ## Get db entries with specific tags and build array with counts ## is it cached already? ------------------------------------------------ $this->cache = Cache::instance(); $tags = array_filter( array_flip(array_flip($tags)) ); sort($tags); $cache_name = implode('', $tags); $cache = $this->cache->get( $cache_name ); if( $cache ) return $cache; ## not cached, fire up --------------------------------------------------- $db = Database::instance(); ## count tagged items ---------------------------------------------------- // build like string $like = array(); foreach( $tags as $tag ) $like[] = "tags LIKE '%$tag%'"; $like = implode(' AND ', $like); // get counts $count = $db->query("SELECT count(id) AS count FROM `articles` WHERE $like")->current()->count; ## check what tags are related ------------------------------------------ $offset = 0; $step = 300; $related_tags = array(); while( $offset < $count ) { $assets = $db->query("SELECT tags FROM `articles` WHERE $like ORDER BY id ASC LIMIT $step OFFSET $offset"); foreach($assets as $asset) { // tags $input = explode( ' ', trim($asset->tags) ); foreach( $input as $k => $v ) { if( $v == ''){ //do nothing, shouldnt be here anyway } elseif( array_key_exists($v, $related_tags) ){ $related_tags[$v]++; } else{ $related_tags[$v] = 1; } } } $offset += $step; } // remove already displayed from list foreach( $tags as $tag ) unset( $related_tags[$tag] ); ksort($related_tags); // set cache $this->cache->set( $cache_name, array($related_tags, $count), 'related_tags_counts', 0); return array($related_tags, $count); } public function update_tags( $tags, $saved_tags ) { // make array if not already if( ! is_array($tags) ) { $tags = explode(' ', trim($tags) ); } if( ! is_array($saved_tags) ) { $saved_tags = explode(' ', trim($saved_tags) ); } // find new tags $new_tags = array_filter( array_diff($tags, $saved_tags) ); // update counts if( count($new_tags) > 0 ) { $this->add_tags($new_tags); } // find removed tags $removed_tags = array_filter( array_diff($saved_tags, $tags) ); // update counts if( count($removed_tags) > 0 ) { $this->remove_tags($removed_tags); } } private function add_tags( $new_tags ) { $db = Database::instance(); // check if tags are new system wide // try to load all and then compare $tags_db = array(); $tags_in_db = $db->in('tag_name', $new_tags)->get('tags'); foreach( $tags_in_db as $t ) { $tags_db[] = $t->tag_name; } $system_new_tags = array_filter( array_diff($new_tags, $tags_db) ); // insert new tags to db if necessary if( count($system_new_tags) > 0 ) { $tag_array = array(); foreach( $system_new_tags as $t ) { $tag_array[] = "('$t')"; } $tag_str = implode(',', $tag_array); $sql = "INSERT INTO tags (tag_name) VALUES $tag_str"; $db->query($sql); } // update counts $tag_array = array(); foreach( $new_tags as $t ) { $tag_array[] = "'$t'"; } $tag_str = implode(',', $tag_array); $sql = "UPDATE tags SET `tag_count`=`tag_count`+1 WHERE `tag_name` IN ($tag_str)"; $db->query($sql); } private function remove_tags( $removed_tags ) { $db = Database::instance(); // update counts $tag_array = array(); foreach( $removed_tags as $t ) { $tag_array[] = "'$t'"; } $tag_str = implode(',', $tag_array); $sql = "UPDATE tags SET `tag_count`=`tag_count`-1 WHERE `tag_name` IN ($tag_str)"; $db->query($sql); } }