forked from Public/pics
		
	
		
			
				
	
	
		
			516 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			516 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
/*****************************************************************************
 | 
						|
 * Tag.php
 | 
						|
 * Contains key class Tag.
 | 
						|
 *
 | 
						|
 * Kabuki CMS (C) 2013-2015, Aaron van Geffen
 | 
						|
 *****************************************************************************/
 | 
						|
 | 
						|
class Tag
 | 
						|
{
 | 
						|
	public $id_tag;
 | 
						|
	public $id_parent;
 | 
						|
	public $id_asset_thumb;
 | 
						|
	public $id_user_owner;
 | 
						|
	public $tag;
 | 
						|
	public $slug;
 | 
						|
	public $description;
 | 
						|
	public $kind;
 | 
						|
	public $count;
 | 
						|
 | 
						|
	protected function __construct(array $data)
 | 
						|
	{
 | 
						|
		foreach ($data as $attribute => $value)
 | 
						|
			$this->$attribute = $value;
 | 
						|
	}
 | 
						|
 | 
						|
	public function __toString()
 | 
						|
	{
 | 
						|
		return $this->tag;
 | 
						|
	}
 | 
						|
 | 
						|
	public static function fromId($id_tag, $return_format = 'object')
 | 
						|
	{
 | 
						|
		$db = Registry::get('db');
 | 
						|
 | 
						|
		$row = $db->queryAssoc('
 | 
						|
			SELECT *
 | 
						|
			FROM tags
 | 
						|
			WHERE id_tag = :id_tag',
 | 
						|
			[
 | 
						|
				'id_tag' => $id_tag,
 | 
						|
			]);
 | 
						|
 | 
						|
		// Tag not found?
 | 
						|
		if (empty($row))
 | 
						|
			throw new NotFoundException();
 | 
						|
 | 
						|
		return $return_format === 'object' ? new Tag($row) : $row;
 | 
						|
	}
 | 
						|
 | 
						|
	public static function fromSlug($slug, $return_format = 'object')
 | 
						|
	{
 | 
						|
		$db = Registry::get('db');
 | 
						|
 | 
						|
		$row = $db->queryAssoc('
 | 
						|
			SELECT *
 | 
						|
			FROM tags
 | 
						|
			WHERE slug = :slug',
 | 
						|
			[
 | 
						|
				'slug' => $slug,
 | 
						|
			]);
 | 
						|
 | 
						|
		// Tag not found?
 | 
						|
		if (empty($row))
 | 
						|
			throw new NotFoundException();
 | 
						|
 | 
						|
		return $return_format === 'object' ? new Tag($row) : $row;
 | 
						|
	}
 | 
						|
 | 
						|
	public static function getAll($limit = 0, $return_format = 'array')
 | 
						|
	{
 | 
						|
		$rows = Registry::get('db')->queryAssocs('
 | 
						|
			SELECT *
 | 
						|
			FROM tags
 | 
						|
			ORDER BY ' . ($limit > 0 ? 'count
 | 
						|
			LIMIT :limit' : 'tag'),
 | 
						|
			[
 | 
						|
				'limit' => $limit,
 | 
						|
			]);
 | 
						|
 | 
						|
		// No tags found?
 | 
						|
		if (empty($rows))
 | 
						|
			return [];
 | 
						|
 | 
						|
		// Limited? Make sure the lot is sorted alphabetically.
 | 
						|
		if (!empty($limit))
 | 
						|
		{
 | 
						|
			usort($rows, function($a, $b) {
 | 
						|
				return strcmp($a['tag'], $b['tag']);
 | 
						|
			});
 | 
						|
		}
 | 
						|
 | 
						|
		if ($return_format === 'object')
 | 
						|
		{
 | 
						|
			$return = [];
 | 
						|
			foreach ($rows as $row)
 | 
						|
				$return[$row['id_tag']] = new Tag($row);
 | 
						|
			return $return;
 | 
						|
		}
 | 
						|
		else
 | 
						|
			return $rows;
 | 
						|
	}
 | 
						|
 | 
						|
	public static function getAllByOwner($id_user_owner)
 | 
						|
	{
 | 
						|
		$db = Registry::get('db');
 | 
						|
		$res = $db->query('
 | 
						|
			SELECT *
 | 
						|
			FROM tags
 | 
						|
			WHERE id_user_owner = :id_user_owner
 | 
						|
			ORDER BY tag',
 | 
						|
			[
 | 
						|
				'id_user_owner' => $id_user_owner,
 | 
						|
			]);
 | 
						|
 | 
						|
		$objects = [];
 | 
						|
		while ($row = $db->fetchAssoc($res))
 | 
						|
			$objects[$row['id_tag']] = new Tag($row);
 | 
						|
 | 
						|
		return $objects;
 | 
						|
	}
 | 
						|
 | 
						|
	public static function getAlbums($id_parent = 0, $offset = 0, $limit = 24, $return_format = 'array')
 | 
						|
	{
 | 
						|
		$rows = Registry::get('db')->queryAssocs('
 | 
						|
			SELECT *
 | 
						|
			FROM tags
 | 
						|
			WHERE id_parent = :id_parent AND kind = :kind
 | 
						|
			ORDER BY tag ASC
 | 
						|
			LIMIT :offset, :limit',
 | 
						|
			[
 | 
						|
				'id_parent' => $id_parent,
 | 
						|
				'kind' => 'Album',
 | 
						|
				'offset' => $offset,
 | 
						|
				'limit' => $limit,
 | 
						|
			]);
 | 
						|
 | 
						|
		if ($return_format === 'object')
 | 
						|
		{
 | 
						|
			$return = [];
 | 
						|
			foreach ($rows as $row)
 | 
						|
				$return[$row['id_tag']] = new Tag($row);
 | 
						|
			return $return;
 | 
						|
		}
 | 
						|
		else
 | 
						|
			return $rows;
 | 
						|
	}
 | 
						|
 | 
						|
	public function getContributorList()
 | 
						|
	{
 | 
						|
		return Registry::get('db')->queryPairs('
 | 
						|
			SELECT u.id_user, u.first_name, u.surname, u.slug, COUNT(*) AS num_assets
 | 
						|
			FROM assets_tags AS at
 | 
						|
			LEFT JOIN assets AS a ON at.id_asset = a.id_asset
 | 
						|
			LEFT JOIN users AS u ON a.id_user_uploaded = u.id_user
 | 
						|
			WHERE at.id_tag = :id_tag
 | 
						|
			GROUP BY a.id_user_uploaded
 | 
						|
			ORDER BY u.first_name, u.surname',
 | 
						|
			[
 | 
						|
				'id_tag' => $this->id_tag,
 | 
						|
			]);
 | 
						|
	}
 | 
						|
 | 
						|
	public static function getPeople($id_parent = 0, $offset = 0, $limit = 24, $return_format = 'array')
 | 
						|
	{
 | 
						|
		$rows = Registry::get('db')->queryAssocs('
 | 
						|
			SELECT *
 | 
						|
			FROM tags
 | 
						|
			WHERE id_parent = :id_parent AND kind = :kind
 | 
						|
			ORDER BY tag ASC
 | 
						|
			LIMIT :offset, :limit',
 | 
						|
			[
 | 
						|
				'id_parent' => $id_parent,
 | 
						|
				'kind' => 'Person',
 | 
						|
				'offset' => $offset,
 | 
						|
				'limit' => $limit,
 | 
						|
			]);
 | 
						|
 | 
						|
		if ($return_format === 'object')
 | 
						|
		{
 | 
						|
			$return = [];
 | 
						|
			foreach ($rows as $row)
 | 
						|
				$return[$row['id_tag']] = new Tag($row);
 | 
						|
			return $return;
 | 
						|
		}
 | 
						|
		else
 | 
						|
			return $rows;
 | 
						|
	}
 | 
						|
 | 
						|
	public static function byAssetId($id_asset, $return_format = 'object')
 | 
						|
	{
 | 
						|
		$rows = Registry::get('db')->queryAssocs('
 | 
						|
			SELECT *
 | 
						|
			FROM tags
 | 
						|
			WHERE id_tag IN(
 | 
						|
				SELECT id_tag
 | 
						|
				FROM assets_tags
 | 
						|
				WHERE id_asset = :id_asset
 | 
						|
			)
 | 
						|
			ORDER BY count DESC',
 | 
						|
			[
 | 
						|
				'id_asset' => $id_asset,
 | 
						|
			]);
 | 
						|
 | 
						|
		// No tags found?
 | 
						|
		if (empty($rows))
 | 
						|
			return [];
 | 
						|
 | 
						|
		if ($return_format === 'object')
 | 
						|
		{
 | 
						|
			$return = [];
 | 
						|
			foreach ($rows as $row)
 | 
						|
				$return[$row['id_tag']] = new Tag($row);
 | 
						|
			return $return;
 | 
						|
		}
 | 
						|
		else
 | 
						|
			return $rows;
 | 
						|
	}
 | 
						|
 | 
						|
	public static function byPostId($id_post, $return_format = 'object')
 | 
						|
	{
 | 
						|
		$rows = Registry::get('db')->queryAssocs('
 | 
						|
			SELECT *
 | 
						|
			FROM tags
 | 
						|
			WHERE id_tag IN(
 | 
						|
				SELECT id_tag
 | 
						|
				FROM posts_tags
 | 
						|
				WHERE id_post = :id_post
 | 
						|
			)
 | 
						|
			ORDER BY count DESC',
 | 
						|
			[
 | 
						|
				'id_post' => $id_post,
 | 
						|
			]);
 | 
						|
 | 
						|
		// No tags found?
 | 
						|
		if (empty($rows))
 | 
						|
			return [];
 | 
						|
 | 
						|
		if ($return_format === 'object')
 | 
						|
		{
 | 
						|
			$return = [];
 | 
						|
			foreach ($rows as $row)
 | 
						|
				$return[$row['id_tag']] = new Tag($row);
 | 
						|
			return $return;
 | 
						|
		}
 | 
						|
		else
 | 
						|
			return $rows;
 | 
						|
	}
 | 
						|
 | 
						|
	public static function recount(array $id_tags = [])
 | 
						|
	{
 | 
						|
		return Registry::get('db')->query('
 | 
						|
			UPDATE tags AS t SET count = (
 | 
						|
				SELECT COUNT(*)
 | 
						|
				FROM `assets_tags` AS at
 | 
						|
				WHERE at.id_tag = t.id_tag
 | 
						|
			)' . (!empty($id_tags) ? '
 | 
						|
			WHERE t.id_tag IN(@id_tags)' : ''),
 | 
						|
			['id_tags' => $id_tags]);
 | 
						|
	}
 | 
						|
 | 
						|
	public static function createNew(array $data, $return_format = 'object')
 | 
						|
	{
 | 
						|
		$db = Registry::get('db');
 | 
						|
 | 
						|
		if (!isset($data['id_parent']))
 | 
						|
			$data['id_parent'] = 0;
 | 
						|
 | 
						|
		if (!isset($data['description']))
 | 
						|
			$data['description'] = '';
 | 
						|
 | 
						|
		if (!isset($data['count']))
 | 
						|
			$data['count'] = 0;
 | 
						|
 | 
						|
		$res = $db->query('
 | 
						|
			INSERT IGNORE INTO tags
 | 
						|
			(id_parent, tag, slug, kind, description, count)
 | 
						|
			VALUES
 | 
						|
			(:id_parent, :tag, :slug, :kind, :description, :count)
 | 
						|
			ON DUPLICATE KEY UPDATE count = count + 1',
 | 
						|
			$data);
 | 
						|
 | 
						|
		if (!$res)
 | 
						|
			throw new Exception('Could not create the requested tag.');
 | 
						|
 | 
						|
		$data['id_tag'] = $db->insertId();
 | 
						|
		return $return_format === 'object' ? new Tag($data) : $data;
 | 
						|
	}
 | 
						|
 | 
						|
	public function getUrl()
 | 
						|
	{
 | 
						|
		return BASEURL . '/' . $this->slug . '/';
 | 
						|
	}
 | 
						|
 | 
						|
	public function save()
 | 
						|
	{
 | 
						|
		return Registry::get('db')->query('
 | 
						|
			UPDATE tags
 | 
						|
			SET
 | 
						|
				id_parent = :id_parent,
 | 
						|
				id_asset_thumb = :id_asset_thumb,' . (isset($this->id_user_owner) ? '
 | 
						|
				id_user_owner = :id_user_owner,' : '') . '
 | 
						|
				tag = :tag,
 | 
						|
				slug = :slug,
 | 
						|
				kind = :kind,
 | 
						|
				description = :description,
 | 
						|
				count = :count
 | 
						|
			WHERE id_tag = :id_tag',
 | 
						|
			get_object_vars($this));
 | 
						|
	}
 | 
						|
 | 
						|
	public function delete()
 | 
						|
	{
 | 
						|
		$db = Registry::get('db');
 | 
						|
 | 
						|
		// Unlink any tagged assets
 | 
						|
		$res = $db->query('
 | 
						|
			DELETE FROM assets_tags
 | 
						|
			WHERE id_tag = :id_tag',
 | 
						|
			[
 | 
						|
				'id_tag' => $this->id_tag,
 | 
						|
			]);
 | 
						|
 | 
						|
		if (!$res)
 | 
						|
			return false;
 | 
						|
 | 
						|
		// Delete the actual tag
 | 
						|
		return $db->query('
 | 
						|
			DELETE FROM tags
 | 
						|
			WHERE id_tag = :id_tag',
 | 
						|
			[
 | 
						|
				'id_tag' => $this->id_tag,
 | 
						|
			]);
 | 
						|
	}
 | 
						|
 | 
						|
	public function resetIdAsset()
 | 
						|
	{
 | 
						|
		$db = Registry::get('db');
 | 
						|
		$new_id = $db->queryValue('
 | 
						|
			SELECT MAX(id_asset) as new_id
 | 
						|
			FROM assets_tags
 | 
						|
			WHERE id_tag = :id_tag',
 | 
						|
			[
 | 
						|
				'id_tag' => $this->id_tag,
 | 
						|
			]);
 | 
						|
 | 
						|
		return $db->query('
 | 
						|
			UPDATE tags
 | 
						|
			SET id_asset_thumb = :new_id
 | 
						|
			WHERE id_tag = :id_tag',
 | 
						|
			[
 | 
						|
				'new_id' => $new_id ?? 0,
 | 
						|
				'id_tag' => $this->id_tag,
 | 
						|
			]);
 | 
						|
	}
 | 
						|
 | 
						|
	public static function match($tokens)
 | 
						|
	{
 | 
						|
		if (!is_array($tokens))
 | 
						|
			$tokens = explode(' ', $tokens);
 | 
						|
 | 
						|
		return Registry::get('db')->queryPair('
 | 
						|
			SELECT id_tag, tag
 | 
						|
			FROM tags
 | 
						|
			WHERE LOWER(tag) LIKE :tokens
 | 
						|
			ORDER BY tag ASC',
 | 
						|
			['tokens' => '%' . strtolower(implode('%', $tokens)) . '%']);
 | 
						|
	}
 | 
						|
 | 
						|
	public static function matchPeople($tokens)
 | 
						|
	{
 | 
						|
		if (!is_array($tokens))
 | 
						|
			$tokens = explode(' ', $tokens);
 | 
						|
 | 
						|
		return Registry::get('db')->queryPairs('
 | 
						|
			SELECT id_tag, tag, slug
 | 
						|
			FROM tags
 | 
						|
			WHERE LOWER(tag) LIKE {string:tokens} AND
 | 
						|
				kind = {string:person}
 | 
						|
			ORDER BY tag ASC',
 | 
						|
			[
 | 
						|
				'tokens' => '%' . strtolower(implode('%', $tokens)) . '%',
 | 
						|
				'person' => 'Person',
 | 
						|
			]);
 | 
						|
	}
 | 
						|
 | 
						|
	public static function exactMatch($tag)
 | 
						|
	{
 | 
						|
		if (!is_string($tag))
 | 
						|
			throw new InvalidArgumentException('Expecting a string!');
 | 
						|
 | 
						|
		return Registry::get('db')->queryPair('
 | 
						|
			SELECT id_tag, tag
 | 
						|
			FROM tags
 | 
						|
			WHERE tag = :tag',
 | 
						|
			['tag' => $tag]);
 | 
						|
	}
 | 
						|
 | 
						|
	public static function matchSlug($slug)
 | 
						|
	{
 | 
						|
		if (!is_string($slug))
 | 
						|
			throw new InvalidArgumentException('Expecting a string!');
 | 
						|
 | 
						|
		return Registry::get('db')->queryValue('
 | 
						|
			SELECT id_tag
 | 
						|
			FROM tags
 | 
						|
			WHERE slug = :slug',
 | 
						|
			['slug' => $slug]);
 | 
						|
	}
 | 
						|
 | 
						|
	public static function matchAll(array $tags)
 | 
						|
	{
 | 
						|
		return Registry::get('db')->queryPair('
 | 
						|
			SELECT tag, id_tag
 | 
						|
			FROM tags
 | 
						|
			WHERE tag IN (:tags)',
 | 
						|
			['tags' => $tags]);
 | 
						|
	}
 | 
						|
 | 
						|
	public static function getCount($only_used = true, $kind = '', $isAlbum = false)
 | 
						|
	{
 | 
						|
		$where = [];
 | 
						|
		if ($only_used)
 | 
						|
			$where[] = 'count > 0';
 | 
						|
		if (empty($kind))
 | 
						|
			$kind = 'Album';
 | 
						|
 | 
						|
		$operator = $isAlbum ? '=' : '!=';
 | 
						|
		$where[] = 'kind ' . $operator . ' :kind';
 | 
						|
		$where = implode(' AND ', $where);
 | 
						|
 | 
						|
		return Registry::get('db')->queryValue('
 | 
						|
			SELECT COUNT(*)
 | 
						|
			FROM tags
 | 
						|
			WHERE ' . $where,
 | 
						|
			[
 | 
						|
				'kind' => $kind,
 | 
						|
			]);
 | 
						|
	}
 | 
						|
 | 
						|
	public static function getOffset($offset, $limit, $order, $direction, $isAlbum = false)
 | 
						|
	{
 | 
						|
		assert(in_array($order, ['id_tag', 'tag', 'slug', 'count']));
 | 
						|
		$order = $order . ($direction === 'up' ? ' ASC' : ' DESC');
 | 
						|
 | 
						|
		$operator = $isAlbum ? '=' : '!=';
 | 
						|
 | 
						|
		$db = Registry::get('db');
 | 
						|
		$res = $db->query('
 | 
						|
			SELECT t.*, u.id_user, u.first_name, u.surname
 | 
						|
			FROM tags AS t
 | 
						|
			LEFT JOIN users AS u ON t.id_user_owner = u.id_user
 | 
						|
			WHERE kind ' . $operator . ' :album
 | 
						|
			ORDER BY id_parent, ' . $order . '
 | 
						|
			LIMIT :offset, :limit',
 | 
						|
			[
 | 
						|
				'offset' => $offset,
 | 
						|
				'limit' => $limit,
 | 
						|
				'album' => 'Album',
 | 
						|
			]);
 | 
						|
 | 
						|
		$albums_by_parent = [];
 | 
						|
		while ($row = $db->fetchAssoc($res))
 | 
						|
		{
 | 
						|
			if (!isset($albums_by_parent[$row['id_parent']]))
 | 
						|
				$albums_by_parent[$row['id_parent']] = [];
 | 
						|
 | 
						|
			$albums_by_parent[$row['id_parent']][] = $row + ['children' => []];
 | 
						|
		}
 | 
						|
 | 
						|
		$albums = self::getChildrenRecursively(0, 0, $albums_by_parent);
 | 
						|
		$rows = self::flattenChildrenRecursively($albums);
 | 
						|
 | 
						|
		return $rows;
 | 
						|
	}
 | 
						|
 | 
						|
	private static function getChildrenRecursively($id_parent, $level, &$albums_by_parent)
 | 
						|
	{
 | 
						|
		$children = [];
 | 
						|
		if (!isset($albums_by_parent[$id_parent]))
 | 
						|
			return $children;
 | 
						|
 | 
						|
		foreach ($albums_by_parent[$id_parent] as $child)
 | 
						|
		{
 | 
						|
			if (isset($albums_by_parent[$child['id_tag']]))
 | 
						|
				$child['children'] = self::getChildrenRecursively($child['id_tag'], $level + 1, $albums_by_parent);
 | 
						|
 | 
						|
			$child['tag'] = ($level ? str_repeat('—', $level * 2) . ' ' : '') . $child['tag'];
 | 
						|
			$children[] = $child;
 | 
						|
		}
 | 
						|
 | 
						|
		return $children;
 | 
						|
	}
 | 
						|
 | 
						|
	private static function flattenChildrenRecursively($albums)
 | 
						|
	{
 | 
						|
		if (empty($albums))
 | 
						|
			return [];
 | 
						|
 | 
						|
		$rows = [];
 | 
						|
		foreach ($albums as $album)
 | 
						|
		{
 | 
						|
			static $headers_to_keep = ['id_tag', 'tag', 'slug', 'count', 'id_user', 'first_name', 'surname'];
 | 
						|
			$rows[] = array_intersect_key($album, array_flip($headers_to_keep));
 | 
						|
			if (!empty($album['children']))
 | 
						|
			{
 | 
						|
				$children = self::flattenChildrenRecursively($album['children']);
 | 
						|
				foreach ($children as $child)
 | 
						|
					$rows[] = array_intersect_key($child, array_flip($headers_to_keep));
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		return $rows;
 | 
						|
	}
 | 
						|
}
 |