tags
[ class tree: tags ] [ index: tags ] [ all elements ]

Source for file LibertyTag.php

Documentation is available at LibertyTag.php

  1. <?php
  2. /**
  3.  * @version $Header$
  4.  * @package tags
  5.  * 
  6.  * @copyright Copyright (c) 2004-2006, bitweaver.org
  7.  *  All Rights Reserved. See below for details and a complete list of authors.
  8.  *  Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See http://www.gnu.org/copyleft/lesser.html for details.
  9.  */
  10.  
  11. /**
  12.  * required setup
  13.  */
  14. require_once( KERNEL_PKG_PATH.'BitBase.php' );
  15.  
  16. /**
  17.  * @package tags
  18.  */
  19. class LibertyTag extends LibertyBase {
  20.     var $mContentId;
  21.  
  22.     function __construct( $pContentId=NULL ) {
  23.         parent::__construct();
  24.         $this->mContentId = $pContentId;
  25.     }
  26.  
  27.  
  28.     /* Delete when package complete! -wjames5
  29.      * methods needed
  30.      *
  31.      * get all tags limited by content_id        <- load
  32.      * get all tags                                <- getList
  33.      * get all content for tag_id                <- getContentList
  34.      * get tags by map use count                <- getList with map refs count
  35.      * get tags    sorted by tagged date            <- getList sorted by map tagged date
  36.      *
  37.      * store new tags from tags array
  38.      * store new tag-content map for content_id
  39.      * expunge tag and all tag-content maps
  40.      * expunge tag-content map for content_id
  41.      *
  42.      */
  43.  
  44.  
  45.     /**
  46.     * Load all the tags for a given ContentId
  47.     * @param pParamHash be sure to pass by reference in case we need to make modifcations to the hash
  48.     ***/
  49.     function load() {
  50.         if( $this->isValid() ) {
  51.             $query = "
  52.                     SELECT tgc.*, tg.*
  53.                     FROM `".BIT_DB_PREFIX."tags_content_map` tgc
  54.                         INNER JOIN `".BIT_DB_PREFIX."tags` tg ON tg.`tag_id` = tgc.`tag_id`
  55.                     WHERE tgc.`content_id`=?";
  56.  
  57.             //$this->mInfo = $this->mDb->query( $query, array( $this->mContentId ) );
  58.             $result = $this->mDb->query( $query, array( $this->mContentId ) );
  59.             if ($result) {
  60.                 $ret = array();
  61.                 while ($res = $result->fetchRow()) {
  62.                     //Add tag urls
  63.                     $res['tag_url'] = LibertyTag::getDisplayUrlWithTag($res['tag']);
  64.                     
  65.                     $ret[] = $res;
  66.                 }
  67.                 $this->mInfo['tags'] = $ret;
  68.             }
  69.         }
  70.         return( count( $this->mInfo ) );
  71.     }
  72.  
  73.     function loadTag ( &$pParamHash ){
  74.         if( !empty( $pParamHash['tag_id'] ) && is_numeric( $pParamHash['tag_id'] )) {
  75.             $selectSql = ''; $joinSql = ''; $whereSql = '';
  76.             $bindVars = array();
  77.  
  78.             $whereSql .= "WHERE tg.`tag_id` = ?";
  79.             $bindVars[] = $pParamHash['tag_id'];
  80.  
  81.             $query = "
  82.                     SELECT tg.*
  83.                     FROM `".BIT_DB_PREFIX."tags` tg
  84.                     $whereSql";
  85.  
  86.             if ( $result = $this->mDb->getRow( $query, $bindVars ) ){
  87.                 //Add tag url
  88.                 $result['tag_url'] = LibertyTag::getDisplayUrlWithTag($result['tag']);
  89.                     
  90.                 $this->mInfo = $result;
  91.             };
  92.         }
  93.         return( count( $this->mInfo ) );
  94.     }
  95.  
  96.  
  97.  
  98.     /**
  99.     * Make sure the data is safe to store
  100.     * @param array pParams reference to hash of values that will be used to store the page, they will be modified where necessary
  101.     * @return bool TRUE on success, FALSE if verify failed. If FALSE, $this->mErrors will have reason why
  102.     * @access private
  103.     ***/
  104.     function verify( &$pParamHash ) {
  105.         global $gBitUser, $gBitSystem;
  106.         $pParamHash['tag_store'] = array();
  107.         $pParamHash['tag_map_store'] = array();
  108.  
  109.         if(!empty( $pParamHash['tag'])){
  110.             $pParamHash['tag_store']['tag'] = $pParamHash['tag'];
  111.         }
  112.         if( !empty( $pParamHash['tag_id']) && is_numeric( $pParamHash['tag_id'])){
  113. //            $pParamHash['tag_map_store']['tag_id'] = $pParamHash['tag_id'];
  114.             $pParamHash['tag_store']['tag_id'] = $pParamHash['tag_id'];
  115.         }
  116.         if( isset( $pParamHash['tagged_on']) ){
  117.             $pParamHash['tag_map_store']['tagged_on'] = $pParamHash['tagged_on'];
  118.         } else {
  119.             $pParamHash['tag_map_store']['tagged_on'] = $gBitSystem->getUTCTime();
  120.         }
  121.         if( @$this->verifyId( $pParamHash['content_id']) ){
  122.             $pParamHash['tag_map_store']['content_id'] = $pParamHash['content_id'];
  123.         }/* else {
  124.             $this->mErrors['content_id'] = "No content id specified.";
  125.         }*/
  126.         if( $gBitUser->mUserId ){
  127.             $pParamHash['tag_map_store']['tagger_id'] = $gBitUser->mUserId;
  128.         } else {
  129.             $this->mErrors['user_id'] = "No user id specified.";
  130.         }
  131.  
  132.         return( count( $this->mErrors )== 0 );
  133.     }
  134.  
  135.  
  136.     /* check tag exists
  137.      */
  138.     function verifyTag ( &$pParamHash ){
  139.         $ret = FALSE;
  140.         $selectSql = ''; $joinSql = ''; $whereSql = '';
  141.         $bindVars = array();
  142.  
  143.         // Bounds checking on tag name length
  144.         if( !empty( $pParamHash['tag'] ) && strlen( $pParamHash['tag'] ) > 64 ) {
  145.             $pParamHash['tag'] = substr( $pParamHash['tag'], 0, 64 );
  146.         }
  147.  
  148.         // if tag_id supplied, use that
  149.         if( !empty( $pParamHash['tag_id'] ) && is_numeric( $pParamHash['tag_id'] )) {
  150.             $whereSql .= "WHERE tg.`tag_id` = ?";
  151.             $bindVars[] = $pParamHash['tag_id'];
  152.         }elseif( isset( $pParamHash['tag'] ) ) {
  153.             $whereSql .= "WHERE tg.`tag` = ?";
  154.             $bindVars[] = $pParamHash['tag'];
  155.         }
  156.  
  157.         $query = " SELECT tg.* FROM `".BIT_DB_PREFIX."tags` tg $whereSql";
  158.         if ( $result = $this->mDb->getRow( $query, $bindVars ) ){
  159.             $pParamHash['tag_id'] = $result['tag_id'];
  160.             $this->mTagId = $result['tag'];
  161.             $ret = TRUE;
  162.         };
  163.  
  164.         return $ret;
  165.     }
  166.  
  167.  
  168.  
  169.     /**
  170.     * @param array pParams hash of values that will be used to store the page
  171.     * @return bool TRUE on success, FALSE if store could not occur. If FALSE, $this->mErrors will have reason why
  172.     * @access public
  173.     ***/
  174.     function store( &$pParamHash ) {
  175.         if( $this->verify( $pParamHash ) ) {
  176.             $this->mDb->StartTrans();
  177.             if (!empty($pParamHash['tag_store'])) {
  178.                 $tagtable = BIT_DB_PREFIX."tags";
  179.                 $maptable = BIT_DB_PREFIX."tags_content_map";
  180.  
  181.                 if( $this->verifyTag($pParamHash['tag_store']) ) {
  182.                     $pParamHash['tag_map_store']['tag_id'] = $pParamHash['tag_store']['tag_id'];
  183.                     $this->mDb->associateInsert( $maptable, $pParamHash['tag_map_store'] );
  184.                 } else {
  185.                     $pParamHash['tag_store']['tag_id'] = $this->mDb->GenID( 'tags_tag_id_seq' );
  186.                     $this->mDb->associateInsert( $tagtable, $pParamHash['tag_store'] );
  187.                     $this->mTagId = $pParamHash['tag_map_store']['tag_id'] = $pParamHash['tag_store']['tag_id'];
  188.                     $this->mDb->associateInsert( $maptable, $pParamHash['tag_map_store'] );
  189.                 }
  190.             }
  191.             $this->mDb->CompleteTrans();
  192.             // since we use store generally in a loop of several tags we should not load here
  193.             //$this->load();
  194.         }
  195.         return( count( $this->mErrors )== 0 );
  196.     }
  197.  
  198.  
  199.  
  200.     function storeOneTag( &$pParamHash ) {
  201.         if( $this->verify( $pParamHash ) ) {
  202.             $this->mDb->StartTrans();
  203.             if (!empty($pParamHash['tag_store'])) {
  204.                 $tagtable = BIT_DB_PREFIX."tags";
  205.  
  206.                 if( isset($pParamHash['tag_store']['tag_id']) ) {
  207.                     //this is kind of ugly but it works right
  208.                     $this->mDb->associateUpdate( $tagtable, array("tag" => $pParamHash['tag_store']['tag']),  array( "tag_id" => $pParamHash['tag_id'] )  );
  209.                 } else {
  210.                     $pParamHash['tag_store']['tag_id'] = $this->mDb->GenID( 'tags_tag_id_seq' );
  211.                     $this->mDb->associateInsert( $tagtable, $pParamHash['tag_store'] );
  212.                 }
  213.             }
  214.             $this->mDb->CompleteTrans();
  215.             $this->loadTag( $pParamHash['tag_store'] );
  216.         }
  217.         return( count( $this->mErrors )== 0 );
  218.     }
  219.  
  220.     function sanitizeTag($pTag) {
  221.         global $gBitSystem;
  222.  
  223.         // We always trim tags
  224.         $pTag = trim($pTag);
  225.  
  226.         if( $gBitSystem->isFeatureActive("tags_strip_spaces") ) {
  227.             $pTag = preg_replace('/\s+/', '', $pTag);
  228.         }
  229.  
  230.         if( $gBitSystem->isFeatureActive("tags_strip_nonword") ) {
  231.             $pTag  = preg_replace('/\W+/', '', $pTag);
  232.         }
  233.  
  234.         if( $gBitSystem->isFeatureActive("tags_lowercase") ) {
  235.             $pTag = strtolower($pTag);
  236.         }
  237.  
  238.         if( $gBitSystem->getConfig('tags_strip_regexp') ) {
  239.             $pTag = preg_replace($gBitSystem->getConfig('tags_strip_regexp', $pTag), $gBitSystem->getConfig('tags_strip_replace'), $pTag);
  240.         }
  241.         return $pTag;
  242.     }
  243.  
  244.     /* make tag data is safe to store
  245.      */
  246.     function verifyTagsMap( &$pParamHash ) {
  247.         global $gBitUser, $gBitSystem;
  248.  
  249.         $pParamHash['tag_map_store'] = array();
  250.  
  251.         //this is to set the time we add content to a tag.
  252.         $timeStamp = $gBitSystem->getUTCTime();
  253.  
  254.         //need to break up this string
  255.         $tagMixed = isset($pParamHash['tags']) ? $pParamHash['tags'] : NULL;
  256.         if( !empty( $tagMixed )){
  257.             if (!is_array( $tagMixed ) && !is_numeric( $tagMixed ) ){
  258.                 $tagIds = explode( ",", $tagMixed );
  259.             }else if ( is_array( $tagMixed ) ) {
  260.                 $tagIds = $tagMixed;
  261.             }else if ( is_numeric( $tagMixed ) ) {
  262.                 $tagIds = array( $tagMixed );
  263.             }
  264.  
  265.             foreach( $tagIds as $value ) {
  266.                 $value = trim($value);
  267.                 /* Ignore empty tags like a trailing , generate */
  268.                 if( !empty($value) ) {
  269.                     $value = LibertyTag::sanitizeTag($value);
  270.                     if ( !empty($value) ) {
  271.                         array_push( $pParamHash['tag_map_store'], array(
  272.                                         'tag' => $value,
  273.                                         'tagged_on' => $timeStamp,
  274.                                         'content_id' => $this->mContentId,
  275.                                         'user_id' => $gBitUser->mUserId,
  276.                                         ));
  277.                     }
  278.                     else {
  279.                         $this->mErrors[$value] = "Invalid tag.";
  280.                     }
  281.                 }
  282.             }
  283.         }
  284.  
  285.         return ( count( $this->mErrors ) == 0 );
  286.     }
  287.  
  288.  
  289.     /**
  290.     * @param array pParams hash includes mix of tags that will be storeded and associated with a ContentId used by service
  291.     * @return bool TRUE on success, FALSE if store could not occur. If FALSE, $this->mErrors will have reason why
  292.     * @access public
  293.     ***/
  294.     function storeTags( &$pParamHash ){
  295.         global $gBitSystem;
  296.         if( $this->verifyTagsMap( $pParamHash ) ) {
  297.             if( $this->isValid() ) {
  298.                 foreach ( $pParamHash['tag_map_store'] as $value) {
  299.                     $result = $this->store( $value );
  300.                 }
  301.                 $this->load();
  302.             }
  303.         }
  304.         return ( count( $this->mErrors ) == 0 );
  305.     }
  306.  
  307.  
  308.     /**
  309.     * check if the mContentId is set and valid
  310.     */
  311.     function isValid() {
  312.         return( @BitBase::verifyId( $this->mContentId ) );
  313.     }
  314.  
  315.     /**
  316.     * This function removes a tag entry
  317.     **/
  318.  
  319.     function expunge( $tag_id ) {
  320.         $ret = FALSE;
  321.         $this->mDb->StartTrans();
  322.         $query = "DELETE FROM `".BIT_DB_PREFIX."tags_content_map` WHERE `tag_id` = ?";
  323.  
  324.         if ( $result = $this->mDb->query( $query, array( $tag_id ) ) ){
  325.             // remove all references to tag in tags_content_map
  326.             $query = "DELETE FROM `".BIT_DB_PREFIX."tags` WHERE `tag_id` = ?";
  327.             if ( $result = $this->mDb->query( $query, array( $tag_id ) ) ) {
  328.                 $ret = TRUE;
  329.             }else{
  330.                 //some rollback feature would be nice here
  331.             }
  332.         }
  333.         $this->mDb->CompleteTrans();
  334.         return $ret;
  335.     }
  336.  
  337.     /**
  338.     * This function removes all references to contentid from tags_content_map
  339.     **/
  340.  
  341.     function expungeContentFromTagMap(){
  342.         $ret = FALSE;
  343.         if( $this->isValid() ) {
  344.             $this->mDb->StartTrans();
  345.             $query = "DELETE FROM `".BIT_DB_PREFIX."tags_content_map` WHERE `content_id` = ?";
  346.             $result = $this->mDb->query( $query, array( $this->mContentId ) );
  347.             $this->mDb->CompleteTrans();
  348.         }
  349.         return $ret;
  350.     }
  351.  
  352.     /**
  353.     * This function removes all references to contentid from tags_content_map
  354.     **/
  355.  
  356.     function expungeMyContentFromTagMap( &$pObject ){
  357.         global $gBitUser;
  358.         $ret = FALSE;
  359.         if( $this->isValid() ) {
  360.             $this->mDb->StartTrans();
  361.             $whereSql = "";
  362.             $bindVars[] = $this->mContentId;
  363.             if( !$pObject->hasAdminPermission() ){
  364.                 $whereSql .= " AND tagger_id = ?";
  365.                 $bindVars[] = $gBitUser->mUserId;
  366.             }
  367.             $query = "DELETE FROM `".BIT_DB_PREFIX."tags_content_map` WHERE `content_id` = ? $whereSql";
  368.             $result = $this->mDb->query( $query, $bindVars );
  369.             $this->mDb->CompleteTrans();
  370.         }
  371.         return $ret;
  372.     }
  373.  
  374.     /**
  375.      * The function removes one or more tag from a piece of content
  376.      */
  377.     function expungeTags($pContentId, $pTagIdArray) {
  378.         if (LibertyContent::verifyId($pContentId)) {
  379.             $this->mDb->StartTrans();
  380.             $query = "DELETE FROM `".BIT_DB_PREFIX."tags_content_map` WHERE `content_id` = ? AND `tag_id` IN (".implode( ',',array_fill( 0,count( $pTagIdArray ),'?' ) )." )";
  381.             $bind[] = $pContentId;
  382.             $bind = array_merge($bind, $pTagIdArray);
  383.             $result = $this->mDb->query( $query, $bind );
  384.             foreach( $pTagIdArray as $tagId ) {
  385.                 if( !$this->mDb->getOne( "SELECT COUNT(*) FROM `".BIT_DB_PREFIX."tags_content_map` WHERE `tag_id`=?", array( $tagId ) ) ) {
  386.                     $this->expunge( $tagId );
  387.                 }
  388.             }
  389.             $this->mDb->CompleteTrans();
  390.         }
  391.     }
  392.     
  393.     function getDisplayUriWithTag( $tag ) {
  394.         return BIT_BASE_URI.$this->getDisplayUrlWithTag( $tag );
  395.     }
  396.  
  397.     function getDisplayUrlWithTag($tag){
  398.         global $gBitSystem;
  399.         if( $gBitSystem->isFeatureActive( 'pretty_urls' ) || $gBitSystem->isFeatureActive( 'pretty_urls_extended' ) ) {
  400.             $rewrite_tag = $gBitSystem->isFeatureActive( 'pretty_urls_extended' ) ? 'view/':'';
  401.             $tag_url = TAGS_PKG_URL.$rewrite_tag.urlencode( $tag );
  402.         } else {
  403.             $tag_url = TAGS_PKG_URL.'index.php?tags='.urlencode( $tag );
  404.         }
  405.         return $tag_url;
  406.     }
  407.  
  408.     /**
  409.     * This function gets a list of tags
  410.     **/
  411.  
  412.     function getList( &$pParamHash ) {
  413.         global $gBitUser, $gBitSystem;
  414.  
  415.         $bindVars = array();
  416.         $joinSql = !empty($pParamHash['join_sql']) ? $pParamHash['join_sql'] : '';
  417.  
  418.         if( !empty( $pParamHash['content_type_guid'] ) ) {
  419.             $bindVars[] = $pParamHash['content_type_guid'];
  420.             $joinSql = "INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON (tgc.`content_id`=lc.`content_id` AND lc.`content_type_guid`=?) ";
  421.         }
  422.  
  423.         $sort_mode_prefix = 'tg';
  424.         //Backward compatability for most popular sort method
  425.         
  426.         if( empty( $pParamHash['sort_mode'] ) ) {
  427.             $pParamHash['sort_mode'] = 'tag_asc';
  428.         } else {
  429.             switch( $pParamHash['sort_mode'] ) {
  430.                 case 'tag_asc':
  431.                 case 'tag_desc':
  432.                 case 'tag_count_desc':
  433.                 case 'tag_count_asc':
  434.                     break;
  435.                 default:
  436.                     $pParamHash['sort_mode'] = 'tag_asc';
  437.                     break;
  438.             }
  439.         }
  440.  
  441.         /**
  442.         * @TODO this all needs to go in in some other getList type method
  443.         * and these are just sketches - need to be different kinds of queries in most cases
  444.         **/
  445.         /*
  446.         // get tags by most hits on content
  447.         if ($pParamHash['sort_mode'] == 'hits_desc') {
  448.             $joinSql .=    "LEFT OUTER JOIN `".BIT_DB_PREFIX."liberty_content_hits` lch ON lc.`content_id`         = lch.`content_id`";
  449.         }
  450.  
  451.         // get tags    sorted by tagged date            <- getList sorted by map tagged date
  452.         if ($pParamHash['sort_mode'] == 'tagged_on_desc') {
  453.             $sort_mode_prefix = 'tgc';
  454.         }
  455.         */
  456.  
  457.         $sort_mode = $this->mDb->convertSortmode( $pParamHash['sort_mode'] );
  458.  
  459.         // get all tags
  460.         $query = "SELECT tg.`tag_id`, tg.`tag`, COUNT(tgc.`content_id`) AS tag_count
  461.                 FROM `".BIT_DB_PREFIX."tags` tg
  462.                      INNER JOIN `".BIT_DB_PREFIX."tags_content_map` tgc ON ( tgc.`tag_id` = tg.`tag_id` ) 
  463.                 $joinSql
  464.                 GROUP BY tg.`tag_id`,tg.`tag`
  465.                 ORDER BY $sort_mode";
  466.         $result = $this->mDb->query( $query,$bindVars, ( !empty($pParamHash['max_records']) ? $pParamHash['max_records'] : NULL ) );
  467.  
  468.         $queryCount = "SELECT COUNT( * ) FROM `".BIT_DB_PREFIX."tags` tg";
  469.         $cant = $this->mDb->getOne( $queryCount );
  470.         $ret = array();
  471.  
  472.         while ($res = $result->fetchRow()) {
  473.             // this was really sucky, its now replaced by the slightly lesssucky subselect above. the subselect should prolly be replaced with a count table
  474. //            $res['tag_count'] = $this->getPopCount($res['tag_id']);
  475.             $res['tag_url'] = LibertyTag::getDisplayUrlWithTag($res['tag']);
  476.             $ret[] = $res;
  477.         }
  478.  
  479.         //get keys for doing sorts
  480.         foreach ($ret as $key => $row) {
  481.            $popcant[$key]  = $row['tag_count'];
  482.            $orderedcant[$key]  = $row['tag_count'];
  483.         }
  484.  
  485.         //this part creates the tag weight in a scale of 1-10
  486.             //get highest count and get lowest count
  487.         if (!empty($orderedcant)) {
  488.             sort($orderedcant);
  489.  
  490.             $lowcant = $orderedcant[0];
  491.             $highcant = $orderedcant[ (count($orderedcant) - 1) ];
  492.             //hack to prevent us from dividing by zero - this whole weighting thing could use a slightly better formula
  493.             if ($highcant == $lowcant){$lowcant -= 1;}
  494.  
  495.             //rescore
  496.             //1.  High-low = x
  497.             $cantoffset = $highcant - $lowcant;
  498.  
  499.             //2.  ratio 10/x
  500.             if ($cantoffset > 9){
  501.                 $tagscale = 9/$cantoffset;
  502.             }else{
  503.                 //@todo make this more sophisticated if the spread is not big enough
  504.                 $tagscale = 9/$cantoffset;
  505.             }
  506.             //3.  (n - low+1)*ratio  (n is # to be scaled)
  507.             foreach ($ret as $key => $row) {
  508.                 $ret[$key]['tagscale']  = round((($row['tag_count'] - $lowcant) * $tagscale) + 1, 0);
  509.             }
  510.         }
  511.  
  512.         
  513.         //trim to max popular count if a limit is asked for
  514.         if ( isset($pParamHash["max_popular"]) && is_numeric($pParamHash["max_popular"])){
  515.             $max_popular = $ret;
  516.             array_multisort($popcant, SORT_DESC, $max_popular);
  517.              $max_popular = array_slice($max_popular, 0, $pParamHash["max_popular"]);
  518.              // preserve the sort requested by matching to the original list
  519.             $sorted_popular = array();
  520.             foreach ( $ret as $retkey => $retrow){
  521.                 foreach ( $max_popular as $key => $row){
  522.                     if ( $row['tag_id'] ==  $retrow['tag_id'] ){
  523.                         $sorted_popular[] = $retrow;
  524.                         break;
  525.                     }
  526.                 }
  527.             }
  528.             $ret = $sorted_popular;
  529.         }
  530.          
  531.         $pParamHash["data"] = $ret;
  532.         $pParamHash["cant"] = $cant;
  533.         
  534.         return $pParamHash;
  535.     }
  536.  
  537.     
  538.     /**
  539.     * This function gets the number of times a tag is used aka Popularity Count
  540.     **/
  541.  
  542.     function getPopCount($tag_id){
  543.         $queryCount = "
  544.             SELECT COUNT( * )
  545.             FROM `".BIT_DB_PREFIX."tags_content_map` tgc
  546.             WHERE tgc.`tag_id` = ?";
  547.         $cant = $this->mDb->getOne($queryCount, array($tag_id) );
  548.         return $cant;
  549.     }
  550.  
  551.     /**
  552.     * This function gets all content by matching to any tag passed in a group of tags, eliminates dupe records
  553.     **/
  554.  
  555.     function assignContentList(&$pParamHash){
  556.         global $gBitSystem, $gBitSmarty;
  557.  
  558.         $gBitSystem->verifyPermission( 'p_tags_view' );
  559.  
  560.         // some content specific offsets and pagination settings
  561.         if( !empty( $pParamHash['sort_mode'] )) {
  562.             $content_sort_mode = $pParamHash['sort_mode'];
  563.             $gBitSmarty->assign( 'sort_mode', $content_sort_mode );
  564.         }
  565.  
  566.         $max_content = ( !empty( $pParamHash['max_records'] )) ? $pParamHash['max_records'] : $gBitSystem->getConfig( 'max_records' );
  567.         $gBitSmarty->assign( 'user_id', @BitBase::verifyId( $pParamHash['user_id'] ) ? $pParamHash['user_id'] : NULL );
  568.  
  569.         // now that we have all the offsets, we can get the content list
  570.         include_once( LIBERTY_PKG_PATH.'get_content_list_inc.php' );
  571.  
  572.         $gBitSmarty->assign( 'contentSelect', $contentSelect );
  573.         $gBitSmarty->assign( 'contentTypes', $contentTypes );
  574.         $contentListHash['parameters']['content_type_guid'] = $contentSelect;
  575.         $gBitSmarty->assign( 'listInfo', $contentListHash );
  576.         $gBitSmarty->assign( 'content_type_guids', ( isset( $pParamHash['content_type_guid'] ) ? $pParamHash['content_type_guid'] : NULL ));
  577.  
  578.         if ( isset($pParamHash['matchtags']) && $pParamHash['matchtags'] == 'all'){
  579.             //need some sort of matching function
  580.         } else {
  581.             //match on any tags
  582.             $distinctdata = $this->array_distinct( $contentList, 'content_id' );
  583.             $distinctdata = array_merge($distinctdata);
  584.         }
  585.         $gBitSmarty->assign_by_ref('contentList', $distinctdata);
  586.         return $contentList;
  587.     }
  588.  
  589.  
  590.     /**
  591.     * Used by getContentList to strip out duplicate records in a list
  592.     * Lifted from http://us3.php.net/manual/en/function.array-unique.php#57006
  593.     *
  594.     * @param $array - nothing to say
  595.     * @param $group_keys - columns which have to be grouped - can be STRING or ARRAY (STRING, STRING[, ...])
  596.     * @param $sum_keys - columns which have to be summed - can be STRING or ARRAY (STRING, STRING[, ...])
  597.     * @param $count_key - must be STRING - count the grouped keys
  598.     */
  599.     function array_distinct ($array, $group_keys, $sum_keys = NULL, $count_key = NULL){
  600.       if (!is_array ($group_keys)) $group_keys = array ($group_keys);
  601.       if (!is_array ($sum_keys)) $sum_keys = array ($sum_keys);
  602.  
  603.       $existing_sub_keys = array ();
  604.       $output = array ();
  605.  
  606.       foreach ($array as $key => $sub_array){
  607.        $puffer = NULL;
  608.        #group keys
  609.        foreach ($group_keys as $group_key){
  610.          $puffer .= $sub_array[$group_key];
  611.        }
  612.        $puffer = serialize ($puffer);
  613.        if (!in_array ($puffer, $existing_sub_keys)){
  614.          $existing_sub_keys[$key] = $puffer;
  615.          $output[$key] = $sub_array;
  616.        }
  617.        else{
  618.          $puffer = array_search ($puffer, $existing_sub_keys);
  619.          #sum keys
  620.          foreach ($sum_keys as $sum_key){
  621.            if (is_string ($sum_key)) $output[$puffer][$sum_key] += $sub_array[$sum_key];
  622.          }
  623.          #count grouped keys
  624.          if (!array_key_exists ($count_key, $output[$puffer])) $output[$puffer][$count_key] = 1;
  625.          if (is_string ($count_key)) $output[$puffer][$count_key]++;
  626.        }
  627.       }
  628.       return $output;
  629.     }
  630.  
  631. }
  632.  
  633. /********* SERVICE FUNCTIONS *********/
  634. function tags_content_display( &$pObject ) {
  635.     global $gBitSystem, $gBitSmarty, $gBitUser;
  636.     
  637.     if( method_exists( $pObject, 'getContentType' ) && $gBitSystem->isFeatureActive( 'tags_tag_'.$pObject->getContentType()) ){
  638.         if ( $gBitSystem->isPackageActive( 'tags' ) ) {
  639.             if( $gBitUser->hasPermission( 'p_tags_view' ) ) {
  640.                 $tag = new LibertyTag( $pObject->mContentId );
  641.                 if( $tag->load() ) {
  642.                     $gBitSmarty->assign( 'tagData', !empty( $tag->mInfo['tags'] ) ? $tag->mInfo['tags'] : NULL );
  643.                 }
  644.             }
  645.         }
  646.     }
  647. }
  648.  
  649. /**
  650.  * filter the search with pigeonholes
  651.  * @param $pParamHash['tags']['filter'] - a tag or an array of tags
  652.  ***/
  653. function tags_content_list_sql( &$pObject, &$pParamHash = NULL ) {
  654.     global $gBitSystem;
  655.     $ret = array();
  656.  
  657.     if (isset($pParamHash['tags']) && !empty($pParamHash['tags'])){
  658.         /* slated for removal - makes no sense since content likely has multiple tags */
  659.         // $ret['select_sql'] = ", tgc.`tag_id`, tgc.`tagger_id`, tgc.`tagged_on`";
  660.         $ret['join_sql'] = " INNER JOIN `".BIT_DB_PREFIX."tags_content_map` tgc ON ( lc.`content_id`=tgc.`content_id` )
  661.                              INNER JOIN `".BIT_DB_PREFIX."tags` tg ON ( tg.`tag_id`=tgc.`tag_id` )";
  662.        
  663.         $tagMixed = $pParamHash['tags']; //need to break up this string
  664.         if( !empty( $tagMixed )){
  665.             if (!is_array( $tagMixed ) && !is_numeric( $tagMixed ) ){
  666.                 $tagIds = explode( ",", $tagMixed );
  667.             }else if ( is_array( $tagMixed ) ) {
  668.                 $tagIds = $tagMixed;
  669.             }else if ( is_numeric( $tagMixed ) ) {
  670.                 $tagIds = array( $tagMixed );
  671.             }
  672.         }
  673.  
  674.         $tags = array();
  675.         // strip off whitespace
  676.         foreach( $tagIds as $value ){
  677.             // ignore empty ones created by trailing ,'s
  678.             $value = trim( $value );
  679.             if( !empty($value) ) {
  680.                 $tags[] = $value;
  681.             }
  682.         }
  683.  
  684.         $ret['where_sql'] = ' AND tg.`tag` IN ('.implode( ',', array_fill(0, count( $tags ), '?' ) ).')';
  685.        
  686.         $ret['bind_vars'] = $tags;
  687.  
  688.         // return the values sent for pagination / url purposes
  689.         $pParamHash['listInfo']['tags'] = $pParamHash['tags'];
  690.         $pParamHash['listInfo']['ihash']['tags'] = $pParamHash['tags'];
  691.     }
  692.  
  693.     return $ret;
  694. }
  695.  
  696. function tags_content_edit( $pObject=NULL ) {
  697.     global $gBitSystem, $gBitSmarty, $gBitUser;
  698.     
  699.     if( method_exists( $pObject, 'getContentType' ) && $gBitSystem->isFeatureActive( 'tags_tag_'.$pObject->getContentType()) ){
  700.         if ( $gBitSystem->isPackageActive( 'tags' )) {
  701.             $tag = new LibertyTag( $pObject->mContentId );
  702.             if( $tag->load() && ($pObject->hasUserPermission( 'p_tags_create' ) || $gBitUser->hasPermission( 'p_tags_moderate' )) ) {
  703.                 $tags = array();
  704.                 foreach ($tag->mInfo['tags'] as $t) {
  705.                     if ($t['tagger_id'] == $gBitUser->mUserId || $gBitUser->hasPermission('p_tags_admin') ) {
  706.                         $tags[] = $t['tag'];
  707.                     }
  708.                 }
  709.  
  710.                 $pObject->setField( 'tags', implode(", ", $tags) );
  711.  
  712.                 $gBitSmarty->assign( 'loadTags', TRUE );
  713.                 $gBitSmarty->assign( 'tagList', $pObject->getField( 'tags' ) );
  714.                 $gBitSmarty->assign( 'tagData', $tag->getField( 'tags' ) );
  715.             }
  716.         }
  717.     }
  718. }
  719.  
  720. /**
  721.  * @param includes a string or array of 'tags' and contentid for association.
  722.  ***/
  723. function tags_content_store( &$pObject, &$pParamHash ) {
  724.     global $gBitUser, $gBitSystem;
  725.     if( $gBitUser->hasPermission( 'p_tags_create' ) ) {
  726.         $errors = NULL;
  727.         // If a content access system is active, let's call it
  728.         if( $gBitSystem->isPackageActive( 'tags' ) && isset( $pParamHash['tags'] ) ) {
  729.             $tag = new LibertyTag( $pObject->mContentId );
  730.             if( $gBitUser->hasPermission('p_tags_create') ) {
  731.                 $tag->expungeMyContentFromTagMap( $pObject );
  732.             }
  733.             if ( !$tag->storeTags( $pParamHash ) ) {
  734.                 $errors=$tag->mErrors;
  735.             }
  736.         }
  737.         return( $errors );
  738.     }
  739. }
  740.  
  741. function tags_content_preview( &$pObject) {
  742.     global $gBitUser, $gBitSystem, $gBitSmarty;
  743.     tags_content_edit( $pObject );
  744.     if( $gBitUser->hasPermission( 'p_tags_create' ) ) {
  745.         if ( $gBitSystem->isPackageActive( 'tags' ) ) {
  746.             if (isset($_REQUEST['tags'])) {
  747.               //$pObject->mInfo['tags'] = $_REQUEST['tags'];
  748.                 $gBitSmarty->assign('tagList', $_REQUEST['tags']);
  749.             }
  750.         }
  751.     }
  752. }
  753.  
  754. function tags_content_expunge( &$pObject ) {
  755.     $tag = new LibertyTag( $pObject->mContentId );
  756.     $tag->expungeContentFromTagMap();
  757. }
  758.  
  759. // make sure all tags from a deleted user are nuked
  760. function tags_user_expunge( &$pObject ) {
  761.     if( is_a( $pObject, 'BitUser' ) && !empty( $pObject->mUserId ) ) {
  762.         $pObject->mDb->StartTrans();
  763.         $pObject->mDb->query( "DELETE FROM `".BIT_DB_PREFIX."tags_content_map` WHERE tagger_id=?", array( $pObject->mUserId ) );
  764.         $pObject->mDb->CompleteTrans();
  765.     }
  766. }
  767.  
  768. ?>

Documentation generated on Wed, 29 Jul 2015 13:57:00 +0000 by phpDocumentor 1.5.0-lsces