Tag - Add label field
authorcolemanw <coleman@civicrm.org>
Sat, 7 Oct 2023 21:02:28 +0000 (17:02 -0400)
committercolemanw <coleman@civicrm.org>
Sun, 8 Oct 2023 02:17:48 +0000 (22:17 -0400)
26 files changed:
CRM/Admin/Page/AJAX.php
CRM/Core/BAO/EntityTag.php
CRM/Core/BAO/Tag.php
CRM/Core/DAO/EntityTag.php
CRM/Core/DAO/Tag.php
CRM/Tag/Form/Edit.php
CRM/Tag/Page/Tag.php
CRM/Upgrade/Incremental/php/FiveSixtyEight.php
CRM/Upgrade/Incremental/sql/5.68.alpha1.mysql.tpl
Civi/Api4/Service/Spec/Provider/TagCreationSpecProvider.php
Civi/Test/Api3TestTrait.php
api/v3/Tag.php
ext/search_kit/Civi/Search/Admin.php
ext/search_kit/ang/crmSearchAdmin.module.js
ext/search_kit/ang/crmSearchAdmin/crmSearchAdminTags.component.js
ext/search_kit/ang/crmSearchAdmin/crmSearchAdminTags.html
ext/search_kit/ang/crmSearchTasks/crmSearchTaskTag.ctrl.js
ext/search_kit/ang/crmSearchTasks/crmSearchTaskTag.html
sql/civicrm_data/civicrm_tag.sqldata.php
templates/CRM/Tag/Form/Edit.tpl
templates/CRM/Tag/Page/Tag.tpl
tests/phpunit/CRM/Core/BAO/TagTest.php
tests/phpunit/api/v3/TagTest.php
tests/phpunit/api/v4/Custom/PseudoconstantTest.php
xml/schema/Core/EntityTag.xml
xml/schema/Core/Tag.xml

index 0cc9bbbb8ced4ebc70047d47711373d8facb170d..c82be9ba8dbaed5d45db3c21ed01b1c62aa19557 100644 (file)
@@ -290,7 +290,7 @@ class CRM_Admin_Page_AJAX {
     $result = [];
 
     $whereClauses = ['is_tagset <> 1'];
-    $orderColumn = 'name';
+    $orderColumn = 'label';
 
     // fetch all child tags in Array('parent_tag' => array('child_tag_1', 'child_tag_2', ...)) format
     $childTagIDs = CRM_Core_BAO_Tag::getChildTags($substring);
@@ -300,7 +300,7 @@ class CRM_Admin_Page_AJAX {
       $whereClauses[] = "parent_id = $parent";
     }
     elseif ($substring) {
-      $whereClauses['substring'] = " name LIKE '%$substring%' ";
+      $whereClauses['substring'] = " label LIKE '%$substring%' ";
       if (!empty($parentIDs)) {
         $whereClauses['substring'] = sprintf(" %s OR id IN (%s) ", $whereClauses['substring'], implode(',', $parentIDs));
       }
@@ -328,7 +328,7 @@ class CRM_Admin_Page_AJAX {
         $usedFor = (array) explode(',', $dao->used_for);
         $tag = [
           'id' => $dao->id,
-          'text' => $dao->name,
+          'text' => $dao->label,
           'a_attr' => [
             'class' => 'crm-tag-item',
           ],
index c48246775db47cd33537292d58696fc3fc65fe43..97c94866d95da8fd15f670cf314c88d002317512 100644 (file)
@@ -301,7 +301,7 @@ class CRM_Core_BAO_EntityTag extends CRM_Core_DAO_EntityTag {
   public static function getContactTags($contactID, $count = FALSE) {
     $contactTags = [];
     if (!$count) {
-      $select = "SELECT ct.id, ct.name ";
+      $select = "SELECT ct.id, ct.label ";
     }
     else {
       $select = "SELECT count(*) as cnt";
@@ -322,7 +322,7 @@ class CRM_Core_BAO_EntityTag extends CRM_Core_DAO_EntityTag {
     }
 
     while ($dao->fetch()) {
-      $contactTags[$dao->id] = $dao->name;
+      $contactTags[$dao->id] = $dao->label;
     }
 
     return $contactTags;
index cd2a0522e05efe6f10a8bcb23c57b2ee14ad1634..a86f4b1785ce6fd99564e035959f66997d793b26 100644 (file)
@@ -311,7 +311,7 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag {
         'sort' => "name ASC",
       ],
       'is_tagset' => 0,
-      'return' => ['name', 'description', 'parent_id', 'color', 'is_selectable', 'used_for'],
+      'return' => ['label', 'description', 'parent_id', 'color', 'is_selectable', 'used_for'],
     ];
     if ($usedFor) {
       $params['used_for'] = ['LIKE' => "%$usedFor%"];
@@ -322,7 +322,7 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag {
     $allTags = [];
     foreach (CRM_Utils_Array::value('values', civicrm_api3('Tag', 'get', $params)) as $id => $tag) {
       $allTags[$id] = [
-        'text' => $tag['name'],
+        'text' => $tag['label'],
         'id' => $id,
         'description' => $tag['description'] ?? NULL,
         'parent_id' => $tag['parent_id'] ?? NULL,
@@ -366,8 +366,16 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag {
    */
   public static function add(&$params, $ids = []) {
     $id = $params['id'] ?? $ids['tag'] ?? NULL;
-    if (!$id && !self::dataExists($params)) {
-      return NULL;
+    if (!$id) {
+      // Make label from name if missing.
+      if (CRM_Utils_System::isNull($params['label'] ?? NULL)) {
+        // If name is also missing, cannot create object.
+        if (CRM_Utils_System::isNull($params['name'] ?? NULL)) {
+          // FIXME: Throw exception
+          return NULL;
+        }
+        $params['label'] = $params['name'];
+      }
     }
 
     // Check permission to create or modify reserved tag
@@ -401,7 +409,6 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag {
     // save creator id and time
     if (!$id) {
       $params['created_id'] = $params['created_id'] ?? CRM_Core_Session::getLoggedInContactID();
-      $params['created_date'] = $params['created_date'] ?? date('YmdHis');
     }
 
     $tag = self::writeRecord($params);
@@ -422,23 +429,6 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag {
     return $tag;
   }
 
-  /**
-   * Check if there is data to create the object.
-   *
-   * @param array $params
-   *
-   * @return bool
-   */
-  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') {
-      return TRUE;
-    }
-
-    return FALSE;
-  }
-
   /**
    * Get the tag sets for a entity object.
    *
@@ -450,7 +440,7 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag {
    */
   public static function getTagSet($entityTable) {
     $tagSets = [];
-    $query = "SELECT name, id FROM civicrm_tag
+    $query = "SELECT label, id FROM civicrm_tag
               WHERE is_tagset=1 AND parent_id IS NULL and used_for LIKE %1";
     $dao = CRM_Core_DAO::executeQuery($query, [
       1 => [
@@ -459,7 +449,7 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag {
       ],
     ], TRUE, NULL, FALSE, FALSE);
     while ($dao->fetch()) {
-      $tagSets[$dao->id] = $dao->name;
+      $tagSets[$dao->id] = $dao->label;
     }
     return $tagSets;
   }
index 3f57d572bdecb9825380674732ec5df88f4ad08b..df3e79bd2ae813ad7b60050d49f5b1641a3ef20f 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Generated from xml/schema/CRM/Core/EntityTag.xml
  * DO NOT EDIT.  Generated by CRM_Core_CodeGen
- * (GenCodeChecksum:2fccc138a26fe391325fd641c891cd91)
+ * (GenCodeChecksum:5bca5ff1c4ba7d85034410408464f0ac)
  */
 
 /**
@@ -200,7 +200,8 @@ class CRM_Core_DAO_EntityTag extends CRM_Core_DAO {
           'pseudoconstant' => [
             'table' => 'civicrm_tag',
             'keyColumn' => 'id',
-            'labelColumn' => 'name',
+            'labelColumn' => 'label',
+            'nameColumn' => 'name',
             'condition' => 'is_tagset != 1',
           ],
           'add' => '1.1',
index b84fa0d5e4e102adf00864000ea304c105ba6944..b6c5a2f1a4d4adc20f365c62db9fbe957c1209a9 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Generated from xml/schema/CRM/Core/Tag.xml
  * DO NOT EDIT.  Generated by CRM_Core_CodeGen
- * (GenCodeChecksum:f8d8698f48fbd60b8d8e0bf8eff40c47)
+ * (GenCodeChecksum:ded9d6a9f9c08146a0205da83c838c91)
  */
 
 /**
@@ -35,7 +35,7 @@ class CRM_Core_DAO_Tag extends CRM_Core_DAO {
    *
    * @var string
    */
-  public static $_labelField = 'name';
+  public static $_labelField = 'label';
 
   /**
    * Should CiviCRM log any modifications to this table in the civicrm_log table.
@@ -54,7 +54,7 @@ class CRM_Core_DAO_Tag extends CRM_Core_DAO {
   public $id;
 
   /**
-   * Name of Tag.
+   * Unique machine name
    *
    * @var string
    *   (SQL type: varchar(64))
@@ -62,6 +62,15 @@ class CRM_Core_DAO_Tag extends CRM_Core_DAO {
    */
   public $name;
 
+  /**
+   * User-facing tag name
+   *
+   * @var string
+   *   (SQL type: varchar(64))
+   *   Note that values will be retrieved from the database as a string.
+   */
+  public $label;
+
   /**
    * Optional verbose description of the tag.
    *
@@ -206,7 +215,7 @@ class CRM_Core_DAO_Tag extends CRM_Core_DAO {
           'name' => 'name',
           'type' => CRM_Utils_Type::T_STRING,
           'title' => ts('Tag Name'),
-          'description' => ts('Name of Tag.'),
+          'description' => ts('Unique machine name'),
           'required' => TRUE,
           'maxlength' => 64,
           'size' => CRM_Utils_Type::BIG,
@@ -223,6 +232,30 @@ class CRM_Core_DAO_Tag extends CRM_Core_DAO {
           'localizable' => 0,
           'add' => '1.1',
         ],
+        'label' => [
+          'name' => 'label',
+          'type' => CRM_Utils_Type::T_STRING,
+          'title' => ts('Tag Label'),
+          'description' => ts('User-facing tag name'),
+          'required' => TRUE,
+          'maxlength' => 64,
+          'size' => CRM_Utils_Type::BIG,
+          'usage' => [
+            'import' => FALSE,
+            'export' => FALSE,
+            'duplicate_matching' => FALSE,
+            'token' => FALSE,
+          ],
+          'where' => 'civicrm_tag.label',
+          'table_name' => 'civicrm_tag',
+          'entity' => 'Tag',
+          'bao' => 'CRM_Core_BAO_Tag',
+          'localizable' => 0,
+          'html' => [
+            'type' => 'Text',
+          ],
+          'add' => '5.68',
+        ],
         'description' => [
           'name' => 'description',
           'type' => CRM_Utils_Type::T_STRING,
@@ -267,7 +300,8 @@ class CRM_Core_DAO_Tag extends CRM_Core_DAO {
           'pseudoconstant' => [
             'table' => 'civicrm_tag',
             'keyColumn' => 'id',
-            'labelColumn' => 'name',
+            'labelColumn' => 'label',
+            'nameColumn' => 'name',
           ],
           'add' => '1.1',
         ],
@@ -375,6 +409,7 @@ class CRM_Core_DAO_Tag extends CRM_Core_DAO {
           'localizable' => 0,
           'FKClassName' => 'CRM_Contact_DAO_Contact',
           'html' => [
+            'type' => 'EntityRef',
             'label' => ts("Created By"),
           ],
           'add' => '3.4',
@@ -412,10 +447,17 @@ class CRM_Core_DAO_Tag extends CRM_Core_DAO {
             'token' => FALSE,
           ],
           'where' => 'civicrm_tag.created_date',
+          'default' => 'CURRENT_TIMESTAMP',
           'table_name' => 'civicrm_tag',
           'entity' => 'Tag',
           'bao' => 'CRM_Core_BAO_Tag',
           'localizable' => 0,
+          'html' => [
+            'type' => 'Select Date',
+            'formatType' => 'activityDateTime',
+            'label' => ts("Created Date"),
+          ],
+          'readonly' => TRUE,
           'add' => '3.4',
         ],
       ];
index 09d38c00f06f1f80a3ccaf1204742d25b3dbc186..6fa36b90f284706572ca72789ad87f855e6e0910 100644 (file)
@@ -102,13 +102,9 @@ class CRM_Tag_Form_Edit extends CRM_Admin_Form {
 
       $this->applyFilter('__ALL__', 'trim');
 
-      $this->add('text', 'name', ts('Name'),
-        CRM_Core_DAO::getAttribute('CRM_Core_DAO_Tag', 'name'), TRUE
+      $this->add('text', 'label', ts('Label'),
+        CRM_Core_DAO::getAttribute('CRM_Core_DAO_Tag', 'label'), TRUE
       );
-      $this->addRule('name', ts('Name already exists in Database.'), 'objectExists', [
-        'CRM_Core_DAO_Tag',
-        $this->_id,
-      ]);
 
       $this->add('text', 'description', ts('Description'),
         CRM_Core_DAO::getAttribute('CRM_Core_DAO_Tag', 'description')
@@ -142,7 +138,7 @@ class CRM_Tag_Form_Edit extends CRM_Admin_Form {
     if (empty($this->_id) && $cloneFrom) {
       $params = ['id' => $cloneFrom];
       CRM_Core_BAO_Tag::retrieve($params, $this->_values);
-      $this->_values['name'] .= ' (' . ts('copy') . ')';
+      $this->_values['label'] .= ' (' . ts('copy') . ')';
       if (!empty($this->_values['is_reserved']) && !CRM_Core_Permission::check('administer reserved tags')) {
         $this->_values['is_reserved'] = 0;
       }
@@ -171,10 +167,10 @@ class CRM_Tag_Form_Edit extends CRM_Admin_Form {
       }
       if (count($this->_id) == 1 && $deleted == 1) {
         if ($tag['is_tagset']) {
-          CRM_Core_Session::setStatus(ts("The tag set '%1' has been deleted.", [1 => $tag['name']]), ts('Deleted'), 'success');
+          CRM_Core_Session::setStatus(ts("The tag set '%1' has been deleted.", [1 => $tag['label']]), ts('Deleted'), 'success');
         }
         else {
-          CRM_Core_Session::setStatus(ts("The tag '%1' has been deleted.", [1 => $tag['name']]), ts('Deleted'), 'success');
+          CRM_Core_Session::setStatus(ts("The tag '%1' has been deleted.", [1 => $tag['label']]), ts('Deleted'), 'success');
         }
       }
       else {
@@ -211,7 +207,7 @@ class CRM_Tag_Form_Edit extends CRM_Admin_Form {
         $params['is_selectable'] = 0;
       }
       $tag = CRM_Core_BAO_Tag::add($params);
-      CRM_Core_Session::setStatus(ts("The tag '%1' has been saved.", [1 => $tag->name]), ts('Saved'), 'success');
+      CRM_Core_Session::setStatus(ts("The tag '%1' has been saved.", [1 => $tag->label]), ts('Saved'), 'success');
       $this->ajaxResponse['tag'] = $tag->toArray();
     }
     CRM_Core_Session::singleton()->pushUserContext(CRM_Utils_System::url('civicrm/tag'));
index 772439b7c4e12a90315a35586db89d86df0a836e..6d4a26c69431feb864149d282a3eccdee64098ce 100644 (file)
@@ -40,7 +40,7 @@ class CRM_Tag_Page_Tag extends CRM_Core_Page {
     }
 
     $result = civicrm_api3('Tag', 'get', [
-      'return' => ["name", "used_for", "description", "created_id.display_name", "created_date", "is_reserved"],
+      'return' => ["name", "label", "used_for", "description", "created_id.display_name", "created_date", "is_reserved"],
       'is_tagset' => 1,
       'options' => ['limit' => 0],
     ]);
index c974bd67be76895ec7afc23677480fb43b3e5c72..66421e94350a273e0f78bbdea08c530a824d1c4f 100644 (file)
@@ -28,6 +28,10 @@ class CRM_Upgrade_Incremental_php_FiveSixtyEight extends CRM_Upgrade_Incremental
    *   The version number matching this function name
    */
   public function upgrade_5_68_alpha1($rev): void {
+    // Add column prior to updating it via runSql
+    $this->addTask('Add Tag.label field', 'addColumn', 'civicrm_tag', 'label', "varchar(64) NOT NULL COMMENT 'User-facing tag name' AFTER `name`");
+    $this->addTask('Update Tag.name field', 'alterColumn', 'civicrm_tag', 'name', "varchar(64) NOT NULL COMMENT 'Unique machine name'");
+    $this->addTask('Update Tag.created_date field', 'alterColumn', 'civicrm_tag', 'created_date', "datetime DEFAULT CURRENT_TIMESTAMP COMMENT 'Date and time that tag was created.'");
     $this->addTask(ts('Upgrade DB to %1: SQL', [1 => $rev]), 'runSql', $rev);
   }
 
index 4e284bc85b86454a159f0c05d659edd38a5286fb..9a2b0a2373aef3fae29bf80d17145967150ee478 100644 (file)
@@ -1 +1,3 @@
 {* file to handle db changes in 5.68.alpha1 during upgrade *}
+
+UPDATE `civicrm_tag` SET `label` = `name` WHERE `label` = '';
index dcfaeaff75ee1290cdf11e03e292d701e6bc819a..dce76d87fcd28d74539792030f0c1b1301abfe67 100644 (file)
@@ -25,6 +25,8 @@ class TagCreationSpecProvider extends \Civi\Core\Service\AutoService implements
    */
   public function modifySpec(RequestSpec $spec) {
     $spec->getFieldByName('used_for')->setDefaultValue('civicrm_contact');
+    $spec->getFieldByName('name')->setRequired(FALSE)->setRequiredIf('empty($values.label)');
+    $spec->getFieldByName('label')->setRequired(FALSE)->setRequiredIf('empty($values.name)');
   }
 
   /**
index d12f912bdb2106eb0a9a95a7073817d6b353d5b2..d68b04de11753d02a8871c87976db1b73fbf4e0c 100644 (file)
@@ -125,7 +125,7 @@ trait Api3TestTrait {
    * @param null $extraOutput
    * @return array|int
    */
-  public function callAPIFailure($entity, $action, $params, $expectedErrorMessage = NULL, $extraOutput = NULL) {
+  public function callAPIFailure($entity, $action, $params = [], $expectedErrorMessage = NULL, $extraOutput = NULL) {
     if (is_array($params)) {
       $params += [
         'version' => $this->_apiversion,
index 89bc9070cef18cf9858202a4c3aa2ba6c4c9ce65..57434e43415180b6e4b85b4ef78e2fa4d60268ec 100644 (file)
@@ -45,7 +45,6 @@ function civicrm_api3_tag_create($params) {
  */
 function _civicrm_api3_tag_create_spec(&$params) {
   $params['used_for']['api.default'] = 'civicrm_contact';
-  $params['name']['api.required'] = 1;
   $params['id']['api.aliases'] = ['tag'];
 }
 
index 8232f2523325f3e733e4e0dd784dd7dec19c31b7..b32af91822ff123b975db4d22633f13ddb65c63c 100644 (file)
@@ -53,7 +53,7 @@ class Admin {
         ->setLoadOptions(['id', 'label'])
         ->execute()->first()['options'],
       'tags' => Tag::get()
-        ->addSelect('id', 'name', 'color', 'is_selectable', 'description')
+        ->addSelect('id', 'label', 'color', 'is_selectable', 'description')
         ->addWhere('used_for', 'CONTAINS', 'civicrm_saved_search')
         ->execute(),
     ];
index 01947260a024e6a5f1861c30632ac6d9b20c9858..1b9adf9ffdf061767f97eab3a020c733d691f98c 100644 (file)
@@ -55,7 +55,7 @@
         modules.push({text: label, id: key});
       }, []), 'text');
       this.getTags = function() {
-        return {results: formatForSelect2(CRM.crmSearchAdmin.tags, 'id', 'name', ['color', 'description'])};
+        return {results: formatForSelect2(CRM.crmSearchAdmin.tags, 'id', 'label', ['color', 'description'])};
       };
 
       this.getPrimaryEntities = function() {
index 0527d1a1c45873e9d0d81c839443f16aab938a1f..a17d18c02d81b90e29bdb2bd2a9eead7d42cbc35 100644 (file)
@@ -64,9 +64,9 @@
         }
       };
 
-      this.makeTag = function(name) {
+      this.makeTag = function(label) {
         crmApi4('Tag', 'create', {
-          values: {name: name, color: ctrl.color, is_selectable: true, used_for: ['civicrm_saved_search']}
+          values: {label: label, color: ctrl.color, is_selectable: true, used_for: ['civicrm_saved_search']}
         }, 0).then(function(tag) {
           ctrl.allTags.push(tag);
           ctrl.toggleTag(tag);
index 31711443dc46e993d6f5682e7a3b2cfe2ea25415..26e52e3bf07232528f8f712347cee4ba4e9c7f9c 100644 (file)
       <a href ng-click="$ctrl.makeTag($ctrl.search)">{{ $ctrl.search }}</a>
     </div>
   </li>
-  <li ng-repeat="tag in $ctrl.allTags | filter:{name: $ctrl.search, is_selectable: true}">
+  <li ng-repeat="tag in $ctrl.allTags | filter:{label: $ctrl.search, is_selectable: true}">
     <a href ng-click="$ctrl.toggleTag(tag)">
       <i class="crm-i fa-check" style="visibility: {{ $ctrl.hasTag(tag) ? 'visible' : 'hidden' }}"></i>
       <span class="crm-search-admin-tag-color" style="background-color: {{:: tag.color }}"></span>
-      {{:: tag.name }}
+      {{:: tag.label }}
     </a>
   </li>
 </ul>
 <span class="badge" ng-repeat="id in $ctrl.tagIds" style="{{:: $ctrl.getStyle(id) }}">
-  {{:: $ctrl.getTag(id).name }}
+  {{:: $ctrl.getTag(id).label }}
 </span>
index bace4279079c1173f41048c81475d43bd52c46d5..ed1ac2f9c2283dc044417be0ff71136f3df71845 100644 (file)
 
     crmApi4({
       tags: ['Tag', 'get', {
-        select: ['id', 'name', 'color', 'description', 'is_selectable', 'parent_id'],
+        select: ['id', 'label', 'color', 'description', 'is_selectable', 'parent_id'],
         where: [
           ['is_tagset', '=', false],
           ['used_for:name', 'CONTAINS', this.entity],
           ['OR', [['parent_id', 'IS NULL'], ['parent_id.is_tagset', '=', false]]]
         ],
-        orderBy: {name: 'ASC'}
+        orderBy: {label: 'ASC'}
       }],
       tagsets: ['Tag', 'get', {
-        select: ['id', 'name'],
+        select: ['id', 'name', 'label'],
         where: [['is_tagset', '=', true], ['used_for:name', 'CONTAINS', this.entity]]
       }],
     }).then(function(result) {
@@ -36,7 +36,7 @@
       var sorted = _.transform(rawTags, function(sorted, tag) {
         sorted[tag.id] = {
           id: tag.id,
-          text: tag.name,
+          text: tag.label,
           description: tag.description,
           color: tag.color,
           disabled: !tag.is_selectable,
index 51363c6e9d3bfaf1512b1256b7fe80d9c9ae4d9f..d1bb6a09d8f2ef0a1cbbcee36141a32b05061bbc 100644 (file)
@@ -28,7 +28,7 @@
         >
       </div>
       <div ng-repeat="tagset in $ctrl.tagsets" class="form-inline">
-        <label>{{:: tagset.name }}</label>
+        <label>{{:: tagset.label }}</label>
         <input
           ng-model="$ctrl.selectedTagsetTags[tagset.name]"
           ng-list
index 974fba7f4f4b73414051179e6d2ab630391bab58..4811b8825a24cc044181dfc037648542c586f53c 100644 (file)
@@ -6,23 +6,33 @@ return CRM_Core_CodeGen_SqlData::create('civicrm_tag')
   ])
   ->addValues([
     [
-      'name' => ts('Non-profit'),
+      'label' => ts('Non-profit'),
+      'name' => 'Non_profit',
       'description' => ts('Any not-for-profit organization.'),
+      'color' => '#0bcb21',
     ],
     [
-      'name' => ts('Company'),
+      'label' => ts('Company'),
+      'name' => 'Company',
       'description' => ts('For-profit organization.'),
+      'color' => '#2260c3',
     ],
     [
-      'name' => ts('Government Entity'),
+      'label' => ts('Government Entity'),
+      'name' => 'Government_Entity',
       'description' => ts('Any governmental entity.'),
+      'color' => '#cd4b13',
     ],
     [
-      'name' => ts('Major Donor'),
+      'label' => ts('Major Donor'),
+      'name' => 'Major_Donor',
       'description' => ts('High-value supporter of our organization.'),
+      'color' => '#0cdae9',
     ],
     [
-      'name' => ts('Volunteer'),
+      'label' => ts('Volunteer'),
+      'name' => 'Volunteer',
       'description' => ts('Active volunteers.'),
+      'color' => '#f0dc00',
     ],
   ]);
index 434ef8ecfb8c7feb705b755e43c296297148cc7b..e70aa192b814e6bd1b69f3af7fa9905e4e28107e 100644 (file)
@@ -12,8 +12,8 @@
   {if $action eq 1 or $action eq 2}
     <table class="form-layout-compressed">
        <tr class="crm-tag-form-block-label">
-          <td class="label">{$form.name.label}</td>
-          <td>{$form.name.html}</td>
+          <td class="label">{$form.label.label}</td>
+          <td>{$form.label.html}</td>
        </tr>
        <tr class="crm-tag-form-block-description">
           <td class="label">{$form.description.label}</td>
index 4caf65995fd4d4b0becc67e83c8baaba00bbbeed..5f37b01b81526a91f7dcc99c9ca689d11810d92c 100644 (file)
@@ -24,7 +24,7 @@
       </li>
       {foreach from=$tagsets item=set}
         <li class="ui-corner-all crm-tab-button {if ($set.is_reserved)}is-reserved{/if}" title="{ts 1=', '|implode:$set.used_for_label}Tag Set for %1{/ts}">
-          <a href="#tagset-{$set.id}">{$set.name}</a>
+          <a href="#tagset-{$set.id}">{$set.label}</a>
         </li>
       {/foreach}
       {if call_user_func(array('CRM_Core_Permission','check'), 'administer Tagsets')}
 
         function updateTagset(info) {
           tagSets[tagset].description = info.description;
-          tagSets[tagset].name = info.name;
+          tagSets[tagset].label = info.label;
           tagSets[tagset].used_for = info.used_for;
           tagSets[tagset].is_reserved = info.is_reserved;
           formatTagSet(tagSets[tagset]);
         function addTagsetHeader() {
           $('.tagset-header', $panel).remove();
           $panel.prepend(tagsetHeaderTpl(tagSets[tagset]));
-          $("a[href='#tagset-" + tagset + "']").text(tagSets[tagset].name)
+          $("a[href='#tagset-" + tagset + "']").text(tagSets[tagset].label)
             .parent().toggleClass('is-reserved', tagSets[tagset].is_reserved == 1)
             .attr('title', ts('{/literal}{ts escape='js' 1='%1'}Tag Set for %1{/ts}{literal}', {'1': tagSets[tagset].used_for_label.join(', ')}));
         }
           e.preventDefault();
           var sets = [{key: '0', value: '{/literal}{ts escape='js'}Main Tag Tree{/ts}{literal}'}];
           _.each(tagSets, function(tagSet) {
-            sets.push({key: tagSet.id, value: tagSet.name});
+            sets.push({key: tagSet.id, value: tagSet.label});
           });
           CRM.confirm({
             title: '{/literal}{ts escape='js'}Move to Tagset{/ts}{literal}',
             tagSets[data.tag.id].display_name = user.display_name;
             formatTagSet(tagSets[data.tag.id]);
             $("#new-tagset").before('<div id="tagset-' + data.tag.id + '">');
-            $("a[href='#new-tagset']").parent().before('<li class="ui-corner-all crm-tab-button"><a href="#tagset-' + data.tag.id + '">' + data.tag.name + '</a></li>');
+            $("a[href='#new-tagset']").parent().before('<li class="ui-corner-all crm-tab-button"><a href="#tagset-' + data.tag.id + '">' + data.tag.label + '</a></li>');
             $('#mainTabContainer').tabs('refresh');
             $('#mainTabContainer').tabs('option', 'active', -2);
           });
   <div class="crm-entity" data-entity="Tag" data-id="<%= id %>">
     <h4>
       <input type="color" value="<%= data.color %>" <% if (!data.is_reserved || adminReserved) {ldelim} %>title="{ts}Select color{/ts}" <% {rdelim} else {ldelim} %>disabled<% {rdelim} %> />
-      <span class="<% if (!data.is_reserved || adminReserved) {ldelim} %>crm-editable<% {rdelim} %>" data-field="name"><%- text %></span>
+      <span class="<% if (!data.is_reserved || adminReserved) {ldelim} %>crm-editable<% {rdelim} %>" data-field="label"><%- text %></span>
     </h4>
     <hr />
     <div><span class="tdl">{ts}Description:{/ts}</span>
index fa395dba0343bb9cb3557183835f60de2751de40..6168636597718c972a0f4f579bc75221f9d5b664 100644 (file)
@@ -18,13 +18,17 @@ class CRM_Core_BAO_TagTest extends CiviUnitTestCase {
     // Create an example hierarchy of tags.
     // The family tree of Abraham is used as a well known example of a hierarchy (no statement intended).
     // The order of ids is important because of: https://lab.civicrm.org/dev/core/-/issues/4049, that's why we create Isaac before Abraham.
-    CRM_Core_DAO::executeQuery("INSERT INTO civicrm_tag (id,name,used_for,is_tagset) VALUES(1, 'Isaac', 'civicrm_contact', 0);");
-    CRM_Core_DAO::executeQuery("INSERT INTO civicrm_tag (id,name,used_for,is_tagset) VALUES(2, 'Abraham', 'civicrm_contact', 0);");
-    CRM_Core_DAO::executeQuery("INSERT INTO civicrm_tag (id,name,used_for,is_tagset) VALUES(3, 'Jacob', 'civicrm_contact', 0);");
-    CRM_Core_DAO::executeQuery("INSERT INTO civicrm_tag (id,name,used_for,is_tagset) VALUES(4, 'Ishmael', 'civicrm_contact', 1);");
-    CRM_Core_DAO::executeQuery("INSERT INTO civicrm_tag (id,name,used_for,is_tagset) VALUES(5, 'Kedar', 'civicrm_contact', 1);");
-    CRM_Core_DAO::executeQuery("INSERT INTO civicrm_tag (id,name,used_for,is_tagset) VALUES(6, 'Working', 'civicrm_activity', 1);");
-    CRM_Core_DAO::executeQuery("INSERT INTO civicrm_tag (id,name,used_for,is_tagset) VALUES(7, 'Eating', 'civicrm_activity', 1);");
+    CRM_Core_DAO::executeQuery("
+      INSERT INTO civicrm_tag (id, name, label, used_for, is_tagset)
+      VALUES
+        (1, 'Isaac', 'Isaac', 'civicrm_contact', 0),
+        (2, 'Abraham', 'Abraham', 'civicrm_contact', 0),
+        (3, 'Jacob', 'Jacob', 'civicrm_contact', 0),
+        (4, 'Ishmael', 'Ishmael', 'civicrm_contact', 1),
+        (5, 'Kedar', 'Kedar', 'civicrm_contact', 1),
+        (6, 'Working', 'Working', 'civicrm_activity', 1),
+        (7, 'Eating', 'Eating', 'civicrm_activity', 1);
+    ");
 
     // Isaac is the son of abraham
     CRM_Core_DAO::executeQuery("UPDATE civicrm_tag SET parent_id = 2 WHERE name = 'Isaac';");
index d975f59889fb2d0308ab400a73b90bd739d7b492..fe741287a4059a13fc26699d9b94affb908d5a44 100644 (file)
@@ -96,7 +96,7 @@ class api_v3_TagTest extends CiviUnitTestCase {
    */
   public function testCreateEmptyParams($version) {
     $this->_apiversion = $version;
-    $result = $this->callAPIFailure('tag', 'create', [], 'name');
+    $result = $this->callAPIFailure('tag', 'create');
   }
 
   /**
index 27fe1de01520c3631ebf1f9fbbd7f45d2a658722..ea8d8dc52ec5d1b55d2c6b034ea08e9e371d2d35 100644 (file)
@@ -272,6 +272,7 @@ class PseudoconstantTest extends CustomTestBase {
     $options = array_column($options, NULL, 'name');
     $this->assertEquals('colorful', $options[$tag]['description']);
     $this->assertEquals('#aabbcc', $options[$tag]['color']);
+    $this->assertEquals($tag, $options[$tag]['name']);
     $this->assertEquals($tag, $options[$tag]['label']);
   }
 
index ab063e8a7d8faf5eeddd07e7f3f4162bdf672944..c39d45b2daae30918861c50e1cb9e8d2d7fdf854 100644 (file)
@@ -56,7 +56,8 @@
     <pseudoconstant>
       <table>civicrm_tag</table>
       <keyColumn>id</keyColumn>
-      <labelColumn>name</labelColumn>
+      <nameColumn>name</nameColumn>
+      <labelColumn>label</labelColumn>
       <condition>is_tagset != 1</condition>
     </pseudoconstant>
     <html>
index 3d875d5346ed140be071bcdfcb912f2a69a2537e..620eb591e903b8f5ea0ce046df46f189d786df6b 100644 (file)
@@ -8,7 +8,7 @@
   <add>1.1</add>
   <log>true</log>
   <icon>fa-tag</icon>
-  <labelField>name</labelField>
+  <labelField>label</labelField>
   <field>
     <name>id</name>
     <title>Tag ID</title>
     <type>varchar</type>
     <required>true</required>
     <length>64</length>
-    <comment>Name of Tag.</comment>
+    <comment>Unique machine name</comment>
     <add>1.1</add>
   </field>
+  <!-- TODO: Localizable -->
+  <field>
+    <name>label</name>
+    <title>Tag Label</title>
+    <comment>User-facing tag name</comment>
+    <required>true</required>
+    <type>varchar</type>
+    <length>64</length>
+    <html>
+      <type>Text</type>
+    </html>
+    <add>5.68</add>
+  </field>
+  <!-- TODO: Localizable -->
   <field>
     <name>description</name>
     <title>Description</title>
@@ -50,7 +64,8 @@
     <pseudoconstant>
       <table>civicrm_tag</table>
       <keyColumn>id</keyColumn>
-      <labelColumn>name</labelColumn>
+      <nameColumn>name</nameColumn>
+      <labelColumn>label</labelColumn>
     </pseudoconstant>
     <html>
       <label>Parent Tag</label>
     <comment>FK to civicrm_contact, who created this tag</comment>
     <html>
       <label>Created By</label>
+      <type>EntityRef</type>
     </html>
     <add>3.4</add>
   </field>
     <type>datetime</type>
     <title>Tag Created Date</title>
     <comment>Date and time that tag was created.</comment>
+    <default>CURRENT_TIMESTAMP</default>
+    <readonly>true</readonly>
+    <html>
+      <type>Select Date</type>
+      <formatType>activityDateTime</formatType>
+      <label>Created Date</label>
+    </html>
     <add>3.4</add>
   </field>
 </table>