Merge pull request #4892 from colemanw/INFRA-132
[civicrm-core.git] / CRM / Core / BAO / Tag.php
index 63378fc4cddb9951cdd086bb05307da0b9d37612..475bb5f6ff9f83e448eeaa65899cd532ce837a96 100644 (file)
@@ -1,7 +1,7 @@
 <?php
 /*
  +--------------------------------------------------------------------+
- | CiviCRM version 4.5                                                |
+ | CiviCRM version 4.6                                                |
  +--------------------------------------------------------------------+
  | Copyright CiviCRM LLC (c) 2004-2014                                |
  +--------------------------------------------------------------------+
 class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag {
 
   /**
-   * class constructor
+   * Class constructor
    */
-  function __construct() {
+  public function __construct() {
     parent::__construct();
   }
 
   /**
-   * Takes a bunch of params that are needed to match certain criteria and
-   * retrieves the relevant objects. Typically the valid params are only
-   * contact_id. We'll tweak this function to be more full featured over a period
-   * of time. This is the inverse function of create. It also stores all the retrieved
-   * values in the default array
+   * Fetch object based on array of properties
    *
-   * @param array $params      (reference ) an assoc array of name/value pairs
-   * @param array $defaults    (reference ) an assoc array to hold the flattened values
+   * @param array $params
+   *   (reference ) an assoc array of name/value pairs.
+   * @param array $defaults
+   *   (reference ) an assoc array to hold the flattened values.
    *
    * @return object     CRM_Core_DAO_Tag object on success, otherwise null
-   * @access public
    * @static
    */
-  static function retrieve(&$params, &$defaults) {
+  public static function retrieve(&$params, &$defaults) {
     $tag = new CRM_Core_DAO_Tag();
     $tag->copyValues($params);
     if ($tag->find(TRUE)) {
@@ -71,7 +68,7 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag {
    *
    * @return mixed
    */
-  function getTree($usedFor = NULL, $excludeHidden = FALSE) {
+  public function getTree($usedFor = NULL, $excludeHidden = FALSE) {
     if (!isset($this->tree)) {
       $this->buildTree($usedFor, $excludeHidden);
     }
@@ -83,8 +80,8 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag {
    * @param null $usedFor
    * @param bool $excludeHidden
    */
-  function buildTree($usedFor = NULL, $excludeHidden = FALSE) {
-    $sql = "SELECT id, parent_id, name, description FROM civicrm_tag";
+  public function buildTree($usedFor = NULL, $excludeHidden = FALSE) {
+    $sql = "SELECT id, parent_id, name, description, is_selectable FROM civicrm_tag";
 
     $whereClause = array();
     if ($usedFor) {
@@ -109,6 +106,7 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag {
       $thisref['parent_id'] = $dao->parent_id;
       $thisref['name'] = $dao->name;
       $thisref['description'] = $dao->description;
+      $thisref['is_selectable'] = $dao->is_selectable;
 
       if (!$dao->parent_id) {
         $this->tree[$dao->id] = &$thisref;
@@ -124,14 +122,15 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag {
    * @param array $usedFor
    * @param bool $buildSelect
    * @param bool $all
-   * @param null $parentId
+   * @param int $parentId
    *
    * @return array
    */
-  static function getTagsUsedFor($usedFor = array('civicrm_contact'),
+  public static function getTagsUsedFor($usedFor = array(
+    'civicrm_contact'),
     $buildSelect = TRUE,
-    $all         = FALSE,
-    $parentId    = NULL
+    $all = FALSE,
+    $parentId = NULL
   ) {
     $tags = array();
 
@@ -182,17 +181,28 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag {
   }
 
   /**
+   * Function to retrieve tags
+   *
    * @param string $usedFor
+   *   Which type of tag entity.
    * @param array $tags
-   * @param null $parentId
+   *   Tags array.
+   * @param int $parentId
+   *   Parent id if you want need only children.
    * @param string $separator
+   *   Separator to indicate children.
+   * @param bool $formatSelectable
+   *   Add special property for non-selectable.
+   *                tag, so they cannot be selected
    *
    * @return array
    */
-  static function getTags($usedFor = 'civicrm_contact',
+  static function getTags(
+    $usedFor = 'civicrm_contact',
     &$tags = array(),
-    $parentId  = NULL,
-    $separator = '&nbsp;&nbsp;'
+    $parentId = NULL,
+    $separator = '&nbsp;&nbsp;',
+    $formatSelectable = FALSE
   ) {
     if (!is_array($tags)) {
       $tags = array();
@@ -203,7 +213,7 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag {
     // Instead of recursively making mysql queries, we'll make one big
     // query and build the heirarchy with the algorithm below.
     $args = array(1 => array('%' . $usedFor . '%', 'String'));
-    $query = "SELECT id, name, parent_id, is_tagset
+    $query = "SELECT id, name, parent_id, is_tagset, is_selectable
                   FROM civicrm_tag
               WHERE used_for LIKE %1";
     if ($parentId) {
@@ -220,13 +230,35 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag {
     // are necessarily placed.
     $roots = $rows = array();
     while ($dao->fetch()) {
+      // note that we are prepending id with "crm_disabled_opt" which identifies
+      // them as disabled so that they cannot be selected. We do some magic
+      // in crm-select2 js function that marks option values to "disabled"
+      // current QF version in CiviCRM does not support passing this attribute,
+      // so this is another ugly hack / workaround,
+      // also know one is too keen to upgrade QF :P
+      $idPrefix = '';
+      if ($formatSelectable && !$dao->is_selectable) {
+        $idPrefix = "crm_disabled_opt";
+      }
       if ($dao->parent_id == $parentId && $dao->is_tagset == 0) {
-        $roots[] = array('id' => $dao->id, 'prefix' => '', 'name' => $dao->name);
+        $roots[] = array(
+          'id' => $dao->id,
+          'prefix' => '',
+          'name' => $dao->name,
+          'idPrefix' => $idPrefix,
+          );
       }
       else {
-        $rows[] = array('id' => $dao->id, 'prefix' => '', 'name' => $dao->name, 'parent_id' => $dao->parent_id);
+        $rows[] = array(
+          'id' => $dao->id,
+          'prefix' => '',
+          'name' => $dao->name,
+          'parent_id' => $dao->parent_id,
+          'idPrefix' => $idPrefix,
+         );
       }
     }
+
     $dao->free();
     // While we have nodes left to build, shift the first (alphabetically)
     // node of the list, place it in our tags list and loop through the
@@ -237,7 +269,11 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag {
       $new_roots         = array();
       $current_rows      = $rows;
       $root              = array_shift($roots);
-      $tags[$root['id']] = array($root['prefix'], $root['name']);
+      $tags[$root['id']] = array(
+        $root['prefix'],
+        $root['name'],
+        $root['idPrefix'],
+        );
 
       // As you find the children, append them to the end of the new set
       // of roots (maintain alphabetical ordering). Also remove the node
@@ -245,7 +281,12 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag {
       if (is_array($current_rows)) {
         foreach ($current_rows as $key => $row) {
           if ($row['parent_id'] == $root['id']) {
-            $new_roots[] = array('id' => $row['id'], 'prefix' => $tags[$root['id']][0] . $separator, 'name' => $row['name']);
+            $new_roots[] = array(
+              'id' => $row['id'],
+              'prefix' => $tags[$root['id']][0] . $separator,
+              'name' => $row['name'],
+              'idPrefix' => $row['idPrefix'],
+              );
             unset($rows[$key]);
           }
         }
@@ -258,24 +299,31 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag {
 
     // Prefix each name with the calcuated spacing to give the visual
     // appearance of ordering when transformed into HTML in the form layer.
-    foreach ($tags as & $tag) {
-      $tag = $tag[0] . $tag[1];
+    // here is the actual code that to prepends and set disabled attribute for
+    // non-selectable tags
+    $formattedTags = array();
+    foreach ($tags as $key => $tag) {
+      if (!empty($tag[2])) {
+        $key = $tag[2] . "-" . $key;
+      }
+      $formattedTags[$key] = $tag[0] . $tag[1];
     }
 
+    $tags = $formattedTags;
     return $tags;
   }
 
   /**
-   * Function to delete the tag
+   * Delete the tag
    *
-   * @param int $id   tag id
+   * @param int $id
+   *   Tag id.
    *
    * @return boolean
-   * @access public
    * @static
    *
    */
-  static function del($id) {
+  public static function del($id) {
     // since this is a destructive operation, lets make sure
     // id is a postive number
     CRM_Utils_Type::validate($id, 'Positive');
@@ -299,21 +347,22 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag {
   }
 
   /**
-   * takes an associative array and creates a contact object
+   * Takes an associative array and creates a contact object
    *
    * The function extract all the params it needs to initialize the create a
    * contact object. the params array could contain additional unused name/value
    * pairs
    *
-   * @param array  $params         (reference) an assoc array of name/value pairs
-   * @param array  $ids  (optional)  the array that holds all the db ids - we are moving away from this in bao
+   * @param array $params
+   *   (reference) an assoc array of name/value pairs.
+   * @param array $ids
+   *   (optional) the array that holds all the db ids - we are moving away from this in bao.
    * signatures
    *
    * @return object    CRM_Core_DAO_Tag object on success, otherwise null
-   * @access public
    * @static
    */
-  static function add(&$params, $ids = array()) {
+  public static function add(&$params, $ids = array()) {
     $id = CRM_Utils_Array::value('id', $params, CRM_Utils_Array::value('tag', $ids));
     if (!$id && !self::dataExists($params)) {
       return NULL;
@@ -345,7 +394,8 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag {
     // if we modify parent tag, then we need to update all children
     if ($tag->parent_id === 'null') {
       CRM_Core_DAO::executeQuery("UPDATE civicrm_tag SET used_for=%1 WHERE parent_id = %2",
-        array(1 => array($params['used_for'], 'String'),
+        array(
+      1 => array($params['used_for'], 'String'),
           2 => array($tag->id, 'Integer'),
         )
       );
@@ -357,13 +407,13 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag {
   /**
    * Check if there is data to create the object
    *
-   * @param array  $params         (reference ) an assoc array of name/value pairs
+   * @param array $params
+   *   (reference ) an assoc array of name/value pairs.
    *
    * @return boolean
-   * @access public
    * @static
    */
-  static function dataExists(&$params) {
+  public static function dataExists(&$params) {
     // Disallow empty values except for the number zero.
     // TODO: create a utility for this since it's needed in many places
     if (!empty($params['name']) || (string) $params['name'] === '0') {
@@ -374,15 +424,15 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag {
   }
 
   /**
-   * Function to get the tag sets for a entity object
+   * Get the tag sets for a entity object
    *
-   * @param string $entityTable entity_table
+   * @param string $entityTable
+   *   Entity_table.
    *
    * @return array $tagSets array of tag sets
-   * @access public
    * @static
    */
-  static function getTagSet($entityTable) {
+  public static function getTagSet($entityTable) {
     $tagSets = array();
     $query = "SELECT name, id FROM civicrm_tag
               WHERE is_tagset=1 AND parent_id IS NULL and used_for LIKE %1";
@@ -395,12 +445,13 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag {
   }
 
   /**
-   * Function to get the tags that are not children of a tagset.
+   * Get the tags that are not children of a tagset.
    *
-   * @return array $tags associated array of tag name and id@access public
+   * @return array $tags associated array of tag name and id
+   * @access public
    * @static
    */
-  static function getTagsNotInTagset() {
+  public static function getTagsNotInTagset() {
     $tags = $tagSets = array();
     // first get all the tag sets
     $query = "SELECT id FROM civicrm_tag WHERE is_tagset=1 AND parent_id IS NULL";
@@ -424,4 +475,3 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag {
     return $tags;
   }
 }
-