<?php
/**
* SocialEngine
*
* @category Application_Core
* @package Core
* @copyright Copyright 2006-2020 Webligo Developments
* @license http://www.socialengine.com/license/
* @version $Id: Tags.php 9747 2012-07-26 02:08:08Z john $
* @author John
*/
/**
* @category Application_Core
* @package Core
* @copyright Copyright 2006-2020 Webligo Developments
* @license http://www.socialengine.com/license/
*/
class Core_Model_DbTable_Tags extends Engine_Db_Table
{
protected $_rowClass = 'Core_Model_Tag';
/**
* Get the tag table
*
* @return Engine_Db_Table
*/
public function getTagTable()
{
return $this;
}
/**
* Get the tag map table
*
* @return Engine_Db_Table
*/
public function getMapTable()
{
return Engine_Api::_()->getDbtable('TagMaps', 'core');
}
// Tags
/**
* Get an existing or create a new text tag
*
* @param string $text The tag text
* @return Core_Model_Tag
*/
public function getTag($text, $createNew)
{
$text = $this->formatTagText($text);
if (empty($text)) {
return;
}
$table = $this->getTagTable();
$select = $table->select()
->where('text = ?', $text);
$row = $table->fetchRow($select);
if( null === $row && $createNew)
{
$row = $table->createRow();
$row->text = $text;
$row->save();
}
return $row;
}
public function getTagsByTagger($resource, Core_Model_Item_Abstract $tagger)
{
if( $resource instanceof Core_Model_Item_Abstract )
{
$resource_type = $resource->getType();
}
else
{
$resource_type = (string) $resource;
}
$mapTable = $this->getMapTable();
$select = $mapTable->select()
->where('resource_type = ?', $resource_type)
//->where('resource_id = ?', $resource->getIdentity())
->where('tagger_type = ?', $tagger->getType())
->where('tagger_id = ?', $tagger->getIdentity())
->where('tag_type = ?', 'core_tag')
->order('tag_id ASC');
$identities = array();
foreach( $mapTable->fetchAll($select) as $tagmap )
{
$identities[] = $tagmap->tag_id;
}
return Engine_Api::_()->getItemMulti('core_tag', $identities);
}
public function getTagsByText($text = null, $limit = 10)
{
$table = $this->getTagTable();
$select = $table->select()
->order('text ASC')
->limit($limit);
if( $text )
{
$select->where('text LIKE ?', '%'.$text.'%');
}
return $table->fetchAll($select);
}
/**
* Called on text tags for formatting
*
* @param string $text
* @return string
*/
public function formatTagText($text)
{
// We can do formatting on tags later
return trim($text);
}
// Tagging
/**
* Tag a resource
*
* @param Core_Model_Item_Abstract $resource The resource being tagged
* @param Core_Model_Item_Abstract $tagger The resource doing the tagging
* @param string|Core_Model_Item_Abstract $tag What is tagged in resource
* @param array|null $extra
* @return Engine_Db_Table_Row|null
*/
public function addTagMap(Core_Model_Item_Abstract $resource, Core_Model_Item_Abstract $tagger, $tag, $extra = null)
{
$tag = $this->_getTag($tag, true);
if( !$tag ) {
return false;
}
// Check if resource was already tagged with this
if( null !== ($tagmap = $this->getTagMap($resource, $tag)) ) {
return false; // return $tagmap;
//throw new Core_Model_Exception('Resource was already tagged as this');
}
// Do the tagging
$table = $this->getMapTable();
$tagmap = $table->createRow();
$tagmap->setFromArray(array(
'resource_type' => $resource->getType(),
'resource_id' => $resource->getIdentity(),
'tagger_type' => $tagger->getType(),
'tagger_id' => $tagger->getIdentity(),
'tag_type' => $tag->getType(),
'tag_id' => $tag->getIdentity(),
'creation_date' => new Zend_Db_Expr('NOW()'),
'extra' => $extra
));
$tagmap->save();
if (isset($tag->tag_count)) {
$tag->tag_count = $tag->tag_count + 1;
}
$tag->modified_date = date('Y-m-d H:i:s');
$tag->save();
return $tagmap;
}
/**
* Add multiple tags
*
* @param Core_Model_Item_Abstract $resource
* @param Core_Model_Item_Abstract $tagger
* @param array $tags
* @return array
*/
public function addTagMaps(Core_Model_Item_Abstract $resource, Core_Model_Item_Abstract $tagger, array $tags)
{
$tagmaps = array();
foreach( $tags as $key => $value )
{
// ignore empty tags
if (empty($value)) continue;
if( is_numeric($key) )
{
$tagmaps[] = $this->addTagMap($resource, $tagger, $value);
}
else
{
$tagmaps[] = $this->addTagMap($resource, $tagger, $key, $value);
}
}
return $tagmaps;
}
/**
* Get a tag map on resource and existing tag (for checking if already tagged)
*
* @param Core_Model_Item_Abstract $resource
* @param string|Core_Model_Item_Abstract $tag
* @return Engine_Db_Table|null
*/
public function getTagMap(Core_Model_Item_Abstract $resource, $tag)
{
$tag = $this->_getTag($tag);
$table = $this->getMapTable();
$select = $table->select()
->where('resource_type = ?', $resource->getType())
->where('resource_id = ?', $resource->getIdentity())
->where('tag_type = ?', $tag->getType())
->where('tag_id = ?', $tag->getIdentity())
->limit(1)
;
$tagmap = $table->fetchRow($select);
return $tagmap;
}
/**
* Get a tagmap by id that is part of resource
*
* @param Core_Model_Item_Abstract $resource
* @param integer $id
*/
public function getTagMapById(Core_Model_Item_Abstract $resource, $id)
{
$table = $this->getMapTable();
$select = $table->select()
->where('resource_type = ?', $resource->getType())
->where('resource_id = ?', $resource->getIdentity())
->where('tagmap_id = ?', (int) $id)
->limit(1)
;
$tagmap = $table->fetchRow($select);
return $tagmap;
}
/**
* Get all tags for a resource
*
* @param Core_Model_Item_Abstract $resource
* @return Engine_Db_Table_Rowset
*/
public function getTagMaps(Core_Model_Item_Abstract $resource)
{
return $this->getMapTable()->fetchAll($this->getTagMapSelect($resource));
}
/**
* Get a select object for tags on a resource
*
* @param Core_Model_Item_Abstract $resource
* @return Zend_Db_Table_Select
*/
public function getTagMapSelect(Core_Model_Item_Abstract $resource)
{
$table = $this->getMapTable();
$select = $table->select()
->where('resource_type = ?', $resource->getType())
->where('resource_id = ?', $resource->getIdentity())
->order('tag_id ASC')
;
return $select;
}
public function setTagMaps(Core_Model_Item_Abstract $resource, $tagger, array $tags)
{
$existingTagMaps = $this->getTagMaps($resource);
$added = array();
$setTagIndex = array();
$tagObjects = array();
foreach( $tags as $tag )
{
if(empty($tag)) {
continue;
}
$tagObject = $this->_getTag($tag, true);
if (empty($tagObject)) {
continue;
}
$tagObjects[] = $tagObject;
$setTagIndex[$tagObject->getGuid()] = $tagObject;
}
// Check for new tags
foreach( $tagObjects as $tag )
{
if( !$existingTagMaps->getRowMatching(array(
'tag_type' => $tag->getType(),
'tag_id' => $tag->getIdentity(),
)) ) {
$added[] = $this->addTagMap($resource, $tagger, $tag);
}
}
// Check for removed tags
foreach( $existingTagMaps as $tagmap )
{
$key = $tagmap->tag_type . '_' . $tagmap->tag_id;
if( empty($setTagIndex[$key]) )
{
try {
$this->removeTagMap($resource, Engine_Api::_()->getItem($tagmap->tag_type, $tagmap->tag_id)->text);
} catch (Exception $e) {}
}
}
return $added;
}
public function removeTagMaps(Core_Model_Item_Abstract $resource, $tags)
{
foreach ($tags as $key => $tag) {
$this->removeTagMap($resource, $tag);
}
}
public function removeTagMap(Core_Model_Item_Abstract $resource, $tag)
{
$tag = $this->_getTag($tag);
if (!$tag) {
return;
}
$tagMap = $this->getTagMap($resource, $tag);
if (!$tagMap) {
return;
}
$tagMap->delete();
if ($tag->tag_count <= 1) {
return $tag->delete();
}
$tag->tag_count = $tag->tag_count - 1;
$tag->modified_date = date('Y-m-d H:i:s');
$tag->save();
}
// Resources
public function getResourcesByTagSelect($tag, array $params = array())
{
if( is_string($tag) ) {
$tag = $this->_getTag($tag);
}
$table = $this->getMapTable();
$select = $table->select()
->where('tag_type = ?', $tag->getType())
->where('tag_id = ?', $tag->getIdentity())
;
if( !empty($params['resource_types']) ) {
$types = array();
foreach( $params['resource_types'] as $type )
{
if( !Engine_Api::_()->hasItemType($type) ) continue;
$types[] = $type;
}
$select->where('resource_type IN(\''.join("', '", $types).'\')')->order('creation_date DESC');
}
return $select;
}
public function getTopHashtags($limit) {
$hashtagNames = array();
$mapTableName = $this->getMapTable()->info('name');
$select = $this->select()
->setIntegrityCheck(false)
->from($this->info('name'))
->join($mapTableName, $this->info('name') . '.tag_id=' . $mapTableName . '.tag_id', array('count(*) as tagmap_count'))
->order('tag_count desc')
->order('modified_date desc')
->group('tag_id')
->limit($limit);
$hashtagMaps = $this->fetchAll($select);
foreach ($hashtagMaps as $hashtag) {
$hashtagNames[] = '#' . $hashtag->text;
}
return $hashtagNames;
}
// Utility
/**
* Gets an existing string tag or returns the passed item
*
* @param string|Core_Model_Item_Abstract $tag
* @return Core_Model_Item_Abstract
* @throws Core_Model_Exception If argument is not a string or an item
*/
protected function _getTag($tag, $createNew = false)
{
if( is_string($tag) )
{
$tag = $this->getTag($tag, $createNew);
}
if( !($tag instanceof Core_Model_Item_Abstract) || !$tag->getIdentity() )
{
return null;
}
return $tag;
}
/**
* Gets an tag id based on text
*
* @param string|Core_Model_Item_Abstract $tag
* @return tag_id
*/
public function getTagId($tag) {
$tag = str_replace('#','',$tag);
return $this->select()
->from($this->info('name'), 'tag_id')
->where('text = ?', $tag)
->query()
->fetchColumn();
}
public function isExist($params = array()) {
$select = $this->select()
->from($this->info('name'), 'tag_id');
if (isset($params['text']))
$select = $select->where('text = ?', $params['text']);
return $select->query()->fetchColumn();
}
}