[ Index ]
 

Code source de vtiger CRM 5.0.2

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/include/freetag/ -> freetag.class.php (source)

   1  <?php
   2  /**
   3   *  Gordon Luk's Freetag - Generalized Open Source Tagging and Folksonomy.
   4   *  Copyright (C) 2004-2005 Gordon D. Luk <gluk AT getluky DOT net>
   5   *
   6   *  Released under both BSD license and Lesser GPL library license.  Whenever
   7   *  there is any discrepancy between the two licenses, the BSD license will
   8   *  take precedence. See License.txt.  
   9   *
  10   */
  11  /**
  12   *  Freetag API Implementation
  13   *
  14   *  Freetag is a generic PHP class that can hook-in to existing database
  15   *  schemas and allows tagging of content within a social website. It's fun,
  16   *  fast, and easy!  Try it today and see what all the folksonomy fuss is
  17   *  about.
  18   * 
  19   *  Contributions and/or donations are welcome.
  20   *
  21   *  Author: Gordon Luk
  22   *  http://www.getluky.net
  23   *  
  24   *  Version: 0.240
  25   *  Last Updated: 12/26/2005 
  26   * 
  27   */ 
  28  
  29  class freetag {
  30  
  31      /**#@+
  32       *  @access private
  33       *  @param string
  34       */ 
  35      /**#@-*/
  36  
  37      /**
  38       * @access private
  39       * @param ADOConnection The ADODB Database connection instance.
  40       */
  41      //var $_db;
  42      /**
  43       * @access private
  44       * @param bool Prints out limited debugging information if true, not fully implemented yet.
  45       */
  46      var $_debug = FALSE;
  47      /**
  48       * @access private
  49       * @param string The prefix of freetag database vtiger_tables.
  50       */
  51      var $_table_prefix = 'vtiger_';
  52      /**
  53       * @access private
  54       * @param string The regex-style set of characters that are valid for normalized tags.
  55       */
  56      var $_normalized_valid_chars = 'a-zA-Z0-9';
  57      /**
  58       * @access private
  59       * @param string Whether to normalize tags at all.
  60       * value 0 saves the tag in case insensitive mode
  61       * value 1 save the tag in lower case
  62       */
  63      var $_normalize_tags = 0;
  64      /**
  65       * @access private
  66       * @param string Whether to prevent multiple vtiger_users from tagging the same object. By default, set to block (ala Upcoming.org)
  67       */
  68      var $_block_multiuser_tag_on_object =0;
  69      /**
  70       * @access private
  71       * @param bool Whether to use persistent ADODB connections. False by default.
  72       */
  73      //var $_PCONNECT = FALSE;
  74      /**
  75       * @access private
  76       * @param int The maximum length of a tag.
  77       */ 
  78      var $_MAX_TAG_LENGTH = 30;
  79      /**
  80       * @access private
  81       * @param string The file path to the installation of ADOdb used.
  82       */ 
  83      //var $_ADODB_DIR = 'adodb/';
  84  
  85      /**
  86       * freetag
  87       *
  88       * Constructor for the freetag class. 
  89       *
  90       * @param array An associative array of options to pass to the instance of Freetag.
  91       * The following options are valid:
  92       * - debug: Set to TRUE for debugging information. [default:FALSE]
  93       * - db: If you've already got an ADODB ADOConnection, you can pass it directly and Freetag will use that. [default:NULL]
  94       * - db_user: Database username
  95       * - db_pass: Database password
  96       * - db_host: Database hostname [default: localhost]
  97       * - db_name: Database name
  98       * - vtiger_table_prefix: If you wish to create multiple Freetag databases on the same database, you can put a prefix in front of the vtiger_table names and pass separate prefixes to the constructor. [default: '']
  99       * - normalize_tags: Whether to normalize (lowercase and filter for valid characters) on tags at all. [default: 1]
 100       * - normalized_valid_chars: Pass a regex-style set of valid characters that you want your tags normalized against. [default: 'a-zA-Z0-9' for alphanumeric]
 101       * - block_multiuser_tag_on_object: Set to 0 in order to allow individual vtiger_users to all tag the same object with the same tag. Default is 1 to only allow one occurence of a tag per object. [default: 1]
 102       * - MAX_TAG_LENGTH: maximum length of normalized tags in chars. [default: 30]
 103       * - ADODB_DIR: directory in which adodb is installed. Change if you don't want to use the bundled version. [default: adodb/]
 104       * - PCONNECT: Whether to use ADODB persistent connections. [default: FALSE]
 105       * 
 106       */ 
 107  	function freetag($options = NULL) {
 108  /*
 109          $available_options = array('debug', 'db', 'db_user', 'db_pass', 'db_host', 'db_name', 'table_prefix', 'normalize_tags', 'normalized_valid_chars', 'block_multiuser_tag_on_object', 'MAX_TAG_LENGTH', 'ADODB_DIR', 'PCONNECT');
 110          if (is_array($options)) {
 111              foreach ($options as $key => $value) {
 112                  $this->debug_text("Option: $key");
 113  
 114                  if (in_array($key, $available_options) ) {
 115                      $this->debug_text("Valid Config options: $key");
 116                      $property = '_'.$key;
 117                      $this->$property = $value;
 118                      $this->debug_text("Setting $property to $value");
 119                  } else {
 120                      $this->debug_text("ERROR: Config option: $key is not a valid option");
 121                  }
 122              }
 123          }*/
 124  /*
 125          require_once($this->_ADODB_DIR . "/adodb.inc.php");
 126          if (is_object($this->_db)) {
 127              $this->db = &$this->_db;
 128              $this->debug_text("DB Instance already exists, using this one.");
 129          } else {
 130              $this->db = ADONewConnection("mysql");
 131              $this->debug_text("Connecting to db with:" . $this->_db_host . " " . $this->_db_user . " " . $this->_db_pass . " " . $this->_db_name);
 132              if ($this->_PCONNECT) {
 133                  $this->db->PConnect($this->_db_host, $this->_db_user, $this->_db_pass, $this->_db_name);
 134              } else {
 135                  $this->db->Connect($this->_db_host, $this->_db_user, $this->_db_pass, $this->_db_name);
 136              }
 137          }
 138          $this->db->debug = $this->_debug;
 139          // Freetag uses ASSOC for ease of maintenance and compatibility with people who choose to modify the schema.
 140          // Feel free to convert to NUM if performance is the highest concern.
 141          $this->db->SetFetchMode(ADODB_FETCH_ASSOC);*/
 142      }
 143  
 144      /**
 145       * get_objects_with_tag
 146       *
 147       * Use this function to build a page of results that have been tagged with the same tag.
 148       * Pass along a tagger_id to collect only a certain user's tagged objects, and pass along
 149       * none in order to get back all user-tagged objects. Most of the get_*_tag* functions
 150       * operate on the normalized form of tags, because most interfaces for navigating tags
 151       * should use normal form.
 152       *
 153       * @param string - Pass the normalized tag form along to the function.
 154       * @param int (Optional) - The numerical offset to begin display at. Defaults to 0.
 155       * @param int (Optional) - The number of results per page to show. Defaults to 100.
 156       * @param int (Optional) - The unique ID of the 'user' who tagged the object.
 157       *
 158       * @return An array of Object ID numbers that reference your original objects.
 159       */ 
 160  	function get_objects_with_tag($tag, $offset = 0, $limit = 100, $tagger_id = NULL) {
 161          if(!isset($tag)) {
 162              return false;
 163          }        
 164          global $adb;
 165          $tag = $adb->quote($tag, get_magic_quotes_gpc());
 166  
 167          if(isset($tagger_id) && ($tagger_id > 0)) {
 168              $tagger_sql = "AND tagger_id = $tagger_id";
 169          } else {
 170              $tagger_sql = "";
 171          }
 172          $prefix = $this->_table_prefix;
 173  
 174          $sql = "SELECT DISTINCT object_id
 175              FROM $prefix}freetagged_objects INNER JOIN $prefix}freetags ON (tag_id = id)
 176              WHERE tag = $tag
 177              $tagger_sql
 178              ORDER BY object_id ASC
 179              LIMIT $offset, $limit
 180              ";
 181          echo $sql;
 182          $rs = $adb->query($sql) or die("Error: $sql");
 183          $retarr = array();
 184          while(!$rs->EOF) {
 185              $retarr[] = $rs->fields['object_id'];
 186              $rs->MoveNext();
 187          }
 188          return $retarr;
 189      }
 190  
 191      /**
 192       * get_objects_with_tag_all
 193       *
 194       * Use this function to build a page of results that have been tagged with the same tag.
 195       * This function acts the same as get_objects_with_tag, except that it returns an unlimited
 196       * number of results. Therefore, it's more useful for internal displays, not for API's.
 197       * Pass along a tagger_id to collect only a certain user's tagged objects, and pass along
 198       * none in order to get back all user-tagged objects. Most of the get_*_tag* functions
 199       * operate on the normalized form of tags, because most interfaces for navigating tags
 200       * should use normal form.
 201       *
 202       * @param string - Pass the normalized tag form along to the function.
 203       * @param int (Optional) - The unique ID of the 'user' who tagged the object.
 204       *
 205       * @return An array of Object ID numbers that reference your original objects.
 206       */ 
 207  	function get_objects_with_tag_all($tag, $tagger_id = NULL) {
 208          if(!isset($tag)) {
 209              return false;
 210          }        
 211          global $adb;
 212          $tag = $adb->quote($tag, get_magic_quotes_gpc());
 213  
 214          if(isset($tagger_id) && ($tagger_id > 0)) {
 215              $tagger_sql = "AND tagger_id = $tagger_id";
 216          } else {
 217              $tagger_sql = "";
 218          }
 219          $prefix = $this->_table_prefix;
 220  
 221          $sql = "SELECT DISTINCT object_id
 222              FROM $prefix}freetagged_objects INNER JOIN $prefix}freetags ON (tag_id = id)
 223              WHERE tag = $tag
 224              $tagger_sql
 225              ORDER BY object_id ASC
 226              ";
 227              //echo $sql;
 228          $rs = $adb->query($sql) or die("Error: $sql");
 229          $retarr = array();
 230          while(!$rs->EOF) {
 231              $retarr[] = $rs->fields['object_id'];
 232              $rs->MoveNext();
 233          }
 234          return $retarr;
 235      }
 236  
 237      /**
 238       * get_objects_with_tag_combo
 239       *
 240       * Returns an array of object ID's that have all the tags passed in the
 241       * tagArray parameter. Use this to provide tag combo services to your vtiger_users.
 242       *
 243       * @param array - Pass an array of normalized form tags along to the function.
 244       * @param int (Optional) - The numerical offset to begin display at. Defaults to 0.
 245       * @param int (Optional) - The number of results per page to show. Defaults to 100.
 246       * @param int (Optional) - Restrict the result to objects tagged by a particular user.
 247       *
 248       * @return An array of Object ID numbers that reference your original objects.
 249       */
 250  	 function get_objects_with_tag_combo($tagArray, $offset = 0, $limit = 100, $tagger_id = NULL) {
 251          if (!isset($tagArray) || !is_array($tagArray)) {
 252              return false;
 253          }
 254          global $adb;
 255          //$db = &$this->db;
 256          $retarr = array();
 257          if (count($tagArray) == 0) {
 258              return $retarr;
 259          }
 260          if(isset($tagger_id) && ($tagger_id > 0)) {
 261              $tagger_sql = "AND tagger_id = $tagger_id";
 262          } else {
 263              $tagger_sql = "";
 264          }
 265  
 266          foreach ($tagArray as $key => $value) {
 267              $tagArray[$key] = $adb->qstr($value, get_magic_quotes_gpc());
 268          }
 269  
 270          $tagArray = array_unique($tagArray);
 271          $tag_sql = join(",", $tagArray);
 272          $numTags = count($tagArray);
 273          $prefix = $this->_table_prefix;
 274  
 275          // We must adjust for duplicate normalized tags appearing multiple times in the join by 
 276          // counting only the distinct tags. It should also work for an individual user.
 277  
 278          $sql = "SELECT $prefix}freetagged_objects.object_id, tag, COUNT(DISTINCT tag) AS uniques
 279              FROM $prefix}freetagged_objects 
 280              INNER JOIN $prefix}freetags ON ($prefix}freetagged_objects.tag_id = $prefix}freetags.id)
 281              WHERE $prefix}freetags.tag IN ($tag_sql)
 282              $tagger_sql
 283              GROUP BY $prefix}freetagged_objects.object_id
 284              HAVING uniques = $numTags
 285              LIMIT $offset, $limit
 286              ";
 287          $this->debug_text("Tag combo: " . join("+", $tagArray) . " SQL: $sql");
 288          $rs = $adb->query($sql) or die("Error: $sql");
 289          while(!$rs->EOF) {
 290              $retarr[] = $rs->fields['object_id'];
 291              $rs->MoveNext();
 292          }
 293          return $retarr;
 294      }
 295  
 296      /**
 297       * get_objects_with_tag_id
 298       *
 299       * Use this function to build a page of results that have been tagged with the same tag.
 300       * This function acts the same as get_objects_with_tag, except that it accepts a numerical
 301       * tag_id instead of a text tag.
 302       * Pass along a tagger_id to collect only a certain user's tagged objects, and pass along
 303       * none in order to get back all user-tagged objects.
 304       *
 305       * @param int - Pass the ID number of the tag.
 306       * @param int (Optional) - The numerical offset to begin display at. Defaults to 0.
 307       * @param int (Optional) - The number of results per page to show. Defaults to 100.
 308       * @param int (Optional) - The unique ID of the 'user' who tagged the object.
 309       *
 310       * @return An array of Object ID numbers that reference your original objects.
 311       */ 
 312  	function get_objects_with_tag_id($tag_id, $offset = 0, $limit = 100, $tagger_id = NULL) {
 313          if(!isset($tag_id)) {
 314              return false;
 315          }        
 316          global $adb;
 317  
 318          if(isset($tagger_id) && ($tagger_id > 0)) {
 319              $tagger_sql = "AND tagger_id = $tagger_id";
 320          } else {
 321              $tagger_sql = "";
 322          }
 323          $prefix = $this->_table_prefix;
 324  
 325          $sql = "SELECT DISTINCT object_id
 326              FROM $prefix}freetagged_objects INNER JOIN $prefix}freetags ON (tag_id = id)
 327              WHERE id = $tag_id
 328              $tagger_sql
 329              ORDER BY object_id ASC
 330              LIMIT $offset, $limit
 331              ";
 332          $rs = $adb->query($sql) or die("Error: $sql");
 333          $retarr = array();
 334          while(!$rs->EOF) {
 335              $retarr[] = $rs->fields['object_id'];
 336              $rs->MoveNext();
 337          }
 338          return $retarr;
 339      }
 340  
 341  
 342      /**
 343       * get_tags_on_object
 344       *
 345       * You can use this function to show the tags on an object. Since it supports both user-specific
 346       * and general modes with the $tagger_id parameter, you can use it twice on a page to make it work
 347       * similar to upcoming.org and flickr, where the page displays your own tags differently than
 348       * other vtiger_users' tags.
 349       *
 350       * @param int The unique ID of the object in question.
 351       * @param int The offset of tags to return.
 352       * @param int The size of the tagset to return. Use a zero size to get all tags.
 353       * @param int The unique ID of the person who tagged the object, if user-level tags only are preferred.
 354       *
 355       * @return array Returns a PHP array with object elements ordered by object ID. Each element is an associative
 356       * array with the following elements:
 357       *   - 'tag' => Normalized-form tag
 358       *     - 'raw_tag' => The raw-form tag
 359       *     - 'tagger_id' => The unique ID of the person who tagged the object with this tag.
 360       */ 
 361  	function get_tags_on_object($object_id, $offset = 0, $limit = 10, $tagger_id = NULL) {
 362          if(!isset($object_id)) {
 363              return false;
 364          }        
 365          if(isset($tagger_id) && ($tagger_id > 0)) {
 366              $tagger_sql = "AND tagger_id = $tagger_id";
 367          } else {
 368              $tagger_sql = "";
 369          }
 370          global $adb;
 371  
 372          if($limit <= 0) {
 373              $limit_sql = "";
 374          } else {
 375              $limit_sql = "LIMIT $offset, $limit";
 376          }
 377          $prefix = $this->_table_prefix;
 378  
 379          $sql = "SELECT DISTINCT tag, raw_tag, tagger_id, id
 380              FROM $prefix}freetagged_objects INNER JOIN $prefix}freetags ON (tag_id = id)
 381              WHERE object_id = $object_id
 382              $tagger_sql
 383              ORDER BY id ASC
 384              $limit_sql
 385              ";
 386              //echo ' <br><br>get_tags_on_object sql is ' .$sql;
 387          $rs = $adb->query($sql) or die("Error: $sql");
 388          $retarr = array();
 389          while(!$rs->EOF) {
 390              $retarr[] = array(
 391                      'tag' => $rs->fields['tag'],
 392                      'raw_tag' => $rs->fields['raw_tag'],
 393                      'tagger_id' => $rs->fields['tagger_id']
 394                      );
 395              $rs->MoveNext();
 396          }
 397          return $retarr;
 398      }
 399  
 400      /**
 401       * safe_tag
 402       *
 403       * Pass individual tag phrases along with object and person ID's in order to 
 404       * set a tag on an object. If the tag in its raw form does not yet exist,
 405       * this function will create it.
 406       * Fails transparently on duplicates, and checks for dupes based on the 
 407       * block_multiuser_tag_on_object constructor param.
 408       *
 409       * @param int The unique ID of the person who tagged the object with this tag.
 410       * @param int The unique ID of the object in question.
 411       * @param string A raw string from a web form containing tags.
 412       *
 413       * @return boolean Returns true if successful, false otherwise. Does not operate as a transaction.
 414       */ 
 415  
 416  	function safe_tag($tagger_id, $object_id, $tag, $module) {
 417          if(!isset($tagger_id)||!isset($object_id)||!isset($tag)) {
 418              die("safe_tag argument missing");
 419              return false;
 420          }
 421          global $adb;
 422  
 423          $normalized_tag = $adb->quote($this->normalize_tag($tag));
 424  
 425          $tag = $adb->quote($tag);
 426          $prefix = $this->_table_prefix;
 427  
 428          // First, check for duplicate of the normalized form of the tag on this object.
 429          // Dynamically switch between allowing duplication between vtiger_users on the constructor param 'block_multiuser_tag_on_object'.
 430          // If it's set not to block multiuser tags, then modify the existence
 431          // check to look for a tag by this particular user. Otherwise, the following
 432          // query will reveal whether that tag exists on that object for ANY user.
 433          if ($this->_block_multiuser_tag_on_object == 0) {
 434              $tagger_sql = " AND tagger_id = $tagger_id";
 435          }
 436          $sql = "SELECT COUNT(*) as count 
 437              FROM $prefix}freetagged_objects INNER JOIN $prefix}freetags ON (tag_id = id)
 438              WHERE 1=1 
 439              $tagger_sql
 440              AND object_id = $object_id
 441              AND tag = $normalized_tag
 442              ";
 443          $rs = $adb->query($sql) or die("Syntax Error: $sql");
 444          if($rs->fields['count'] > 0) {
 445              return true;
 446          }
 447          // Then see if a raw tag in this form exists.
 448          $sql = "SELECT id 
 449              FROM $prefix}freetags 
 450              WHERE raw_tag = $tag
 451              ";
 452          $rs = $adb->query($sql) or die("Syntax Error: $sql");
 453          if(!$rs->EOF) {
 454              $tag_id = $rs->fields['id'];
 455          } else {
 456              // Add new tag! 
 457              $tag_id = $adb->getUniqueId('vtiger_freetags');
 458              $sql = "INSERT INTO $prefix}freetags (id,tag, raw_tag) VALUES ($tag_id,$normalized_tag, $tag)";
 459              $rs = $adb->query($sql) or die("Syntax Error: $sql");
 460              
 461          }
 462          if(!($tag_id > 0)) {
 463              return false;
 464          }
 465          $sql = "INSERT INTO $prefix}freetagged_objects
 466              (tag_id, tagger_id, object_id, tagged_on, module)
 467              VALUES ($tag_id, $tagger_id, $object_id, NOW(), '$module')
 468              ";
 469          $rs = $adb->query($sql) or die("Syntax error: $sql");
 470  
 471          return true;
 472      }
 473  
 474      /**
 475       * normalize_tag
 476       *
 477       * This is a utility function used to take a raw tag and convert it to normalized form.
 478       * Normalized form is essentially lowercased alphanumeric characters only, 
 479       * with no spaces or special characters.
 480       *
 481       * Customize the normalized valid chars with your own set of special characters
 482       * in regex format within the option 'normalized_valid_chars'. It acts as a filter
 483       * to let a customized set of characters through.
 484       * 
 485       * After the filter is applied, the function also lowercases the characters using strtolower 
 486       * in the current locale.
 487       *
 488       * The default for normalized_valid_chars is a-zA-Z0-9, or english alphanumeric.
 489       *
 490       * @param string An individual tag in raw form that should be normalized.
 491       *
 492       * @return string Returns the tag in normalized form.
 493       */ 
 494  	function normalize_tag($tag) {
 495          if ($this->_normalize_tags) {
 496              $normalized_valid_chars = $this->_normalized_valid_chars;
 497              $normalized_tag = preg_replace("/[^$normalized_valid_chars]/", "", $tag);
 498              return strtolower($normalized_tag);
 499          } else {
 500              return $tag;
 501          }
 502  
 503      }
 504  
 505      /**
 506       * delete_object_tag
 507       *
 508       * Removes a tag from an object. This does not delete the tag itself from
 509       * the database. Since most applications will only allow a user to delete
 510       * their own tags, it supports raw-form tags as its tag parameter, because
 511       * that's what is usually shown to a user for their own tags.
 512       *
 513       * @param int The unique ID of the person who tagged the object with this tag.
 514       * @param int The ID of the object in question.
 515       * @param string The raw string form of the tag to delete. See above for vtiger_notes.
 516       *
 517       * @return string Returns the tag in normalized form.
 518       */ 
 519  	function delete_object_tag($tagger_id, $object_id, $tag) {
 520          if(!isset($tagger_id)||!isset($object_id)||!isset($tag)) {
 521              die("delete_object_tag argument missing");
 522              return false;
 523          }
 524          global $adb;
 525          $tag_id = $this->get_raw_tag_id($tag);
 526          $prefix = $this->_table_prefix;
 527          if($tag_id > 0) {
 528  
 529              $sql = "DELETE FROM $prefix}freetagged_objects
 530                  WHERE tagger_id = $tagger_id
 531                  AND object_id = $object_id
 532                  AND tag_id = $tag_id
 533                  LIMIT 1
 534                  ";    
 535                  $rs = $adb->query($sql) or die("Syntax Error: $sql");    
 536              return true;
 537          } else {
 538              return false;    
 539          }
 540      }
 541  
 542      /**
 543       * delete_all_object_tags
 544       *
 545       * Removes all tag from an object. This does not
 546       * delete the tag itself from the database. This is most useful for
 547       * cleanup, where an item is deleted and all its tags should be wiped out
 548       * as well.
 549       *
 550       * @param int The ID of the object in question.
 551       *
 552       * @return boolean Returns true if successful, false otherwise. It will return true if the tagged object does not exist.
 553       */ 
 554  	function delete_all_object_tags($object_id) {
 555          global $adb;
 556          $prefix = $this->_table_prefix;
 557          if($object_id > 0) {
 558              $sql = "DELETE FROM $prefix}freetagged_objects
 559                  WHERE 
 560                  object_id = $object_id
 561                  ";    
 562                  $rs = $adb->query($sql) or die("Syntax Error: $sql");    
 563              return true;
 564          } else {
 565              return false;    
 566          }
 567      }
 568  
 569  
 570      /**
 571       * delete_all_object_tags_for_user
 572       *
 573       * Removes all tag from an object for a particular user. This does not
 574       * delete the tag itself from the database. This is most useful for
 575       * implementations similar to del.icio.us, where a user is allowed to retag
 576       * an object from a text box. That way, it becomes a two step operation of
 577       * deleting all the tags, then retagging with whatever's left in the input.
 578       *
 579       * @param int The unique ID of the person who tagged the object with this tag.
 580       * @param int The ID of the object in question.
 581       *
 582       * @return boolean Returns true if successful, false otherwise. It will return true if the tagged object does not exist.
 583       */ 
 584  
 585  	function delete_all_object_tags_for_user($tagger_id, $object_id) {
 586          if(!isset($tagger_id)||!isset($object_id)) {
 587              die("delete_all_object_tags_for_user argument missing");
 588              return false;
 589          }
 590          global $adb;
 591          $prefix = $this->_table_prefix;
 592          if($object_id > 0) {
 593  
 594              $sql = "DELETE FROM $prefix}freetagged_objects
 595                  WHERE tagger_id = $tagger_id
 596                  AND object_id = $object_id
 597                  ";    
 598                  $rs = $adb->query($sql) or die("Syntax Error: $sql");    
 599              return true;
 600          } else {
 601              return false;    
 602          }
 603      }
 604  
 605      /**
 606       * get_tag_id
 607       *
 608       * Retrieves the unique ID number of a tag based upon its normal form. Actually,
 609       * using this function is dangerous, because multiple tags can exist with the same
 610       * normal form, so be careful, because this will only return one, assuming that
 611       * if you're going by normal form, then the individual tags are interchangeable.
 612       *
 613       * @param string The normal form of the tag to fetch.
 614       *
 615       * @return string Returns the tag in normalized form.
 616       */ 
 617  	function get_tag_id($tag) {
 618          if(!isset($tag)) {
 619              die("get_tag_id argument missing");
 620              return false;
 621          }
 622          global $adb;
 623          
 624          $prefix = $this->_table_prefix;
 625  
 626          $tag = $adb->quote($tag, get_magic_quotes_gpc());
 627  
 628          $sql = "SELECT id FROM $prefix}freetags
 629              WHERE 
 630              tag = $tag
 631              LIMIT 1
 632              ";    
 633              $rs = $adb->query($sql) or die("Syntax Error: $sql");    
 634          return $rs->fields['id'];
 635  
 636      }
 637  
 638      /**
 639       * get_raw_tag_id
 640       *
 641       * Retrieves the unique ID number of a tag based upon its raw form. If a single
 642       * unique record is needed, then use this function instead of get_tag_id, 
 643       * because raw_tags are unique.
 644       *
 645       * @param string The raw string form of the tag to fetch.
 646       *
 647       * @return string Returns the tag in normalized form.
 648       */ 
 649  
 650  	function get_raw_tag_id($tag) {
 651          if(!isset($tag)) {
 652              die("get_tag_id argument missing");
 653              return false;
 654          }
 655          global $adb;
 656          $prefix = $this->_table_prefix;
 657  
 658          $tag = $adb->quote($tag, get_magic_quotes_gpc());
 659  
 660          $sql = "SELECT id FROM $prefix}freetags
 661              WHERE 
 662              raw_tag = $tag
 663              LIMIT 1
 664              ";    
 665              $rs = $adb->query($sql) or die("Syntax Error: $sql");    
 666          return $rs->fields['id'];
 667  
 668      }
 669  
 670      /**
 671       * tag_object
 672       *
 673       * This function allows you to pass in a string directly from a form, which is then
 674       * parsed for quoted phrases and special characters, normalized and converted into tags.
 675       * The tag phrases are then individually sent through the safe_tag() method for processing
 676       * and the object referenced is set with that tag. 
 677       *
 678       * This method has been refactored to automatically look for existing tags and run
 679       * adds/updates/deletes as appropriate.
 680       *
 681       * @param int The unique ID of the person who tagged the object with this tag.
 682       * @param int The ID of the object in question.
 683       * @param string The raw string form of the tag to delete. See above for vtiger_notes.
 684       * @param int Whether to skip the update portion for objects that haven't been tagged. (Default: 1)
 685       *
 686       * @return string Returns the tag in normalized form.
 687       */
 688  	function tag_object($tagger_id, $object_id, $tag_string, $module, $skip_updates = 1) {
 689          if($tag_string == '') {
 690              // If an empty string was passed, just return true, don't die.
 691              // die("Empty tag string passed");
 692              return true;
 693          }
 694          $tagArray = $this->_parse_tags($tag_string);
 695  
 696          $oldTags = $this->get_tags_on_object($object_id, 0, 0, $tagger_id);
 697  
 698          $preserveTags = array();
 699  
 700          if (($skip_updates == 0) && (count($oldTags) > 0)) {
 701              foreach ($oldTags as $tagItem) {
 702                  if (!in_array($tagItem['raw_tag'], $tagArray)) {
 703                      // We need to delete old tags that don't appear in the new parsed string.
 704                      $this->delete_object_tag($tagger_id, $object_id, $tagItem['raw_tag']);
 705                  } else {
 706                      // We need to preserve old tags that appear (to save timestamps)
 707                      $preserveTags[] = $tagItem['raw_tag'];
 708                  }
 709              }
 710          }
 711          $newTags = array_diff($tagArray, $preserveTags);
 712  
 713          $this->_tag_object_array($tagger_id, $object_id, $newTags, $module);
 714  
 715          return true;
 716      }
 717  
 718      /**
 719       * _tag_object_array
 720       *
 721       * Private method to add tags to an object from an array.
 722       *
 723       * @param int Unique ID of tagger
 724       * @param int Unique ID of object
 725       * @param array Array of tags to add.
 726       *
 727       * @return boolean True if successful, false otherwise.
 728       */
 729  	function _tag_object_array($tagger_id, $object_id, $tagArray, $module) {
 730          foreach($tagArray as $tag) {
 731              $tag = trim($tag);
 732              if(($tag != '') && (strlen($tag) <= $this->_MAX_TAG_LENGTH)) {
 733                  if(get_magic_quotes_gpc()) {
 734                      $tag = addslashes($tag);
 735                  }
 736                  $this->safe_tag($tagger_id, $object_id, $tag, $module);
 737              }
 738          }
 739          return true;
 740      }
 741  
 742      /**
 743       * _parse_tags
 744       *
 745       * Private method to parse tags out of a string and into an array.
 746       *
 747       * @param string String to parse.
 748       *
 749       * @return array Returns an array of the raw "tags" parsed according to the freetag settings.
 750       */
 751  
 752  	function _parse_tags($tag_string) {
 753          $newwords = array();
 754          if ($tag_string == '') {
 755              // If the tag string is empty, return the empty set.
 756              return $newwords;
 757          }
 758          # Perform tag parsing
 759          if(get_magic_quotes_gpc()) {
 760              $query = stripslashes(trim($tag_string));
 761          } else {
 762              $query = trim($tag_string);
 763          }
 764          $words = preg_split('/(")/', $query,-1,PREG_SPLIT_NO_EMPTY|PREG_SPLIT_DELIM_CAPTURE);
 765          $delim = 0;
 766          foreach ($words as $key => $word)
 767          {
 768              if ($word == '"') {
 769                  $delim++;
 770                  continue;
 771              }
 772              if (($delim % 2 == 1) && $words[$key - 1] == '"') {
 773                  $newwords[] = $word;
 774              } else {
 775                  $newwords = array_merge($newwords, preg_split('/\s+/', $word, -1, PREG_SPLIT_NO_EMPTY));
 776              }
 777          }
 778          return $newwords;
 779      }
 780  
 781      /**
 782       * update_tags
 783       *
 784       * This method supports a user updating their set of all tags on an object
 785       * in a streamlined manner. Very useful for interfaces where all tags on an
 786       * object from a user may be edited through a single text box.
 787       */
 788  
 789      /**
 790       * get_most_popular_tags
 791       *
 792       * This function returns the most popular tags in the freetag system, with
 793       * offset and limit support for pagination. It also supports restricting to 
 794       * an individual user. Call it with no parameters for a list of 25 most popular
 795       * tags.
 796       * 
 797       * @param int The unique ID of the person to restrict results to.
 798       * @param int The offset of the tag to start at.
 799       * @param int The number of tags to return in the result set.
 800       *
 801       * @return array Returns a PHP array with tags ordered by popularity descending. 
 802       * Each element is an associative array with the following elements:
 803       *   - 'tag' => Normalized-form tag
 804       *     - 'count' => The number of objects tagged with this tag.
 805       */
 806  
 807  	function get_most_popular_tags($tagger_id = NULL, $offset = 0, $limit = 25) {
 808          global $adb;
 809          if(isset($tagger_id) && ($tagger_id > 0)) {
 810              $tagger_sql = "AND tagger_id = $tagger_id";
 811          } else {
 812              $tagger_sql = "";
 813          }
 814          $prefix = $this->_table_prefix;
 815  
 816          $sql = "SELECT tag, COUNT(*) as count
 817              FROM $prefix}freetags INNER JOIN $prefix}freetagged_objects ON (id = tag_id)
 818              WHERE 1
 819              $tagger_sql
 820              GROUP BY tag
 821              ORDER BY count DESC, tag ASC
 822              LIMIT $offset, $limit
 823              ";
 824  
 825          $rs = $adb->query($sql) or die("Syntax Error: $sql");
 826          $retarr = array();
 827          while(!$rs->EOF) {
 828              $retarr[] = array(
 829                      'tag' => $rs->fields['tag'],
 830                      'count' => $rs->fields['count']
 831                      );
 832              $rs->MoveNext();
 833          }
 834  
 835          return $retarr;
 836  
 837      }
 838  
 839      /**
 840       * count_tags
 841       *
 842       * Returns the total number of tag->object links in the system.
 843       * It might be useful for pagination at times, but i'm not sure if I actually use
 844       * this anywhere. Restrict to a person's tagging by using the $tagger_id parameter.
 845       *
 846       * @param int The unique ID of the person to restrict results to.
 847       *
 848       * @return int Returns the count 
 849       */
 850  	function count_tags($tagger_id = NULL) {
 851          global $adb;
 852          if(isset($tagger_id) && ($tagger_id > 0)) {
 853              $tagger_sql = "AND tagger_id = $tagger_id";
 854          } else {
 855              $tagger_sql = "";
 856          }
 857          $prefix = $this->_table_prefix;
 858  
 859          $sql = "SELECT COUNT(*) as count
 860              FROM $prefix}freetags INNER JOIN $prefix}freetagged_objects ON (id = tag_id)
 861              WHERE 1
 862              $tagger_sql
 863              ";
 864  
 865          $rs = $adb->query($sql) or die("Syntax Error: $sql");
 866          if(!$rs->EOF) {
 867              return $rs->fields['count'];
 868          }
 869          return false;
 870  
 871      }
 872  
 873      /**
 874       * get_tag_cloud_html
 875       *
 876       * This is a pretty straightforward, flexible method that automatically
 877       * generates some html that can be dropped in as a tag cloud.
 878       * It uses explicit font sizes inside of the style attribute of SPAN 
 879       * elements to accomplish the differently sized objects.
 880       *
 881       * It will also link every tag to $tag_page_url, appended with the 
 882       * normalized form of the tag. You should adapt this value to your own
 883       * tag detail page's URL.
 884       *
 885       * @param int The maximum number of tags to return. (default: 100)
 886       * @param int The minimum font size in the cloud. (default: 10)
 887       * @param int The maximum number of tags to return. (default: 20)
 888       * @param string The "units" for the font size (i.e. 'px', 'pt', 'em') (default: px)
 889       * @param string The class to use for all spans in the cloud. (default: cloud_tag)
 890       * @param string The tag page URL (default: /tag/)
 891       *
 892       * @return string Returns an HTML snippet that can be used directly as a tag cloud.
 893       */
 894  
 895  	function get_tag_cloud_html($module="",$tagger_id = NULL,$obj_id= NULL,$num_tags = 100, $min_font_size = 10, $max_font_size = 20, $font_units = 'px', $span_class = '', $tag_page_url = '/tag/') {
 896          global $theme;
 897          $theme_path="themes/".$theme."/";
 898          $image_path=$theme_path."images/";    
 899          $tag_list = $this->get_tag_cloud_tags($num_tags, $tagger_id,$module,$obj_id);
 900          if(!$tag_list[0]) return;
 901          // Get the maximum qty of tagged objects in the set
 902          $max_qty = max(array_values($tag_list[0]));
 903          // Get the min qty of tagged objects in the set
 904          $min_qty = min(array_values($tag_list[0]));
 905  
 906          // For ever additional tagged object from min to max, we add
 907          // $step to the font size.
 908          $spread = $max_qty - $min_qty;
 909          if (0 == $spread) { // Divide by zero
 910              $spread = 1;
 911          }
 912          $step = ($max_font_size - $min_font_size)/($spread);
 913  
 914          // Since the original tag_list is alphabetically ordered,
 915          // we can now create the tag cloud by just putting a span
 916          // on each element, multiplying the diff between min and qty
 917          // by $step.
 918          $cloud_html = '';
 919          $cloud_spans = array();
 920          if($module =='')
 921              $module = 'All';    
 922          if($module != 'All')    
 923          {    
 924              foreach($tag_list[0] as $tag => $qty) {
 925                  $size = $min_font_size + ($qty - $min_qty) * 3;
 926                  $cloud_span[] = '<span id="tag_'.$tag_list[1][$tag].'" class="' . $span_class . '" onMouseOver=$("tagspan_'.$tag_list[1][$tag].'").style.display="inline"; onMouseOut=$("tagspan_'.$tag_list[1][$tag].'").style.display="none";><a class="tagit" href="index.php?module=Home&action=UnifiedSearch&search_module='.$module.'&query_string='. $tag . '" style="font-size: '. $size . $font_units . '">' . htmlspecialchars(stripslashes($tag)) . '</a><span class="'. $span_class .'" id="tagspan_'.$tag_list[1][$tag].'" style="display:none;cursor:pointer;" onClick="DeleteTag('.$tag_list[1][$tag].');"><img src="'.$image_path.'del_tag.gif"></span></span>';
 927  
 928              }
 929          }else
 930          {
 931              foreach($tag_list[0] as $tag => $qty) {
 932                  $size = $min_font_size + ($qty - $min_qty) * 3;
 933                  $cloud_span[] = '<span class="' . $span_class . '"><a class="tagit" href="index.php?module=Home&action=UnifiedSearch&search_module='.$module.'&query_string='. $tag . '" style="font-size: '. $size . $font_units . '">' . htmlspecialchars(stripslashes($tag)) . '</a></span>';
 934  
 935              }
 936  
 937          }    
 938          $cloud_html = join("\n ", $cloud_span);
 939  
 940          return $cloud_html;
 941  
 942      }
 943  
 944      /*
 945       * get_tag_cloud_tags
 946       *
 947       * This is a function built explicitly to set up a page with most popular tags
 948       * that contains an alphabetically sorted list of tags, which can then be sized
 949       * or colored by popularity.
 950       *
 951       * Also known more popularly as Tag Clouds!
 952       *
 953       * Here's the example case: http://upcoming.org/tag/
 954       *
 955       * @param int The maximum number of tags to return.
 956       *
 957       * @return array Returns an array where the keys are normalized tags, and the
 958       * values are numeric quantity of objects tagged with that tag.
 959       */
 960  
 961  	function get_tag_cloud_tags($max = 100, $tagger_id = NULL,$module = "",$obj_id = NULL) {
 962          global $adb;
 963          if(isset($tagger_id) && ($tagger_id > 0)) {
 964              $tagger_sql = " AND tagger_id = $tagger_id";
 965          } else {
 966              $tagger_sql = "";
 967          }
 968  
 969          if($module != "") {
 970              $tagger_sql .= " AND module = '$module'";
 971          } else {
 972              $tagger_sql .= "";
 973          }
 974  
 975          if(isset($obj_id) && $obj_id > 0) {
 976                          $tagger_sql .= " AND object_id = $obj_id";
 977                  } else {
 978                          $tagger_sql .= "";
 979                  }
 980  
 981          $prefix = $this->_table_prefix;
 982          $sql = "SELECT tag,tag_id,COUNT(object_id) AS quantity
 983              FROM $prefix}freetags INNER JOIN $prefix}freetagged_objects
 984              ON ($prefix}freetags.id = tag_id)
 985              WHERE 1=1
 986              $tagger_sql
 987              GROUP BY tag,tag_id
 988              ORDER BY quantity DESC";
 989          //echo $sql;
 990          $rs = $adb->limitQuery($sql, 0, $max) or die("Syntax Error: $sql");
 991          $retarr = array();
 992          while(!$rs->EOF) {
 993              $retarr[$rs->fields['tag']] = $rs->fields['quantity'];
 994              $retarr1[$rs->fields['tag']] = $rs->fields['tag_id'];
 995              $rs->MoveNext();
 996          }
 997          if($retarr) ksort($retarr);
 998          if($retarr1) ksort($retarr1);
 999          $return_value[]=$retarr;
1000          $return_value[]=$retarr1;
1001          return $return_value;
1002  
1003      }
1004  
1005      /**
1006       * similar_tags
1007       *
1008       * Finds tags that are "similar" or related to the given tag.
1009       * It does this by looking at the other tags on objects tagged with the tag specified.
1010       * Confusing? Think of it like e-commerce's "Other vtiger_users who bought this also bought," 
1011       * as that's exactly how this works.
1012       *
1013       * Returns an empty array if no tag is passed, or if no related tags are found.
1014       * Hint: You can detect related tags returned with count($retarr > 0)
1015       *
1016       * It's important to note that the quantity passed back along with each tag
1017       * is a measure of the *strength of the relation* between the original tag
1018       * and the related tag. It measures the number of objects tagged with both
1019       * the original tag and its related tag.
1020       *
1021       * Thanks to Myles Grant for contributing this function!
1022       *
1023       * @param string The raw normalized form of the tag to fetch.
1024       * @param int The maximum number of tags to return.
1025       *
1026       * @return array Returns an array where the keys are normalized tags, and the
1027       * values are numeric quantity of objects tagged with BOTH tags, sorted by
1028       * number of occurences of that tag (high to low).
1029       */ 
1030  
1031  	function similar_tags($tag, $max = 100) {
1032          $retarr = array();
1033          if(!isset($tag)) {
1034              return $retarr;
1035          }
1036          global $adb;
1037          $tag = $adb->quote($tag, get_magic_quotes_gpc());
1038  
1039          // This query was written using a double join for PHP. If you're trying to eke
1040          // additional performance and are running MySQL 4.X, you might want to try a subselect
1041          // and compare perf numbers.
1042          $prefix = $this->_table_prefix;
1043  
1044          $sql = "SELECT t1.tag, COUNT( o1.object_id ) AS quantity
1045              FROM $prefix}freetagged_objects o1
1046              INNER JOIN $prefix}freetags t1 ON ( t1.id = o1.tag_id )
1047              INNER JOIN $prefix}freetagged_objects o2 ON ( o1.object_id = o2.object_id )
1048              INNER JOIN $prefix}freetags t2 ON ( t2.id = o2.tag_id )
1049              WHERE t2.tag = $tag AND t1.tag != $tag
1050              GROUP BY o1.tag_id
1051              ORDER BY quantity DESC
1052              LIMIT 0, $max
1053              ";
1054  
1055          $rs = $adb->query($sql) or die("Syntax Error: $sql");
1056          while(!$rs->EOF) {
1057              $retarr[$rs->fields['tag']] = $rs->fields['quantity'];
1058              $rs->MoveNext();
1059          }
1060  
1061          return $retarr;
1062      }
1063  
1064      /**
1065       * similar_objects
1066       *
1067       * This method implements a simple ability to find some objects in the database
1068       * that might be similar to an existing object. It determines this by trying
1069       * to match other objects that share the same tags.
1070       *
1071       * The user of the method has to use a threshold (by default, 1) which specifies
1072       * how many tags other objects must have in common to match. If the original object 
1073       * has no tags, then it won't match anything. Matched objects are returned in order
1074       * of most similar to least similar.
1075       *
1076       * The more tags set on a database, the better this method works. Since this
1077       * is such an expensive operation, it requires a limit to be set via max_objects.
1078       *
1079       * @param int The unique ID of the object to find similar objects for.
1080       * @param int The Threshold of tags that must be found in common (default: 1)
1081       * @param int The maximum number of similar objects to return (default: 5).
1082       * @param int Optionally pass a tagger id to restrict similarity to a tagger's view.
1083       * 
1084       * @return array Returns a PHP array with matched objects ordered by strength of match descending. 
1085       * Each element is an associative array with the following elements:
1086       * - 'strength' => A floating-point strength of match from 0-1.0
1087       * - 'object_id' => Unique ID of the matched object
1088       *
1089       */
1090  	function similar_objects($object_id, $threshold = 1, $max_objects = 5, $tagger_id = NULL) {
1091          global $adb;    
1092          $retarr = array();
1093  
1094          $object_id = intval($object_id);
1095          $threshold = intval($threshold);
1096          $max_objects = intval($max_objects);
1097          if (!isset($object_id) || !($object_id > 0)) {
1098              return $retarr;
1099          }
1100          if ($threshold <= 0) {
1101              return $retarr;
1102          }
1103          if ($max_objects <= 0) {
1104              return $retarr;
1105          }
1106  
1107          // Pass in a zero-limit to get all tags.
1108          $tagItems = $this->get_tags_on_object($object_id, 0, 0);
1109  
1110          $tagArray = array();
1111          foreach ($tagItems as $tagItem) {
1112              $tagArray[] = $adb->quote($tagItem['tag']);
1113          }
1114          $tagArray = array_unique($tagArray);
1115  
1116          $numTags = count($tagArray);
1117          if ($numTags == 0) {
1118              return $retarr; // Return empty set of matches
1119          }
1120  
1121          $tagList = join(',', $tagArray);
1122  
1123          $prefix = $this->_table_prefix;
1124  
1125          $sql = "SELECT matches.object_id, COUNT( matches.object_id ) AS num_common_tags
1126              FROM $prefix}freetagged_objects as matches
1127              INNER JOIN $prefix}freetags as tags ON ( tags.id = matches.tag_id )
1128              WHERE tags.tag IN ($tagList)
1129              GROUP BY matches.object_id
1130              HAVING num_common_tags >= $threshold
1131              ORDER BY num_common_tags DESC
1132              LIMIT 0, $max_objects
1133              ";
1134  
1135          $rs = $adb->query($sql) or die("Syntax Error: $sql, Error: " . $adb->ErrorMsg());
1136          while(!$rs->EOF) {
1137              $retarr[] = array (
1138                  'object_id' => $rs->fields['object_id'],
1139                  'strength' => ($rs->fields['num_common_tags'] / $numTags)
1140                  );
1141              $rs->MoveNext();
1142          }
1143  
1144          return $retarr;
1145      }
1146  
1147  
1148      /*
1149       * Prints debug text if debug is enabled.
1150       *
1151       * @param string The text to output
1152       * @return boolean Always returns true
1153       */
1154  	function debug_text($text) {
1155          if ($this->_debug) {
1156              echo "$text<br>\n";
1157          }
1158          return true;
1159      }
1160  
1161  }
1162  


Généré le : Sun Feb 25 10:22:19 2007 par Balluche grâce à PHPXref 0.7