You are here

nexcloud.class.php in filedepot 7

Same filename and directory in other branches
  1. 6 nexcloud.class.php

nexcloud.class.php Tag Cloud class for the filedepot module

File

nexcloud.class.php
View source
<?php

/**
 * @file
 * nexcloud.class.php
 * Tag Cloud class for the filedepot module
 */
class nexcloud {
  public $_tagwords;
  public $_tagitems;
  public $_tagmetrics;
  public $_filter;
  public $_newtags;
  public $_activetags;

  // Active search tags - don't show in tag cloud
  public $_type;
  public $_fontmultiplier = 160;

  // Used as a multiplier in displaycloud() function - Increase to see a wider range of font sizes
  public $_maxclouditems = 200;
  public $_allusers = 1;

  // Role Id that includes all users (including anonymous)
  function __construct() {
    global $user;
    if (db_query("SELECT COUNT(id) FROM {nextag_words}")
      ->fetchField() < 30) {
      $this->_fontmultiplier = 100;
    }
    if ($user->uid > 0) {
      $this->_uid = $user->uid;
    }
    else {
      $this->_uid = 0;
    }
  }

  /* Function added so I could isolate out the filtering logic.
   * May not need now for Drupal - but keeping it for now
   * Returns filtered tagword in lowercase
   */
  private function filtertag($tag, $dbmode = FALSE) {
    if ($dbmode) {
      return drupal_strtolower(strip_tags($tag));
    }
    else {
      return drupal_strtolower(strip_tags($tag));
    }
  }

  /* This function can be over-loaded or extended in a module specific class to return the item perms
   * We ony are concerned about view access
   * We only show tags with their relative metric (popularity) depending on users access - so tags in restricted folders do not appear.
   * If item is restricted to a group - then we need the assigned group id returned
   *
   * @param string $itemid    - id that identifies the plugin item, example fid for a file
   * @param boolean $sitewide - if set TRUE, then the call to perms will check site wide vs just for the user
   * @return array            - Return needs to be an associative array with the 3 permission related values
   *                            $A['group_id','perm_members','perm_anon');
   */
  function get_itemperms($fid, $sitewide = FALSE) {
    global $user;
    $perms = array(
      'groups' => array(),
      'roles' => array(),
    );
    $cid = db_query("SELECT cid FROM {filedepot_files} WHERE fid=:fid", array(
      ':fid' => $fid,
    ))
      ->fetchField();
    if ($cid > 0) {
      if (module_exists('og') and module_exists('og_access')) {
        $groups = filedepot_og_get_user_groups();
        if (!empty($groups)) {
          $groupids = implode(',', array_values($groups));
          if (!empty($groupids) or $sitewide === TRUE) {
            $sql = "SELECT permid from {filedepot_access} WHERE catid=:cid AND permtype='group' AND view = 1 AND permid > 0 ";
            $sql .= "AND permid in ({$groupids}) ";
            $query = db_query($sql, array(
              ':cid' => $cid,
            ));
            if ($query) {
              while ($A = $query
                ->fetchAssoc()) {
                $perms['groups'][] = $A['permid'];
              }
            }
          }
        }
      }

      // Determine all the roles the active user has and test for view permission.
      $roleids = implode(',', array_keys($user->roles));
      if (!empty($roleids) or $sitewide === TRUE) {
        $sql = "SELECT permid from {filedepot_access} WHERE catid=:cid AND permtype='role' AND view = 1 AND permid > 0 ";
        if (!$sitewide) {
          $sql .= "AND permid in ({$roleids}) ";
        }
        $query = db_query($sql, array(
          ':cid' => $cid,
        ));
        if ($query) {
          while ($A = $query
            ->fetchAssoc()) {
            $perms['roles'][] = $A['permid'];
          }
        }
      }
    }
    return $perms;
  }

  // Return an array of tagids for the passed in comma separated list of tagwords
  private function get_tagids($tagwords) {
    if (!empty($tagwords)) {
      $tagwords = explode(',', $tagwords);

      // Build a comma separated list of tagwords that we can use in a SQL statements below
      $allTagWords = array();
      foreach ($tagwords as $word) {
        $tag = "'" . addslashes($word) . "'";
        $allTagWords[] = $tag;
      }
      $tagwords = implode(',', $allTagWords);

      // build a comma separated list of words
      if (!empty($tagwords)) {
        $query = db_query("SELECT id FROM {nextag_words} where tagword in ({$tagwords})");
        $tagids = array();
        while ($A = $query
          ->fetchAssoc()) {
          $tagids[] = $A['id'];
        }
        return $tagids;
      }
      else {
        return FALSE;
      }
    }
    else {
      return FALSE;
    }
  }

  /*
   * New item being tagged or new tag being added to an item.
   * The usage count for this tagword will be incremented by 1 - regardless of the number of roles or groups that have access to item.
   * @param string $itemid  - Item id, used to get the access permissions
   * @param array $tagids   - array of tag id's
   */
  private function add_accessmetrics($itemid, $tagids) {

    // Test that a valid array of tag id's is passed in
    if (is_array($tagids) and count($tagids) > 0) {

      // Test that a valid item record exist
      if (db_query("SELECT count(itemid) FROM {nextag_items} WHERE type=:type AND itemid=:iid", array(
        ':type' => $this->_type,
        ':iid' => $itemid,
      ))
        ->fetchField() > 0) {

        // Get item permissions to determine what rights to use for tag metrics record
        $perms = $this
          ->get_itemperms($itemid, true);

        // Add any new tags
        foreach ($tagids as $id) {
          if (!empty($id)) {

            // For each role or group with view access to this item - create or update the access metric record count.
            $haveGroupsToUpdate = count($perms['groups']) > 0;
            $haveRolesToUpdate = count($perms['roles']) > 0;
            if ($haveGroupsToUpdate or $haveRolesToUpdate) {
              db_query("UPDATE {nextag_words} SET metric=metric+1 WHERE id=:id", array(
                ':id' => $id,
              ));

              // use an array to handle the logic of whether to process groups, roles, or both
              // use the key to track the field to update and the value to track the values
              $permAccessMetric = array();
              if ($haveGroupsToUpdate) {
                $permAccessMetric['groupid'] = $perms['groups'];
              }
              if ($haveRolesToUpdate) {
                $permAccessMetric['roleid'] = $perms['roles'];
              }
              foreach ($permAccessMetric as $permKey => $permValue) {
                foreach ($permValue as $permid) {
                  if ($permid > 0) {
                    $sql = "SELECT count(tagid) FROM {nextag_metrics} WHERE tagid = :tid AND type = :type AND " . $permKey . " = :permkey";
                    if (db_query($sql, array(
                      ':tid' => $id,
                      ':type' => $this->_type,
                      ':permkey' => $permid,
                    ))
                      ->fetchField() > 0) {
                      $sql = "UPDATE {nextag_metrics} SET metric=metric+1, last_updated=:updated " . "WHERE tagid=:tid AND type=:type AND " . $permKey . "=:permkey";
                      db_query($sql, array(
                        'updated' => time(),
                        ':tid' => $id,
                        ':type' => $this->_type,
                        ':permkey' => $permid,
                      ));
                    }
                    else {
                      $sql = "INSERT INTO {nextag_metrics} (tagid,type," . $permKey . ",metric,last_updated) " . "VALUES (:id, :type, :permkey, :alias, :time)";
                      db_query($sql, array(
                        ':id' => $id,
                        ':type' => $this->_type,
                        ':permkey' => $permid,
                        ':alias' => 1,
                        ':time' => time(),
                      ));
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }

  /*
   * Method is called when removing a tag for an item.
   * Need to decrement it's metric and update related access records
   * @param string $itemid  - Item id, used to get the access permissions
   * @param array $tagids   - array of tag id's
   */
  private function remove_accessmetrics($itemid, $tagids) {

    // Test that a valid array of tag id's is passed in
    if (is_array($tagids) and count($tagids) > 0) {

      // Test that a valid item record exist
      if (db_query("SELECT count(itemid) FROM {nextag_items} WHERE type=:type AND itemid=:item", array(
        ':type' => $this->_type,
        ':item' => $itemid,
      ))
        ->fetchField() > 0) {

        // Get item permissions to determine what rights to use for tag metrics record
        $perms = $this
          ->get_itemperms($itemid, true);

        // Remove if required unused tag related records for this item
        foreach ($tagids as $id) {
          if (!empty($id)) {

            // For each role or group with view access to this item - decrement and if need delete the access metric record count.
            $haveGroupsToRemove = count($perms['groups']) > 0;
            $haveRolesToRemove = count($perms['roles']) > 0;
            if ($haveGroupsToRemove or $haveRolesToRemove) {
              db_query("UPDATE {nextag_words} SET metric=metric-1 WHERE id=:id", array(
                ':id' => $id,
              ));
              db_query("DELETE FROM {nextag_words} WHERE id=:id and metric=1", array(
                ':id' => $id,
              ));

              // use an array to handle the logic of whether to process groups, roles, or both
              // use the key to track the field to update and the value to track the values
              $permAccessMetric = array();
              if ($haveGroupsToRemove) {
                $permAccessMetric['groupid'] = $perms['groups'];
              }
              if ($haveRolesToRemove) {
                $permAccessMetric['roleid'] = $perms['roles'];
              }
              foreach ($permAccessMetric as $permKey => $permValue) {
                foreach ($permValue as $permid) {

                  // Delete the tag metric access record if metric = 1 else decrement the metric count
                  db_query("DELETE FROM {nextag_metrics} WHERE tagid=:tid AND type=:type AND " . $permKey . "=:permkey AND metric=1", array(
                    ':tid' => $id,
                    ':type' => $this->_type,
                    ':permkey' => $permid,
                  ));
                  $sql = "UPDATE {nextag_metrics} SET metric=metric-1, last_updated=:time " . "WHERE tagid=:tid AND type=:type AND " . $permKey . "=:permkey";
                  db_query($sql, array(
                    ':time' => time(),
                    ':tid' => $id,
                    ':type' => $this->_type,
                    ':permkey' => $permid,
                  ));
                }
              }
            }
          }
        }
      }
    }
  }

  /*
   * Used when item permissions are changed and we need to possibly remove or add some tag_metrics records
   * Each file identified by tagid of type 'filedepot' will have a record per permission assigned
   * So if the folder has 10 files with tags, 2 role permissions and a group permission - there will be 3 record per file
   * @param string $itemid  - file id, used to get the access permissions
   */
  function update_accessmetrics($itemid, $tagids = '') {
    if (empty($tagids)) {

      // Retrieve the tags field and convert into an array
      $tags = db_query("SELECT tags FROM {nextag_items} WHERE type=:type AND itemid=:item", array(
        ':type' => $this->_type,
        ':item' => $itemid,
      ))
        ->fetchField();
      if (!empty($tags)) {
        $tagids = explode(',', $tags);
      }
      else {
        $tagids = array();
      }
    }

    // Test that we now have a valid array of tag id's
    if (is_array($tagids) and count($tagids) > 0) {

      // Test that a valid item record exist
      if (db_query("SELECT count(itemid) FROM {nextag_items} WHERE type=:type AND itemid=:item", array(
        ':type' => $this->_type,
        ':item' => $itemid,
      ))
        ->fetchField() > 0) {

        // Get item permissions to determine what rights to use for tag metrics record
        $perms = $this
          ->get_itemperms($itemid, true);

        // For each role or group with view access to this item - create or update the access metric record count.
        $haveGroupsToUpdate = count($perms['groups']) > 0;
        $haveRolesToUpdate = count($perms['roles']) > 0;

        // For each tag word - we need to update (add new or remove any un-used tag metric associated with this permission and tagword
        $metricRecords = array();

        // Will contain the processed metric records
        foreach ($tagids as $id) {
          if (!empty($id)) {
            if ($haveGroupsToUpdate or $haveRolesToUpdate) {

              // An array to handle the logic of whether to process groups, roles, or both
              // Use the key to track the field to update and the value to track the values
              $permAccessMetric = array();
              if ($haveGroupsToUpdate) {
                $permAccessMetric['groupid'] = $perms['groups'];
              }
              if ($haveRolesToUpdate) {
                $permAccessMetric['roleid'] = $perms['roles'];
              }
              foreach ($permAccessMetric as $permKey => $permValue) {
                foreach ($permValue as $permid) {
                  if ($permid > 0) {
                    $result = db_query("SELECT id FROM {nextag_metrics} WHERE tagid = :tid AND type = :type AND :permkey = :permid", array(
                      ':tid' => $id,
                      ':type' => $this->_type,
                      ':permkey' => $permKey,
                      'permid' => $permid,
                    ));
                    $numrecs = 0;
                    if ($result) {
                      foreach ($result as $rec) {
                        $numrecs++;
                        if (!in_array($rec->id, $metricRecords)) {
                          $metricRecords[] = $rec->id;
                        }
                      }
                    }
                    if ($numrecs == 0) {
                      $metric = db_query("SELECT metric FROM {nextag_words} WHERE id=:id", array(
                        ':id' => $id,
                      ))
                        ->fetchField();
                      $query = db_insert('nextag_metrics');
                      $query
                        ->fields(array(
                        'tagid',
                        'type',
                        $permKey,
                        'metric',
                        'last_updated',
                      ));
                      $query
                        ->values(array(
                        'tagid' => $id,
                        'type' => $this->_type,
                        $permKey => $permid,
                        'metric' => $metric,
                        'last_updated' => time(),
                      ));
                      $newrecid = $query
                        ->execute();
                      $metricRecords[] = $newrecid;
                    }
                  }
                }
              }
            }
          }

          /* Now we should delete any metric records that are not in the processed $metricRecords array
           * They would be records for access permissions that were removed
           */
          if (count($metricRecords) > 0) {
            $recids = implode(',', $metricRecords);
            $query = db_delete('nextag_metrics')
              ->condition('tagid', $id, '=')
              ->condition('id', $metricRecords, 'NOT IN')
              ->execute();
          }
          else {
            db_query("DELETE FROM {nextag_metrics} WHERE tagid = :tid ", array(
              ':tid' => $id,
            ));
          }

          // Delete any tagword records that are no longer used
          $result = db_query("SELECT id FROM {nextag_words} WHERE metric = 0");
          if ($result) {

            // Let's do one more test and make sure no items are using this tagword
            while ($A = $result
              ->fetchAssoc()) {

              /* REGEX - search for id that is the first id or has a leading comma
               *  must then have a trailing , or be the end of the field
               */
              $sql = "SELECT itemid FROM {nextag_items} WHERE type='{$this->_type}' AND ";
              $sql .= "(tags LIKE '{$A['id']},%' OR tags LIKE '%,{$A['id']}' OR tags LIKE '%,{$A['id']},%' OR tags = '{$A['id']}') ";

              //$sql .= "tags REGEXP '(^|,){$A['id']}(,|$)' ";
              if (db_query($sql)
                ->fetchField() == 0) {
                db_query("DELETE FROM {nextag_words} WHERE id = :id", array(
                  ':id' => $A['id'],
                ));
              }
            }
          }
        }
      }
    }
  }

  /* Update tag metrics for an existing item.
   * Should work for all modules - adding tags or updating tags
   * @param string $itemid       - Example file ID (fid) relates to itemid in the tagitems table
   * @param string $tagwords     - Single tagword or comma separated list of tagwords.
   *                               Tagwords can be unfilterd if passed in.
   *                               The set_newtags function will filter and prepare tags for DB insertion
   * @param boolean $sitewide    - if set TRUE, then the call to perms will check site wide vs just for the user
   */
  public function update_tags($itemid, $tagwords = '', $sitewide = FALSE) {
    if (!empty($tagwords)) {
      $this
        ->set_newtags($tagwords);
    }
    $perms = $this
      ->get_itemperms($itemid, $sitewide);
    if (count($perms['groups']) > 0 or count($perms['roles']) > 0) {
      if (!empty($this->_newtags)) {

        // If item record does not yet exist - create it.
        if (db_query("SELECT count(itemid) FROM {nextag_items} WHERE type=:type AND itemid=:item", array(
          ':type' => $this->_type,
          ':item' => $itemid,
        ))
          ->fetchField() == 0) {
          db_query("INSERT INTO {nextag_items} (itemid,type) VALUES (:item,:type)", array(
            ':item' => $itemid,
            ':type' => $this->_type,
          ));
        }

        // Need to build list of tagid's for these tag words and if tagword does not yet exist then add it
        $tagwords = preg_split("/[\\s,]+/", $this->_newtags, NULL, PREG_SPLIT_NO_EMPTY);
        $tags = array();
        foreach ($tagwords as $word) {
          $word = trim(strip_tags($word));
          $id = db_query("SELECT id FROM {nextag_words} WHERE tagword=:word", array(
            ':word' => $word,
          ))
            ->fetchField();
          if (empty($id)) {
            db_query("INSERT INTO {nextag_words} (tagword,metric,last_updated) VALUES (:word,0,:time)", array(
              ':word' => $word,
              ':time' => time(),
            ));
            $id = db_query("SELECT id FROM {nextag_words} WHERE tagword=:word", array(
              ':word' => $word,
            ))
              ->fetchField();
          }
          $tags[] = $id;
        }

        // Retrieve the current assigned tags to compare against new tags
        $currentTags = db_query("SELECT tags FROM {nextag_items} WHERE type=:type AND itemid=:item", array(
          ':type' => $this->_type,
          ':item' => $itemid,
        ))
          ->fetchField();
        $currentTags = explode(',', $currentTags);
        $unusedTags = array_diff($currentTags, $tags);
        $newTags = array_diff($tags, $currentTags);
        $this
          ->remove_accessmetrics($itemid, $unusedTags);
        $this
          ->add_accessmetrics($itemid, $newTags);
        $tagids = implode(',', $tags);
        if ($currentTags != $tags) {
          db_query("UPDATE {nextag_items} SET tags = :tid WHERE itemid=:item", array(
            ':tid' => $tagids,
            ':item' => $itemid,
          ));
        }
        return TRUE;
      }
      else {
        $this
          ->clear_tags($itemid);
        return TRUE;
      }
    }
    else {
      watchdog('filedepot', 'Attempted to add tags for file (@item) but no role or group based folder permission defined', array(
        '@item' => $itemid,
      ));
      return FALSE;
    }
  }

  /* Clear the tags used for this item and update tag access metrics
   * Typically called when item is deleted
   * @param string $itemid    - Example Story ID (sid) relates to itemid in the tagitems table
   */
  public function clear_tags($itemid) {

    // Retrieve the current assigned tags - these are the tags to update
    $currentTags = db_query("SELECT tags FROM {nextag_items} WHERE type=:type AND itemid=:item", array(
      ':type' => $this->_type,
      ':item' => $itemid,
    ))
      ->fetchField();
    $currentTags = explode(',', $currentTags);
    $this
      ->remove_accessmetrics($itemid, $currentTags);
    db_query("DELETE FROM {nextag_items} WHERE itemid = :item", array(
      ':item' => $itemid,
    ));
  }
  public function set_newtags($newtags) {
    $newtags = $this
      ->filtertag($newtags);
    if (!empty($newtags)) {
      $this->_newtags = str_replace(array(
        "\n",
        ';',
      ), ',', $newtags);
    }
  }
  public function get_newtags($dbmode = TRUE) {
    if ($dbmode) {
      return $this
        ->filtertag($this->_newtags, TRUE);
    }
    else {
      return $this->_newtags;
    }
  }
  public function get_itemtags($itemid) {
    $tags = '';
    $tagids = db_query("SELECT tags FROM {nextag_items} WHERE type=:type AND itemid=:item", array(
      ':type' => $this->_type,
      ':item' => $itemid,
    ))
      ->fetchField();
    if (!empty($tagids)) {
      $query = db_query("SELECT tagword FROM {nextag_words} WHERE id IN ({$tagids})");
      while ($A = $query
        ->fetchAssoc()) {
        $tagwords[] = $A['tagword'];
      }
      if (isset($tagwords) and count($tagwords) > 0) {
        $tags = implode(',', $tagwords);
      }
    }
    return $tags;
  }

  /* Search the defined tagwords across all modules for any tag words matching query
   * Typically would be used in a AJAX driven lookup to populate a dropdown list dynamically as user enters tags
   *
   * @param string $query  - tag words to search on. Can be a list but only the last word will be used for search
   * @return array         - Returns an array of matching tag words
   */
  public function get_matchingtags($query) {
    $matches = array();
    $query = drupal_strtolower(strip_tags($query));

    // User may be looking for more then 1 tag - pull of the last word in the query to search against
    $tags = explode(',', $query);
    $lookup = addslashes(array_pop($tags));
    $sql = "SELECT tagword FROM {nextag_words} WHERE tagword LIKE '{$lookup}%' ORDER BY metric DESC";

    // REGEXP '^$lookup' ORDER BY metric DESC";
    $q = db_query($sql);
    while ($A = $q
      ->fetchAssoc()) {
      $matches[] = $A['tagword'];
    }
    return $matches;
  }

  /* Return an array of item id's matching tag query */
  public function search($query) {
    $query = addslashes($query);
    $itemids = array();

    // Get a list of Tag ID's for the tag words in the query
    $sql = "SELECT id,tagword FROM {nextag_words} ";
    $asearchtags = explode(',', stripslashes($query));
    if (count($asearchtags) > 1) {
      $sql .= "WHERE ";
      $i = 1;
      foreach ($asearchtags as $tag) {
        $tag = addslashes($tag);
        if ($i > 1) {
          $sql .= "OR tagword = '{$tag}' ";
        }
        else {
          $sql .= "tagword = '{$tag}' ";
        }
        $i++;
      }
    }
    else {
      $sql .= "WHERE tagword = '{$query}' ";
    }
    $query = db_query($sql);
    $tagids = array();
    $sql = "SELECT itemid FROM {nextag_items} WHERE type='{$this->_type}' AND ";
    $i = 1;
    while ($A = $query
      ->fetchAssoc()) {
      $tagids[] = $A['id'];

      // REGEX - search for id that is the first id or has a leading comma must then have a trailing , or be the end of the field
      if ($i > 1) {
        $sql .= "AND (tags LIKE '{$A['id']},%' OR tags LIKE '%,{$A['id']}' OR tags LIKE '%,{$A['id']},%' OR tags = '{$A['id']}')";

        //"AND tags REGEXP '(^|,){$A['id']}(,|$)' ";
      }
      else {
        $sql .= "(tags LIKE '{$A['id']},%' OR tags LIKE '%,{$A['id']}' OR tags LIKE '%,{$A['id']},%' OR tags = '{$A['id']}')";

        //"tags REGEXP '(^|,){$A['id']}(,|$)' ";
      }
      $i++;
    }
    if (count($tagids) > 0) {
      $this->_activetags = implode(',', $tagids);
      $query = db_query($sql);
      while ($A = $query
        ->fetchAssoc()) {
        $itemids[] = $A['itemid'];
      }
      if (count($itemids) > 0) {
        return $itemids;
      }
      else {
        return FALSE;
      }
    }
    else {
      return FALSE;
    }
  }

}
class filedepotTagCloud extends nexcloud {
  function __construct() {
    parent::__construct();
    $this->_type = 'filedepot';
  }

  /* For each file in this folder with tagwords - update the metrics per access permission */
  function update_accessmetrics($cid, $tagids = '') {
    $query = db_select('nextag_items', 'a');
    $query
      ->join('filedepot_files', 'b', 'b.fid = a.itemid');
    $query
      ->fields('a', array(
      'itemid',
    ));
    $query
      ->condition('b.cid', $cid, '=');
    $results = $query
      ->execute();
    foreach ($results as $record) {
      parent::update_accessmetrics($record->itemid, $tagids = '');
    }
  }

}

Classes

Namesort descending Description
filedepotTagCloud
nexcloud @file nexcloud.class.php Tag Cloud class for the filedepot module