View file veppa_wallpaper/sys/app/models/Tag.php

File size: 10.26Kb
<?php
/**
 * Free Wallpaper Script
 *
 * Free Wallpaper Script by Vepa Halliyev is licensed under a Creative Commons Attribution-Share Alike 3.0 License.
 *
 * @package		Free Wallpaper Script
 * @author		Vepa Halliyev
 * @copyright	Copyright (c) 2009, Vepa Halliyev, veppa.com.
 * @license		http://www.veppa.com/free-wallpaper-script/
 * @link		http://www.veppa.com/free-wallpaper-script/
 * @since		Version 1.0
 * @filesource
 */
/**
 * class Tag
 *
 * @author Vepa Halliyev
 * @since  1
 */

class Tag extends Record
{
	const TABLE_NAME = 'tag';
	private static $cols = array(
					't_id'=>1,         
					't_name'=>1,         
					't_banned'=>1        
	);

	public function __construct($data = false, $locale_db = false)
	{
		$this->setColumns(self::$cols);
		parent::__construct($data,$locale_db);
	}

	static function relatedTags($records,$num=20,$key_name = 'id')
	{
		// get realted tags

		// FIXME fix tag count per entry to 20 or 250 chars for posts

		if($num)
		{
			$limit = "LIMIT 0,".$num;
		}


		$sql = "SELECT t.t_name
				FROM ".TABLE_PREFIX."tag t LEFT JOIN ".TABLE_PREFIX."tag_relation r ON (r.r_tid=t.t_id) 
				WHERE  r.r_wid=?
				".$limit;

		//echo $sql;

		if(is_array($records))
		{
			foreach($records as $record)
			{
				$record->arr_tags = self::query($sql,array($record->{$key_name}));
			}
		}
		else
		{
			$record = $records;
			$record->arr_tags = self::query($sql,array($record->{$key_name}));
		}

		return $records;
	}



	static function getPopularTags($num = 20, $populer = true)
	{

		// TODO use cache for tags


		// get latest 2000 post id
		$latest = 2000;


		if($populer)
		{
			$ord = "GROUP BY r_wid DESC";
		}
		else
		{
			//rastgele
			$ord = "ORDER BY rand()";
		}


		$sql = "SELECT DISTINCT r_wid
				FROM ".TABLE_PREFIX."tag_relation 
				$ord
				LIMIT $latest";
				$ids = Record::queryArraySingle($sql,array(),MAIN_DB,'r_wid');

				return self::_convertToTagArray($ids,$num,true);
	}





	/**
	 * Get popular tags using latest 1000 records
	 *
	 * @param int $type
	 * @param int $num
	 * @param bool $populer
	 * @return array
	 */
	static public function getPopularTagsByUser($user_id,$num = 20, $populer=true)
	{
		// get latest 2000 post id
		$latest = 1000;


		// AND k.k_public=1  bunu eklesek cok yavasliyor cunku indexte yok
		// indexe eklesek cok fazla index oluyor
		$sql = "SELECT id
				FROM ".TABLE_PREFIX."wallpaper w
				WHERE w.added_by=?  AND w.public=1 
				ORDER BY w.id DESC 
				LIMIT $latest";

		$ids = Record::queryArraySingle($sql, array($user_id), MAIN_DB, 'id');

		return self::_convertToTagArray($ids,$num,$populer);
	}



	static private function _convertToTagArray($ids,$num, $populer )
	{
		$arr_r = array();

		if($populer)
		{
			$ord = "ORDER BY t_num DESC";
		}
		else
		{
			//rastgele
			$ord = "ORDER BY rand()";
		}

		$ids = array_unique($ids);

		if($ids)
		{
			$sql = "SELECT t.t_name, COUNT(t.t_id) as t_num
				FROM ".TABLE_PREFIX."tag t LEFT JOIN 
					 ".TABLE_PREFIX."tag_relation r ON (r.r_tid=t.t_id)
				WHERE r.r_wid IN (".implode(',',$ids).") AND t.t_banned='0' 
			GROUP BY r.r_tid $ord
			LIMIT $num";

			// free memory
			unset($ids);

			$r = Record::query($sql,array());

				
			$arr_r = self::_makeTagArray($r);
		}
		return $arr_r;
	}


	static private function _makeTagArray($records)
	{
		$arr_r = array();

		if($records)
		{
			$max_yogunluk = 0;
			foreach($records as $record)
			{
				$arr_tag_yogunluk[$record->t_name] = $record->t_num;
				if($max_yogunluk < $record->t_num)
				{
					$max_yogunluk = $record->t_num;
				}
			}

			unset($records);

			foreach($arr_tag_yogunluk as $key=>$val)
			{
				$val = round($val*10/$max_yogunluk);
				$arr_r[$key] = $val;
			}

			ksort( $arr_r );
		}
		return $arr_r;
	}


	/**
	 * Add tags and relation to wallpaper
	 *
	 * @uses Tag::str2tags_arr() to convert tags string to array
	 *
	 * @param string $str comma seperated tags
	 * @param int $r_wid wallpaper id
	 * @param bool $remove_old true remove old tag relations
	 * @return string comma seperated tags
	 */
	static function addTags($str, $r_wid, $remove_old = true)
	{
		$locale_db = MAIN_DB;
		$return = '';

		// convert tags string to array
		$arr_tags = self::str2tags_arr($str,250);

		// remove old tags and add new ones
		if($remove_old)
		{
			self::deleteWhere('TagRelation',
				"r_wid=?",
			array($r_wid),$locale_db);
		}


		if($arr_tags)
		{
			//get all tag keys from DB
			foreach($arr_tags as $tag)
			{
				$arr_tags_quoted[] = self::quote($tag,$locale_db);
			}

			// always use binding on string values or ? mark can come in query and give error
			$arr_q = array_fill(0,count($arr_tags),'?');

			//add values to database unique keys
			$query_extra = "(".implode("),(",$arr_q).")";
			$sql = "INSERT IGNORE INTO ".TABLE_PREFIX."tag (t_name) VALUES $query_extra";
			self::query($sql,$arr_tags,$locale_db);


			// get tags from db
			$query_where = "t_name IN (".implode(",",$arr_q).")";
			$tags = self::findAllFrom('Tag',$query_where,$arr_tags,$locale_db);

			$query_extra = array();
			foreach($tags as $tag)
			{
				$query_extra[] = "('".$tag->t_id."','$r_wid')";
			}
			$query_extra = implode(",",$query_extra);

			//now associate tags with post
			$sql = "INSERT INTO ".TABLE_PREFIX."tag_relation
					(r_tid,r_wid) 
					VALUES $query_extra";
			self::query($sql,false,$locale_db);

			$return = implode(',',$arr_tags);
		}

		return $return;
	}



	static function isBanned($tag)
	{
		$banned = self::findOneFrom('Tag','t_name=? AND t_banned=1',array($tag));
		return ($banned?true:false);
	}


	/**
	 * convert comma seperated string to tags array, converts chacartest to lowercase
	 *
	 * @param string $str comma seperated tags
	 * @param string $limit 0|int max number of characters if tags combined to a string
	 * @return array
	 */
	public static function str2tags_arr($str,$limit = 0)
	{

		use_helper('StringUtf8');

		// remove slashes for safe linking. (direcotory)
		$str = str_replace(array("/","\\"),"",$str);

		// convert to lowercase
		$str = StringUtf8::strtolower($str);

		//converts comma seperated tags to array with unique values
		$tagler = explode(",",$str);

		$arr = array();
		foreach($tagler as $tag)
		{
			$tag = trim($tag);
			if(!($tag=='' || $tag=='.' || $tag=='..'))
			{
				$arr[$tag] = 1;
			}
		}
			
		//limit
		if($limit)
		{
			$str = '';
			$arr_ = array();
			foreach($arr as $k => $v)
			{
				$str .= $k.',';
				if(strlen($str)<$limit)
				{
					$arr_[$k] = 1;
				}
			}

			$arr = $arr_;
		}

		return array_keys($arr);
	}

	/**
	 * Get all tags with weight
	 * @return array (tag=>weight)
	 */
	function getAllTags($limit=20)
	{

		if($limit)
		{
			$limit_str = "ORDER BY t_num DESC LIMIT $limit";
		}
		else
		{
			$limit_str = "";
		}

		$sql = "SELECT t.t_name, COUNT(t.t_id) as t_num
				FROM ".TABLE_PREFIX."tag t LEFT JOIN 
					 ".TABLE_PREFIX."tag_relation r ON (r.r_tid=t.t_id)
				WHERE t.t_banned='0' AND r.r_tid IS NOT NULL
			GROUP BY r.r_tid $limit_str";

		$r = self::query($sql,array());
			
		return self::_makeTagArray($r);
	}

	function beforeDelete()
	{
		// find wallpapers and update string tag values
		$tr = TagRelation::findAllFrom('TagRelation','r_tid=?',array($this->t_id));
		TagRelation::appendObject($tr,'r_wid','Wallpaper','id','wallpaper',MAIN_DB,'id,tags');
		foreach($tr as $t)
		{
			$t->wallpaper->tags = ','.$t->wallpaper->tags.',';
			$t->wallpaper->tags = str_replace(','.$this->t_name.',',',',$t->wallpaper->tags);
			$t->wallpaper->tags = trim($t->wallpaper->tags,',');
			if(!$t->wallpaper->save('id'))
			{
				return false;
			}
		}


		// delete existing unrelated tags
		self::deleteUnrelatedTags();


		// delete tag relation
		return TagRelation::deleteWhere('TagRelation','r_tid=?',array($this->t_id));
	}

	function deleteUnrelatedTags()
	{
		$sql = "DELETE t
				FROM ".TABLE_PREFIX."tag t LEFT JOIN ".TABLE_PREFIX."tag_relation tr ON (t.t_id=tr.r_tid) 
				WHERE tr.r_tid is NULL";
		self::query($sql);
	}

	static function url($tag,$order='',$page=1)
	{
		return get_url('tag/'.rawurlencode($tag).'/'.($order?$order.'/'.$page.'/':''));
	}


	static function normalizeTagsStr($str)
	{
		return implode(self::str2tags_arr($str,250),',');
	}

	
	static function mixWithCategories($tags,$categories,$sel_cats)
	{
		// mix tags with selected categories
		$tags = self::normalizeTagsStr($tags);
		$arr_tags = explode(',',$tags);
		$arr_k = array_flip($arr_tags);

		foreach($categories as $c)
		{
			$c_name = strtolower($c->name);
				
			if(in_array($c->id,$sel_cats))
			{
				// add this category as tag
				$arr_k[$c_name] = 1;
			}
			else
			{
				// remove this category from tags if exist
				unset($arr_k[$c_name]);
			}
		}
		
		/*echo $tags;
		print_r($categories);
		print_r($sel_cats);
		echo $tags;*/
		$tags = implode(',',array_keys($arr_k));

		return $tags;
	}
	
	
	static public function changeName($name_old,$name_new)
	{
		
		$name_old = Tag::normalizeTagsStr($name_old);
		
		// get tag 
		$tag_object = Tag::findOneFrom('Tag', 't_name=?', array($name_old));

		if ($tag_object)
		{
			// update tag name and save
			$tag_object->t_name = Tag::normalizeTagsStr($name_new);
			$tag_object->save('t_id');

			// find all wallpapers using same tag and update comma seperated tags string for each wallpaper
			$sql = "SELECT w.id,w.tags FROM 
				" . self::tableNameFromClassName('Wallpaper') . " w LEFT JOIN 
				" . self::tableNameFromClassName('TagRelation') . " tr ON(w.id=tr.r_wid)
				WHERE tr.r_tid=?";
			$wallpapers = Wallpaper::query($sql, array($tag_object->t_id));
			foreach ($wallpapers as $w)
			{
				$tags = explode(',', $w->tags);
				$tags = array_flip($tags);
				// remove old tag name from array
				unset($tags[$name_old]);
				// add new tag name to array
				$tags[$tag_object->t_name] = 1;

				// form new tags string using new values
				$w->tags = implode(',', array_keys($tags));

				// update wallpaper record
				Wallpaper::update('Wallpaper', array('tags'=> $w->tags), 'id=?', array($w->id));
			}
		}
	}
}