Merge pull request #3828 from johanv/CRM-15104-line_item_issues_participant_api
authorcolemanw <coleman@civicrm.org>
Thu, 14 Aug 2014 18:46:29 +0000 (19:46 +0100)
committercolemanw <coleman@civicrm.org>
Thu, 14 Aug 2014 18:46:29 +0000 (19:46 +0100)
CRM-15104 fixed some issues with line items creating participants with the API

41 files changed:
CRM/Contact/BAO/Query.php
CRM/Contact/Form/Search/Builder.php
CRM/Contact/Page/View/CustomData.php
CRM/Core/BAO/CustomField.php
CRM/Core/BAO/CustomGroup.php
CRM/Core/BAO/CustomQuery.php
CRM/Core/BAO/Tag.php
CRM/Profile/Page/Listings.php
CRM/Utils/HttpClient.php
Civi/CiUtil/Arrays.php [new file with mode: 0644]
Civi/CiUtil/Command/AntagonistCommand.php [new file with mode: 0644]
Civi/CiUtil/Command/CompareCommand.php [new file with mode: 0644]
Civi/CiUtil/Command/LsCommand.php [new file with mode: 0644]
Civi/CiUtil/ComparisonPrinter.php [new file with mode: 0644]
Civi/CiUtil/EnvTestRunner.php [new file with mode: 0644]
Civi/CiUtil/PHPUnitParser.php [new file with mode: 0644]
Civi/CiUtil/PHPUnitScanner.php [new file with mode: 0644]
css/civicrm.css
js/angular-crmCaseType.js
partials/crmCaseType/caseTypeDetails.html
templates/CRM/Case/Page/CustomDataView.tpl
templates/CRM/Contact/Form/Contact.tpl
templates/CRM/Contact/Form/Edit/CustomData.tpl
templates/CRM/Contact/Form/Search/Criteria/Basic.tpl
templates/CRM/Custom/Form/CustomData.tpl
templates/CRM/Custom/Form/MultiValueSearch.js.tpl [new file with mode: 0644]
templates/CRM/Custom/Form/Search.tpl
templates/CRM/Custom/Page/CustomDataView.tpl
templates/CRM/Profile/Form/Search.tpl
templates/CRM/Tag/Form/Tag.tpl
templates/CRM/Tag/Form/Tagtree.hlp [new file with mode: 0644]
templates/CRM/Tag/Form/Tagtree.tpl [new file with mode: 0644]
tests/phpunit/WebTest/Event/PCPAddTest.php
tests/phpunit/WebTest/Import/SavedMappingTest.php
tests/phpunit/WebTest/Member/StandaloneAddTest.php
tools/scripts/jmat [new file with mode: 0755]
tools/scripts/phpunit-antagonist [new file with mode: 0755]
tools/scripts/phpunit-compare [new file with mode: 0755]
tools/scripts/phpunit-indiv [new file with mode: 0755]
tools/scripts/phpunit-ls [new file with mode: 0755]
tools/scripts/runTests.sh.txt [deleted file]

index 681142af2022b9b7e966469d1a6bc5e501849a9f..0c7df5514f0a27a21a0cdf7e8595a49f052c1488 100644 (file)
@@ -563,6 +563,13 @@ class CRM_Contact_BAO_Query {
         if (!array_key_exists($cfID, $this->_cfIDs)) {
           $this->_cfIDs[$cfID] = array();
         }
+        // Set wildcard value based on "and/or" selection
+        foreach ($this->_params as $key => $param) {
+          if ($param[0] == $value[0] . '_operator') {
+            $value[4] = $param[2] == 'or';
+            break;
+          }
+        }
         $this->_cfIDs[$cfID][] = $value;
       }
 
index e2a88eaded998ac030815779a672b973d8642f03..380d04a2696cb1f24b6df0a52a7de8fc0b65c6ce 100644 (file)
@@ -450,10 +450,14 @@ class CRM_Contact_Form_Search_Builder extends CRM_Contact_Form_Search {
       foreach ($fields['values'] as $field => $info) {
         if (!empty($info['options']) || !empty($info['pseudoconstant']) || !empty($info['option_group_id'])) {
           $options[$field] = $entity;
+          // Hack for when search field doesn't match db field - e.g. "country" instead of "country_id"
           if (substr($field, -3) == '_id') {
             $options[substr($field, 0, -3)] = $entity;
           }
         }
+        elseif (!empty($info['data_type']) && in_array($info['data_type'], array('StateProvince', 'Country'))) {
+          $options[$field] = $entity;
+        }
         elseif (in_array(substr($field, 0, 3), array('is_', 'do_')) || CRM_Utils_Array::value('data_type', $info) == 'Boolean') {
           $options[$field] = 'yesno';
           if ($entity != 'contact') {
index 2406084a6aac24137afc31b5c1eaaf072b930a7e..07a89e82779eca4606b8624af3e85bc83511d808 100644 (file)
@@ -128,9 +128,12 @@ class CRM_Contact_Page_View_CustomData extends CRM_Core_Page {
         'style'
       );
 
-      if ($displayStyle === 'Tab with table' && $this->_multiRecordDisplay != 'single') {
+      if ($this->_multiRecordDisplay != 'single') {
         $id = "custom_{$this->_groupId}";
         $this->ajaxResponse['tabCount'] = CRM_Contact_BAO_Contact::getCountComponent($id, $this->_contactId, $groupTree[$this->_groupId]['table_name']);
+      }
+
+      if ($displayStyle === 'Tab with table' && $this->_multiRecordDisplay != 'single') {
         $ctype = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact',
           $this->_contactId,
           'contact_type'
index 3336e02f20179c74ac6c1fee1f4cfc7a996154a8..4a902f1054e4b9135cc0b9101f06a4b9c3c048cd 100644 (file)
@@ -726,7 +726,7 @@ class CRM_Core_BAO_CustomField extends CRM_Core_DAO_CustomField {
    * @param CRM_Core_Form $qf form object (reference)
    * @param string $elementName name of the custom field
    * @param $fieldId
-   * @param boolean $inactiveNeeded
+   * @param boolean $inactiveNeeded -deprecated
    * @param bool $useRequired
    * @param boolean $search true if used for search else false
    * @param string $label label for custom field
@@ -744,6 +744,7 @@ class CRM_Core_BAO_CustomField extends CRM_Core_DAO_CustomField {
     $label          = NULL
   ) {
     $field = self::getFieldObject($fieldId);
+    $widget = $field->html_type;
 
     // Custom field HTML should indicate group+field name
     $groupName = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomGroup', $field->custom_group_id);
@@ -752,29 +753,44 @@ class CRM_Core_BAO_CustomField extends CRM_Core_DAO_CustomField {
     $field->attributes .= $dataCrmCustomAttr;
 
     // Fixed for Issue CRM-2183
-    if ($field->html_type == 'TextArea' && $search) {
-      $field->html_type = 'Text';
+    if ($widget == 'TextArea' && $search) {
+      $widget = 'Text';
+    }
+
+    if ($widget == 'Select State/Province' || $widget == 'Select Country') {
+      $qf->_stateCountryMap[$widget == 'Select Country' ? 'country' : 'state_province'][] = $elementName;
     }
 
     $placeholder = $search ? ts('- any -') : ($useRequired ? ts('- select -') : ts('- none -'));
 
     // FIXME: Why are select state/country separate widget types?
-    if (in_array($field->html_type, array('Select', 'Multi-Select', 'Select State/Province', 'Multi-Select State/Province', 'Select Country', 'Multi-Select Country'))) {
+    $isSelect = (in_array($widget, array('Select', 'Multi-Select', 'Select State/Province', 'Multi-Select State/Province', 'Select Country', 'Multi-Select Country', 'AdvMulti-Select', 'CheckBox', 'Radio')));
+
+    if ($isSelect) {
+      $options = CRM_Utils_Array::value('values', civicrm_api3('contact', 'getoptions', array('field' => "custom_$fieldId", 'context' => $search ? 'search' : 'create'), array()));
+
+      // Consolidate widget types to simplify the below switch statement
+      if ($search || ($widget !== 'AdvMulti-Select' && strpos($widget, 'Select') !== FALSE)) {
+        $widget = 'Select';
+      }
       $selectAttributes = array(
         'data-crm-custom' => $dataCrmCustomVal,
         'class' => 'crm-select2',
       );
-      if (strpos($field->html_type, 'Multi') === 0) {
+      // Search field is always multi-select
+      if ($search || strpos($field->html_type, 'Multi') !== FALSE) {
+        $selectAttributes['class'] .= ' huge';
         $selectAttributes['multiple'] = 'multiple';
+        $selectAttributes['placeholder'] = $placeholder;
+      }
+      // Add data for popup link. Normally this is handled by CRM_Core_Form->addSelect
+      if ($field->option_group_id && !$search && $widget == 'Select' && CRM_Core_Permission::check('administer CiviCRM')) {
+        $selectAttributes += array(
+          'data-api-entity' => 'contact', // FIXME: This works because the getoptions api isn't picky about custom fields, but it's WRONG
+          'data-api-field' => 'custom_' . $field->id,
+          'data-option-edit-path' => 'civicrm/admin/options/' . CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionGroup', $field->option_group_id),
+        );
       }
-    }
-    // Add data so popup link. Normally this is handled by CRM_Core_Form->addSelect
-    if ($field->option_group_id && !$search && in_array($field->html_type, array('Select', 'Multi-Select')) && CRM_Core_Permission::check('administer CiviCRM')) {
-      $selectAttributes += array(
-        'data-api-entity' => 'contact', // FIXME: This works because the getoptions api isn't picky about custom fields, but it's WRONG
-        'data-api-field' => 'custom_' . $field->id,
-        'data-option-edit-path' => 'civicrm/admin/options/' . CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionGroup', $field->option_group_id),
-      );
     }
 
     if (!isset($label)) {
@@ -785,14 +801,15 @@ class CRM_Core_BAO_CustomField extends CRM_Core_DAO_CustomField {
      * at some point in time we might want to split the below into small functions
      **/
 
-    switch ($field->html_type) {
+    switch ($widget) {
       case 'Text':
+      case 'Link':
         if ($field->is_search_range && $search) {
           $qf->add('text', $elementName . '_from', $label . ' ' . ts('From'), $field->attributes);
           $qf->add('text', $elementName . '_to', ts('To'), $field->attributes);
         }
         else {
-          $element = &$qf->add(strtolower($field->html_type), $elementName, $label,
+          $element = &$qf->add('text', $elementName, $label,
             $field->attributes,
             $useRequired && !$search
           );
@@ -816,7 +833,7 @@ class CRM_Core_BAO_CustomField extends CRM_Core_DAO_CustomField {
         if ($field->text_length) {
           $attributes .= ' maxlength=' . $field->text_length;
         }
-        $element = &$qf->add(strtolower($field->html_type),
+        $element = &$qf->add('textarea',
           $elementName,
           $label,
           $attributes,
@@ -861,20 +878,10 @@ class CRM_Core_BAO_CustomField extends CRM_Core_DAO_CustomField {
 
       case 'Radio':
         $choice = array();
-        if ($field->data_type != 'Boolean') {
-          $customOption = CRM_Core_BAO_CustomOption::valuesByID($field->id,
-            $field->option_group_id
-          );
-          foreach ($customOption as $v => $l) {
-            $choice[] = $qf->createElement('radio', NULL, '', $l, (string)$v, $field->attributes);
-          }
-          $group = $qf->addGroup($choice, $elementName, $label);
-        }
-        else {
-          $choice[] = $qf->createElement('radio', NULL, '', ts('Yes'), '1', $field->attributes);
-          $choice[] = $qf->createElement('radio', NULL, '', ts('No'), '0', $field->attributes);
-          $group = $qf->addGroup($choice, $elementName, $label);
+        foreach ($options as $v => $l) {
+          $choice[] = $qf->createElement('radio', NULL, '', $l, (string)$v, $field->attributes);
         }
+        $group = $qf->addGroup($choice, $elementName, $label);
         if ($useRequired && !$search) {
           $qf->addRule($elementName, ts('%1 is a required field.', array(1 => $label)), 'required');
         }
@@ -883,34 +890,30 @@ class CRM_Core_BAO_CustomField extends CRM_Core_DAO_CustomField {
         }
         break;
 
+      // For all select elements
       case 'Select':
-        $selectOption = CRM_Core_BAO_CustomOption::valuesByID($field->id,
-          $field->option_group_id
-        );
-
-        $qf->add('select', $elementName, $label,
-          array('' => $placeholder) + $selectOption,
-          $useRequired && !$search,
-          $selectAttributes
-        );
-        break;
+        if (empty($selectAttributes['multiple'])) {
+          $options = array('' => $placeholder) + $options;
+        }
+        $qf->add('select', $elementName, $label, $options, $useRequired && !$search, $selectAttributes);
 
-      //added for select multiple
+        // Add and/or option for fields that store multiple values
+        if ($search && self::isSerialized($field)) {
 
-      case 'AdvMulti-Select':
-        $selectOption = CRM_Core_BAO_CustomOption::valuesByID($field->id,
-          $field->option_group_id
-        );
-        if ($search &&
-          count($selectOption) > 1
-        ) {
-          $selectOption['CiviCRM_OP_OR'] = ts('Select to match ANY; unselect to match ALL');
+          $operators = array(
+            $qf->createElement('radio', NULL, '', ts('Any'), 'or', array('title' => ts('Results may contain any of the selected options'))),
+            $qf->createElement('radio', NULL, '', ts('All'), 'and', array('title' => ts('Results must have all of the selected options'))),
+          );
+          $qf->addGroup($operators, $elementName . '_operator');
+          $qf->setDefaults(array($elementName . '_operator' => 'or'));
         }
+        break;
 
+      case 'AdvMulti-Select':
         $include =& $qf->addElement(
           'advmultiselect',
           $elementName,
-          $label, $selectOption,
+          $label, $options,
           array(
             'size' => 5,
             'style' => '',
@@ -927,35 +930,11 @@ class CRM_Core_BAO_CustomField extends CRM_Core_DAO_CustomField {
         }
         break;
 
-      case 'Multi-Select':
-        $selectOption = CRM_Core_BAO_CustomOption::valuesByID($field->id,
-          $field->option_group_id
-        );
-        if ($search &&
-          count($selectOption) > 1
-        ) {
-          $selectOption['CiviCRM_OP_OR'] = ts('Select to match ANY; unselect to match ALL');
-        }
-        $qf->addElement('select', $elementName, $label, $selectOption, $selectAttributes);
-
-        if ($useRequired && !$search) {
-          $qf->addRule($elementName, ts('%1 is a required field.', array(1 => $label)), 'required');
-        }
-        break;
-
       case 'CheckBox':
-        $customOption = CRM_Core_BAO_CustomOption::valuesByID($field->id,
-          $field->option_group_id
-        );
         $check = array();
-        foreach ($customOption as $v => $l) {
+        foreach ($options as $v => $l) {
           $check[] = &$qf->addElement('advcheckbox', $v, NULL, $l, array('data-crm-custom' => $dataCrmCustomVal));
         }
-        if ($search &&
-          count($check) > 1
-        ) {
-          $check[] = &$qf->addElement('advcheckbox', 'CiviCRM_OP_OR', NULL, ts('Check to match ANY; uncheck to match ALL'), array('data-crm-custom' => $dataCrmCustomVal));
-        }
         $qf->addGroup($check, $elementName, $label);
         if ($useRequired && !$search) {
           $qf->addRule($elementName, ts('%1 is a required field.', array(1 => $label)), 'required');
@@ -977,45 +956,6 @@ class CRM_Core_BAO_CustomField extends CRM_Core_DAO_CustomField {
         $qf->addUploadElement($elementName);
         break;
 
-      case 'Select State/Province':
-        //Add State
-        $stateOption = array('' => $placeholder) + CRM_Core_PseudoConstant::stateProvince();
-        $qf->add('select', $elementName, $label, $stateOption,
-          $useRequired && !$search,
-          $selectAttributes
-        );
-        $qf->_stateCountryMap['state_province'][] = $elementName;
-        break;
-
-      case 'Multi-Select State/Province':
-        //Add Multi-select State/Province
-        $stateOption = CRM_Core_PseudoConstant::stateProvince();
-
-        $qf->addElement('select', $elementName, $label, $stateOption, $selectAttributes);
-        if ($useRequired && !$search) {
-          $qf->addRule($elementName, ts('%1 is a required field.', array(1 => $label)), 'required');
-        }
-        break;
-
-      case 'Select Country':
-        //Add Country
-        $countryOption = array('' => $placeholder) + CRM_Core_PseudoConstant::country();
-        $qf->add('select', $elementName, $label, $countryOption,
-          $useRequired && !$search,
-          $selectAttributes
-        );
-        $qf->_stateCountryMap['country'][] = $elementName;
-        break;
-
-      case 'Multi-Select Country':
-        //Add Country
-        $countryOption = CRM_Core_PseudoConstant::country();
-        $qf->addElement('select', $elementName, $label, $countryOption, $selectAttributes);
-        if ($useRequired && !$search) {
-          $qf->addRule($elementName, ts('%1 is a required field.', array(1 => $label)), 'required');
-        }
-        break;
-
       case 'RichTextEditor':
         $attributes = array('rows' => $field->note_rows, 'cols' => $field->note_columns, 'data-crm-custom' => $dataCrmCustomVal);
         if ($field->text_length) {
@@ -1056,6 +996,7 @@ class CRM_Core_BAO_CustomField extends CRM_Core_DAO_CustomField {
           $attributes += array(
             'entity' => 'option_value',
             'placeholder' => $placeholder,
+            'multiple' => $search,
             'api' => array(
               'params' => array('option_group_id' => $field->option_group_id),
             ),
@@ -1074,7 +1015,7 @@ class CRM_Core_BAO_CustomField extends CRM_Core_DAO_CustomField {
           $qf->addRule($elementName . '_from', ts('%1 From must be an integer (whole number).', array(1 => $label)), 'integer');
           $qf->addRule($elementName . '_to', ts('%1 To must be an integer (whole number).', array(1 => $label)), 'integer');
         }
-        else {
+        elseif ($widget == 'Text') {
           $qf->addRule($elementName, ts('%1 must be an integer (whole number).', array(1 => $label)), 'integer');
         }
         break;
@@ -1084,7 +1025,7 @@ class CRM_Core_BAO_CustomField extends CRM_Core_DAO_CustomField {
           $qf->addRule($elementName . '_from', ts('%1 From must be a number (with or without decimal point).', array(1 => $label)), 'numeric');
           $qf->addRule($elementName . '_to', ts('%1 To must be a number (with or without decimal point).', array(1 => $label)), 'numeric');
         }
-        else {
+        elseif ($widget == 'Text') {
           $qf->addRule($elementName, ts('%1 must be a number (with or without decimal point).', array(1 => $label)), 'numeric');
         }
         break;
@@ -1094,23 +1035,15 @@ class CRM_Core_BAO_CustomField extends CRM_Core_DAO_CustomField {
           $qf->addRule($elementName . '_from', ts('%1 From must in proper money format. (decimal point/comma/space is allowed).', array(1 => $label)), 'money');
           $qf->addRule($elementName . '_to', ts('%1 To must in proper money format. (decimal point/comma/space is allowed).', array(1 => $label)), 'money');
         }
-        else {
+        elseif ($widget == 'Text') {
           $qf->addRule($elementName, ts('%1 must be in proper money format. (decimal point/comma/space is allowed).', array(1 => $label)), 'money');
         }
         break;
 
       case 'Link':
-        $qf->add(
-          'text',
-          $elementName,
-          $label,
-          array(
-            'onfocus' => "if (!this.value) {  this.value='http://';} else return false",
-            'onblur' => "if ( this.value == 'http://') {  this.value='';} else return false",
-            'data-crm-custom' => $dataCrmCustomVal,
-          ),
-          $useRequired && !$search
-        );
+        $element->setAttribute('onfocus', "if (!this.value) {this.value='http://';}");
+        $element->setAttribute('onblur', "if (this.value == 'http://') {this.value='';}");
+        $element->setAttribute('class', "url");
         $qf->addRule($elementName, ts('Enter a valid Website.'), 'wikiURL');
         break;
     }
@@ -1270,10 +1203,6 @@ class CRM_Core_BAO_CustomField extends CRM_Core_DAO_CustomField {
         $v = array();
         $p = array();
         foreach ($checkedData as $key => $val) {
-          if ($key === 'CiviCRM_OP_OR') {
-            continue;
-          }
-
           if ($html_type == 'CheckBox') {
             if ($val) {
               $p[] = $key;
@@ -2552,5 +2481,17 @@ WHERE cf.id = %1 AND cg.is_multiple = 1";
 
     return $isMultipleWithGid;
   }
+
+  /**
+   * Does this field store a serialized string?
+   * @param CRM_Core_DAO_CustomField|array $field
+   * @return bool
+   */
+  static function isSerialized($field) {
+    // Fields retrieved via api are an array, or from the dao are an object. We'll accept either.
+    $field = (array) $field;
+    // FIXME: Currently the only way to know if data is serialized is by looking at the html_type. It would be cleaner to decouple this.
+    return ($field['html_type'] == 'CheckBox' || strpos($field['html_type'], 'Multi') !== FALSE);
+  }
 }
 
index 060dd7dd1f37e64c00112efac997e0ea1f9b6a63..29a091598a43cc8a6a58ddd444a34d674c00f4ff 100644 (file)
@@ -1238,7 +1238,6 @@ ORDER BY civicrm_custom_group.weight,
       if (!isset($group['fields'])) {
         continue;
       }
-      $groupId = CRM_Utils_Array::value('id', $group);
       foreach ($group['fields'] as $field) {
         if (CRM_Utils_Array::value('element_value', $field) !== NULL) {
           $value = $field['element_value'];
@@ -1255,7 +1254,6 @@ ORDER BY civicrm_custom_group.weight,
           continue;
         }
 
-        $fieldId = $field['id'];
         if (!empty($field['element_name'])) {
           $elementName = $field['element_name'];
         }
index 6a36b4468d27f5dc7005b070070ea236d1ceb1b2..8ca162022e06eefdfc34576835a797f4a35be9db 100644 (file)
@@ -347,101 +347,82 @@ SELECT label, value
       foreach ($values as $tuple) {
         list($name, $op, $value, $grouping, $wildcard) = $tuple;
 
-        // fix $value here to escape sql injection attacks
         $field = $this->_fields[$id];
-        $qillValue = CRM_Core_BAO_CustomField::getDisplayValue($value, $id, $this->_options);
 
+        $fieldName = "{$field['table_name']}.{$field['column_name']}";
+
+        // Autocomplete comes back as a string not an array
+        if ($field['data_type'] == 'String' && $field['html_type'] == 'Autocomplete-Select' && $op == '=') {
+          $value = explode(',', $value);
+        }
+
+        // Handle multi-select search for any data type
+        if (is_array($value) && !$field['is_search_range']) {
+          $isSerialized = CRM_Core_BAO_CustomField::isSerialized($field);
+          $wildcard = $isSerialized ? $wildcard : TRUE;
+          $options = CRM_Utils_Array::value('values', civicrm_api3('contact', 'getoptions', array('field' => $name, 'context' => 'search'), array()));
+          $qillValue = '';
+          $sqlOP = $wildcard ? ' OR ' : ' AND ';
+          $sqlValue = array();
+          foreach ($value as $num => &$v) {
+            $sep = count($value) > (1 + $num) ? ', ' : (' ' . ($wildcard ? ts('OR') : ts('AND')) . ' ');
+            $qillValue .= ($num ? $sep : '') . $options[$v];
+            $v = CRM_Core_DAO::escapeString($v);
+            if ($isSerialized) {
+              $sqlValue[] = "( $fieldName like '%" . CRM_Core_DAO::VALUE_SEPARATOR . $v . CRM_Core_DAO::VALUE_SEPARATOR . "%' ) ";
+            }
+            else {
+              $v = "'$v'";
+            }
+          }
+          if (!$isSerialized) {
+            $sqlValue = array("$fieldName IN (" . implode(',', $value) . ")");
+          }
+          $this->_where[$grouping][] = ' ( ' . implode($sqlOP, $sqlValue) . ' ) ';
+          $this->_qill[$grouping][] = "$field[label] $op $qillValue";
+          continue;
+        }
+
+        // fix $value here to escape sql injection attacks
         if (!is_array($value)) {
           $value = CRM_Core_DAO::escapeString(trim($value));
         }
 
-        $fieldName = "{$field['table_name']}.{$field['column_name']}";
+        $qillValue = CRM_Core_BAO_CustomField::getDisplayValue($value, $id, $this->_options);
+
         switch ($field['data_type']) {
           case 'String':
             $sql = "$fieldName";
-            // if we are coming in from listings,
-            // for checkboxes the value is already in the right format and is NOT an array
-            if (is_array($value)) {
-
-              //ignoring $op value for checkbox and multi select
-              $sqlValue   = array();
-              $sqlOP      = ' AND ';
-              $sqlOPlabel = ts('match ALL');
-              if ($field['html_type'] == 'CheckBox') {
-                foreach ($value as $k => $v) {
-                  if ($v) {
-                    if ($k == 'CiviCRM_OP_OR') {
-                      $sqlOP = ' OR ';
-                      $sqlOPlabel = ts('match ANY');
-                      continue;
-                    }
-
-                    $sqlValue[] = "( $sql like '%" . CRM_Core_DAO::VALUE_SEPARATOR . $k . CRM_Core_DAO::VALUE_SEPARATOR . "%' ) ";
-                  }
-                }
-                //if user check only 'CiviCRM_OP_OR' check box
-                //of custom checkbox field, then ignore this field.
-                if (!empty($sqlValue)) {
-                  $this->_where[$grouping][] = ' ( ' . implode($sqlOP, $sqlValue) . ' ) ';
-                  $this->_qill[$grouping][] = "{$field['label']} $op $qillValue ( $sqlOPlabel )";
-                }
-                // for multi select
-              }
-              else {
-                foreach ($value as $k => $v) {
-                  if ($v == 'CiviCRM_OP_OR') {
-                    $sqlOP = ' OR ';
-                    $sqlOPlabel = ts('match ANY');
-                    continue;
-                  }
-                  $v = CRM_Core_DAO::escapeString($v);
-                  $sqlValue[] = "( $sql like '%" . CRM_Core_DAO::VALUE_SEPARATOR . $v . CRM_Core_DAO::VALUE_SEPARATOR . "%' ) ";
-                }
-                //if user select only 'CiviCRM_OP_OR' value
-                //of custom multi select field, then ignore this field.
-                if (!empty($sqlValue)) {
-                  $this->_where[$grouping][] = ' ( ' . implode($sqlOP, $sqlValue) . ' ) ';
-                  $this->_qill[$grouping][] = "$field[label] $op $qillValue ( $sqlOPlabel )";
-                }
-              }
+
+            if ($field['is_search_range'] && is_array($value)) {
+              $this->searchRange($field['id'],
+                $field['label'],
+                $field['data_type'],
+                $fieldName,
+                $value,
+                $grouping
+              );
             }
             else {
-              if ($field['is_search_range'] && is_array($value)) {
-                $this->searchRange($field['id'],
-                  $field['label'],
-                  $field['data_type'],
-                  $fieldName,
-                  $value,
-                  $grouping
-                );
-              }
-              else {
-                if (in_array($field['html_type'], array('Select', 'Radio', 'Autocomplete-Select'))) {
-                  $wildcard = FALSE;
-                  $val = CRM_Utils_Type::escape($value, 'String');
-                }
-                else {
-                  $val = CRM_Utils_Type::escape($strtolower(trim($value)), 'String');
-                }
-
-                if ($wildcard) {
-                  $val = $strtolower(CRM_Core_DAO::escapeString($val));
-                  $val = "%$val%";
-                  $op  = 'LIKE';
-                }
-
-                //FIX for custom data query fired against no value(NULL/NOT NULL)
-                $this->_where[$grouping][] = CRM_Contact_BAO_Query::buildClause($sql, $op, $val, $field['data_type']);
-                $this->_qill[$grouping][] = "$field[label] $op $qillValue";
+              $val = CRM_Utils_Type::escape($strtolower(trim($value)), 'String');
+
+              if ($wildcard) {
+                $val = $strtolower(CRM_Core_DAO::escapeString($val));
+                $val = "%$val%";
+                $op  = 'LIKE';
               }
+
+              //FIX for custom data query fired against no value(NULL/NOT NULL)
+              $this->_where[$grouping][] = CRM_Contact_BAO_Query::buildClause($sql, $op, $val, $field['data_type']);
+              $this->_qill[$grouping][] = "$field[label] $op $qillValue";
             }
-            continue;
+            break;
 
           case 'ContactReference':
             $label = $value ? CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $value, 'sort_name') : '';
             $this->_where[$grouping][] = CRM_Contact_BAO_Query::buildClause($fieldName, $op, $value, 'String');
             $this->_qill[$grouping][] = $field['label'] . " $op $label";
-            continue;
+            break;
 
           case 'Int':
             if ($field['is_search_range'] && is_array($value)) {
@@ -451,7 +432,7 @@ SELECT label, value
               $this->_where[$grouping][] = CRM_Contact_BAO_Query::buildClause($fieldName, $op, $value, 'Integer');
               $this->_qill[$grouping][] = $field['label'] . " $op $value";
             }
-            continue;
+            break;
 
           case 'Boolean':
             if (strtolower($value) == 'yes' || strtolower($value) == strtolower(ts('Yes'))) {
@@ -464,12 +445,12 @@ SELECT label, value
             $this->_where[$grouping][] = CRM_Contact_BAO_Query::buildClause($fieldName, $op, $value, 'Integer');
             $value = $value ? ts('Yes') : ts('No');
             $this->_qill[$grouping][] = $field['label'] . " {$op} {$value}";
-            continue;
+            break;
 
           case 'Link':
             $this->_where[$grouping][] = CRM_Contact_BAO_Query::buildClause($fieldName, $op, $value, 'String');
             $this->_qill[$grouping][] = $field['label'] . " $op $value";
-            continue;
+            break;
 
           case 'Float':
             if ($field['is_search_range'] && is_array($value)) {
@@ -479,7 +460,7 @@ SELECT label, value
               $this->_where[$grouping][] = CRM_Contact_BAO_Query::buildClause($fieldName, $op, $value, 'Float');
               $this->_qill[$grouping][] = $field['label'] . " {$op} {$value}";
             }
-            continue;
+            break;
 
           case 'Money':
             if ($field['is_search_range'] && is_array($value)) {
@@ -495,12 +476,12 @@ SELECT label, value
               $this->_where[$grouping][] = CRM_Contact_BAO_Query::buildClause($fieldName, $op, $value, 'Float');
               $this->_qill[$grouping][] = $field['label'] . " {$op} {$value}";
             }
-            continue;
+            break;
 
           case 'Memo':
             $this->_where[$grouping][] = CRM_Contact_BAO_Query::buildClause($fieldName, $op, $value, 'String');
             $this->_qill[$grouping][] = "$field[label] $op $value";
-            continue;
+            break;
 
           case 'Date':
             $fromValue = CRM_Utils_Array::value('from', $value);
@@ -544,34 +525,13 @@ SELECT label, value
                 $this->_qill[$grouping][] = $field['label'] . ' <= ' . CRM_Utils_Date::customFormat($toDate);
               }
             }
-            continue;
+            break;
 
           case 'StateProvince':
           case 'Country':
-            if (!is_array($value)) {
-              $this->_where[$grouping][] = "$fieldName {$op} " . CRM_Utils_Type::escape($value, 'Int');
-              $this->_qill[$grouping][] = $field['label'] . " {$op} {$qillValue}";
-            }
-            else {
-              $sqlOP = ' AND ';
-              $sqlOPlabel = ts('match ALL');
-              foreach ($value as $k => $v) {
-                if ($v == 'CiviCRM_OP_OR') {
-                  $sqlOP = ' OR ';
-                  $sqlOPlabel = ts('match ANY');
-                  continue;
-                }
-                $sqlValue[] = "( $fieldName like '%" . CRM_Core_DAO::VALUE_SEPARATOR . $v . CRM_Core_DAO::VALUE_SEPARATOR . "%' ) ";
-              }
-
-              //if user select only 'CiviCRM_OP_OR' value
-              //of custom multi select field, then ignore this field.
-              if (!empty($sqlValue)) {
-                $this->_where[$grouping][] = " ( " . implode($sqlOP, $sqlValue) . " ) ";
-                $this->_qill[$grouping][] = "$field[label] $op $qillValue ( $sqlOPlabel )";
-              }
-            }
-            continue;
+            $this->_where[$grouping][] = "$fieldName {$op} " . CRM_Utils_Type::escape($value, 'Int');
+            $this->_qill[$grouping][] = $field['label'] . " {$op} {$qillValue}";
+            break;
 
           case 'File':
             if ( $op == 'IS NULL' || $op == 'IS NOT NULL' || $op == 'IS EMPTY' || $op == 'IS NOT EMPTY' ) {
@@ -586,7 +546,7 @@ SELECT label, value
               $this->_where[$grouping][] = CRM_Contact_BAO_Query::buildClause($fieldName, $op);
               $this->_qill[$grouping][] = $field['label'] . " {$op} ";
             }
-            continue;
+            break;
         }
       }
     }
index 2aa097f503290c6ceed37efaa1069bfccf616315..1b8e840aa22da624b8e0b0454e927a5cd4035582 100644 (file)
@@ -79,11 +79,12 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag {
   }
 
   /**
+   * Build a nested array from hierarchical tags. Supports infinite levels of nesting.
    * @param null $usedFor
    * @param bool $excludeHidden
    */
   function buildTree($usedFor = NULL, $excludeHidden = FALSE) {
-    $sql = "SELECT civicrm_tag.id, civicrm_tag.parent_id,civicrm_tag.name FROM civicrm_tag ";
+    $sql = "SELECT id, parent_id, name, description FROM civicrm_tag";
 
     $whereClause = array();
     if ($usedFor) {
@@ -101,42 +102,22 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag {
 
     $dao = CRM_Core_DAO::executeQuery($sql, CRM_Core_DAO::$_nullArray, TRUE, NULL, FALSE, FALSE);
 
-    $orphan = array();
+    $refs = array();
     while ($dao->fetch()) {
+      $thisref = &$refs[$dao->id];
+
+      $thisref['parent_id'] = $dao->parent_id;
+      $thisref['name'] = $dao->name;
+      $thisref['description'] = $dao->description;
+
       if (!$dao->parent_id) {
-        $this->tree[$dao->id]['name'] = $dao->name;
+        $this->tree[$dao->id] = &$thisref;
       }
       else {
-        if (array_key_exists($dao->parent_id, $this->tree)) {
-          $parent = &$this->tree[$dao->parent_id];
-          if (!isset($this->tree[$dao->parent_id]['children'])) {
-            $this->tree[$dao->parent_id]['children'] = array();
-          }
-        }
-        else {
-          //3rd level tag
-          if (!array_key_exists($dao->parent_id, $orphan)) {
-            $orphan[$dao->parent_id] = array('children' => array());
-          }
-          $parent = &$orphan[$dao->parent_id];
-        }
-        $parent['children'][$dao->id] = array('name' => $dao->name);
+        $refs[$dao->parent_id]['children'][$dao->id] = &$thisref;
       }
     }
-    if (sizeof($orphan)) {
-      //hang the 3rd level lists at the right place
-      foreach ($this->tree as & $level1) {
-        if (!isset($level1['children'])) {
-          continue;
-        }
 
-        foreach ($level1['children'] as $key => & $level2) {
-          if (array_key_exists($key, $orphan)) {
-            $level2['children'] = $orphan[$key]['children'];
-          }
-        }
-      }
-    }
   }
 
   /**
index a505ec9b22eb6839b07e3d017fa9cd3da199d571..1cdfb5fae8aa42399764ff9f37579182084881e9 100644 (file)
@@ -158,12 +158,8 @@ class CRM_Profile_Page_Listings extends CRM_Core_Page {
 
     foreach ($this->_fields as $name => $field) {
       if ((substr($name, 0, 6) == 'custom') && !empty($field['is_search_range'])) {
-        $from = CRM_Utils_Request::retrieve($name . '_from', 'String',
-          $this, FALSE, NULL, 'REQUEST'
-        );
-        $to = CRM_Utils_Request::retrieve($name . '_to', 'String',
-          $this, FALSE, NULL, 'REQUEST'
-        );
+        $from = CRM_Utils_Request::retrieve($name . '_from', 'String', $this);
+        $to = CRM_Utils_Request::retrieve($name . '_to', 'String', $this);
         $value = array();
         if ($from && $to) {
           $value['from'] = $from;
@@ -248,6 +244,10 @@ class CRM_Profile_Page_Listings extends CRM_Core_Page {
         if (!is_array($value)) {
           $value = trim($value);
         }
+        $operator = CRM_Utils_Request::retrieve($name . '_operator', 'String', $this);
+        if ($operator) {
+          $this->_params[$name . '_operator'] = $operator;
+        }
         $this->_params[$name] = $this->_fields[$name]['value'] = $value;
       }
     }
index 3148c536058f9e9538ae72670abd21aef5991d1c..dc88f47559b7b8f58b972092bc9dd4f52e2007b2 100644 (file)
@@ -217,7 +217,7 @@ class CRM_Utils_HttpClient {
    * @return bool
    */
   public function isRedirectSupported() {
-    return (ini_get('open_basedir') == '') && (ini_get('safe_mode') == 'Off' || ini_get('safe_mode') === FALSE);
+    return (ini_get('open_basedir') == '') && (ini_get('safe_mode') == 'Off' || ini_get('safe_mode') == '' || ini_get('safe_mode') === FALSE);
   }
 
 }
diff --git a/Civi/CiUtil/Arrays.php b/Civi/CiUtil/Arrays.php
new file mode 100644 (file)
index 0000000..359ad4c
--- /dev/null
@@ -0,0 +1,12 @@
+<?php
+namespace Civi\CiUtil;
+
+class Arrays {
+  static function collect($arr, $col) {
+    $r = array();
+    foreach ($arr as $k => $item) {
+      $r[$k] = $item[$col];
+    }
+    return $r;
+  }
+}
\ No newline at end of file
diff --git a/Civi/CiUtil/Command/AntagonistCommand.php b/Civi/CiUtil/Command/AntagonistCommand.php
new file mode 100644 (file)
index 0000000..9a71959
--- /dev/null
@@ -0,0 +1,67 @@
+<?php
+namespace Civi\CiUtil\Command;
+
+class AntagonistCommand {
+  static function main($argv) {
+    if (count($argv) != 3) {
+      print "usage: {$argv[0]} <TargetTest::testFunc> </path/to/suite>\n";
+      exit(1);
+    }
+    list ($program, $target, $suite) = $argv;
+
+    $candidateTests = \Civi\CiUtil\PHPUnitScanner::findTestsByPath(array($suite));
+//    $candidateTests = array(
+//      array('class' => 'CRM_Core_RegionTest', 'method' => 'testBlank'),
+//      array('class' => 'CRM_Core_RegionTest', 'method' => 'testDefault'),
+//      array('class' => 'CRM_Core_RegionTest', 'method' => 'testOverride'),
+//      array('class' => 'CRM_Core_RegionTest', 'method' => 'testAllTypes'),
+//    );
+    $antagonist = self::findAntagonist($target, $candidateTests);
+    if ($antagonist) {
+      print_r(array('found an antagonist' => $antagonist));
+    }
+    else {
+      print_r(array('found no antagonists'));
+    }
+  }
+
+  /**
+   * @param string $target e.g. "MyTest::testFoo"
+   * @param array $candidateTests list of strings (e.g. "MyTest::testFoo")
+   * @return array|null array contains keys:
+   *  - antagonist: array
+   *    - file: string
+   *    - class: string
+   *    - method: string
+   *  - expectedResults: array
+   *  - actualResults: array
+   */
+  static function findAntagonist($target, $candidateTests) {
+    //$phpUnit = new \Civi\CiUtil\EnvTestRunner('./scripts/phpunit', 'EnvTests');
+    $phpUnit = new \Civi\CiUtil\EnvTestRunner('phpunit', 'tests/phpunit/EnvTests.php');
+    $expectedResults = $phpUnit->run(array($target));
+    print_r(array('$expectedResults' => $expectedResults));
+
+    foreach ($candidateTests as $candidateTest) {
+      $candidateTestName = $candidateTest['class'] . '::' . $candidateTest['method'];
+      if ($candidateTestName == $target) {
+        continue;
+      }
+      $actualResults = $phpUnit->run(array(
+        $candidateTestName,
+        $target,
+      ));
+      print_r(array('$actualResults' => $actualResults));
+      foreach ($expectedResults as $testName => $expectedResult) {
+        if ($actualResults[$testName] != $expectedResult) {
+          return array(
+            'antagonist' => $candidateTest,
+            'expectedResults' => $expectedResults,
+            'actualResults' => $actualResults,
+          );
+        }
+      }
+    }
+    return NULL;
+  }
+}
\ No newline at end of file
diff --git a/Civi/CiUtil/Command/CompareCommand.php b/Civi/CiUtil/Command/CompareCommand.php
new file mode 100644 (file)
index 0000000..494e909
--- /dev/null
@@ -0,0 +1,42 @@
+<?php
+namespace Civi\CiUtil\Command;
+
+class CompareCommand {
+  static function main($argv) {
+    if (empty($argv[1])) {
+      echo "summary: Compares the output of different test runs\n";
+      echo "usage: phpunit-compare <json-file1> [<json-file2>...]\n";
+      exit(1);
+    }
+
+
+    $suites = array(); // array('file' => string, 'results' => array)
+    for ($i = 1; $i < count($argv); $i++) {
+      $suites[$i] = array(
+        'file' => $argv[$i],
+        'results' => \Civi\CiUtil\PHPUnitParser::parseJsonResults(file_get_contents($argv[$i]))
+      );
+    }
+
+    $tests = array(); // array(string $name)
+    foreach ($suites as $suiteName => $suite) {
+      $tests = array_unique(array_merge(
+        $tests,
+        array_keys($suite['results'])
+      ));
+    }
+    sort($tests);
+
+    $printer = new \Civi\CiUtil\ComparisonPrinter(\Civi\CiUtil\Arrays::collect($suites, 'file'));
+    foreach ($tests as $test) {
+      $values = array();
+      foreach ($suites as $suiteName => $suite) {
+        $values[] = isset($suite['results'][$test]) ? $suite['results'][$test] : 'MISSING';
+      }
+
+      if (count(array_unique($values)) > 1) {
+        $printer->printRow($test, $values);
+      }
+    }
+  }
+}
diff --git a/Civi/CiUtil/Command/LsCommand.php b/Civi/CiUtil/Command/LsCommand.php
new file mode 100644 (file)
index 0000000..b4af978
--- /dev/null
@@ -0,0 +1,12 @@
+<?php
+namespace Civi\CiUtil\Command;
+
+class LsCommand {
+  static function main($argv) {
+    $paths = $argv;
+    array_shift($paths);
+    foreach (\Civi\CiUtil\PHPUnitScanner::findTestsByPath($paths) as $test) {
+      printf("%s %s %s\n", $test['file'], $test['class'], $test['method']);
+    }
+  }
+}
\ No newline at end of file
diff --git a/Civi/CiUtil/ComparisonPrinter.php b/Civi/CiUtil/ComparisonPrinter.php
new file mode 100644 (file)
index 0000000..60f5f2c
--- /dev/null
@@ -0,0 +1,46 @@
+<?php
+namespace Civi\CiUtil;
+
+class ComparisonPrinter {
+  var $headers;
+  var $hasHeader = FALSE;
+
+  function __construct($headers) {
+    $this->headers = $headers;
+  }
+
+  function printHeader() {
+    if ($this->hasHeader) {
+      return;
+    }
+
+    ## LEGEND
+    print "LEGEND\n";
+    $i = 1;
+    foreach ($this->headers as $header) {
+      printf("% 2d: %s\n", $i, $header);
+      $i++;
+    }
+    print "\n";
+
+    ## HEADER
+    printf("%-90s ", 'TEST NAME');
+    $i = 1;
+    foreach ($this->headers as $header) {
+      printf("%-10d ", $i);
+      $i++;
+    }
+    print "\n";
+
+    $this->hasHeader = TRUE;
+  }
+
+  function printRow($test, $values) {
+    $this->printHeader();
+    printf("%-90s ", $test);
+    foreach ($values as $value) {
+      printf("%-10s ", $value);
+    }
+    print "\n";
+  }
+}
\ No newline at end of file
diff --git a/Civi/CiUtil/EnvTestRunner.php b/Civi/CiUtil/EnvTestRunner.php
new file mode 100644 (file)
index 0000000..d16bd84
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+namespace Civi\CiUtil;
+
+/**
+ * Parse phpunit result files
+ */
+class EnvTestRunner {
+  protected $phpunit;
+  protected $envTestSuite;
+
+  function __construct($phpunit = "phpunit", $envTestSuite = 'EnvTests') {
+    $this->phpunit = $phpunit;
+    $this->envTestSuite = $envTestSuite;
+  }
+
+  /**
+   * @param array $tests
+   * @return array (string $testName => string $status)
+   */
+  public function run($tests) {
+    $envTests = implode(' ', $tests);
+    $jsonFile = tempnam(sys_get_temp_dir(), 'phpunit-json-');
+    unlink($jsonFile);
+    $command = "env PHPUNIT_TESTS=\"$envTests\" {$this->phpunit} --log-json $jsonFile {$this->envTestSuite}";
+    echo "Running [$command]\n";
+    system($command);
+    $results = PHPUnitParser::parseJsonResults(file_get_contents($jsonFile));
+    unlink($jsonFile);
+    return $results;
+  }
+}
\ No newline at end of file
diff --git a/Civi/CiUtil/PHPUnitParser.php b/Civi/CiUtil/PHPUnitParser.php
new file mode 100644 (file)
index 0000000..bc28048
--- /dev/null
@@ -0,0 +1,34 @@
+<?php
+namespace Civi\CiUtil;
+
+/**
+ * Parse phpunit result files
+ */
+class PHPUnitParser {
+  /**
+   * @param string $content phpunit streaming JSON
+   * @return array(string "$class::$func" => $status)
+   */
+  protected static function parseJsonStream($content) {
+    $content = '['
+      . strtr($content, array("}{" => "},{"))
+      . ']';
+    return json_decode($content, TRUE);
+  }
+
+  /**
+   * @param string $content json stream
+   * @return array (string $testName => string $status)
+   */
+  public static function parseJsonResults($content) {
+    $records = self::parseJsonStream($content);
+    $results = array();
+    foreach ($records as $r) {
+      if ($r['event'] == 'test') {
+        $results[$r['test']] = $r['status'];
+      }
+    }
+    return $results;
+  }
+
+}
\ No newline at end of file
diff --git a/Civi/CiUtil/PHPUnitScanner.php b/Civi/CiUtil/PHPUnitScanner.php
new file mode 100644 (file)
index 0000000..b09de45
--- /dev/null
@@ -0,0 +1,91 @@
+<?php
+namespace Civi\CiUtil;
+use Symfony\Component\Finder\Finder;
+
+/**
+ * Search for PHPUnit test cases
+ */
+class PHPUnitScanner {
+  /**
+   * @return array<string> class names
+   */
+  static function _findTestClasses($path) {
+//    print_r(array(
+//      'loading' => $path,
+//      get_included_files()
+//    ));
+
+    $origClasses = get_declared_classes();
+    require_once $path;
+    $newClasses = get_declared_classes();
+
+    return preg_grep('/Test$/', array_diff(
+      $newClasses,
+      $origClasses
+    ));
+  }
+
+  /**
+   * @return array (string $file => string $class)
+   */
+  static function findTestClasses($paths) {
+    $testClasses = array();
+    $finder = new Finder();
+
+    foreach ($paths as $path) {
+      if (is_dir($path)) {
+        foreach ($finder->files()->in($paths)->name('*Test.php') as $file) {
+          $testClass = self::_findTestClasses((string) $file);
+          if (count($testClass) == 1) {
+            $testClasses[(string) $file] = array_shift($testClass);
+          }
+          elseif (count($testClass) > 1) {
+            throw new \Exception("Too many classes in $file");
+          }
+          else {
+            throw new \Exception("Too few classes in $file");
+          }
+        }
+      }
+      elseif (is_file($path)) {
+        $testClass = self::_findTestClasses($path);
+        if (count($testClass) == 1) {
+          $testClasses[$path] = array_shift($testClass);
+        }
+        elseif (count($testClass) > 1) {
+          throw new \Exception("Too many classes in $path");
+        }
+        else {
+          throw new \Exception("Too few classes in $path");
+        }
+      }
+    }
+
+    return $testClasses;
+  }
+
+  /**
+   * @param array $testClasses
+   * @return array each element is an array with keys:
+   *   - file: string
+   *   - class: string
+   *   - method: string
+   */
+  static function findTestsByPath($paths) {
+    $r = array();
+    $testClasses = self::findTestClasses($paths);
+    foreach ($testClasses as $testFile => $testClass) {
+      $clazz = new \ReflectionClass($testClass);
+      foreach ($clazz->getMethods() as $method) {
+        if (preg_match('/^test/', $method->name)) {
+          $r[] = array(
+            'file' => $testFile,
+            'class' => $testClass,
+            'method' => $method->name
+          );
+        }
+      }
+    }
+    return $r;
+  }
+}
\ No newline at end of file
index 050732ab45974e72c73778e76b22b9baeb93a355..00dda45966b09496bef53c9cbbb1d3ebca7a0a86 100644 (file)
@@ -1327,11 +1327,11 @@ input.crm-form-entityref {
 
 #crm-container input.submit-link {
   color: #285286;
-  background-color: transparent;
+  background: none transparent;
   border: none;
   cursor: pointer;
-  cursor: hand;
   margin: 0em -0.5em 0em -0.5em;
+  text-shadow: none;
 }
 
 .crm-container .underline-effect {
@@ -2942,6 +2942,7 @@ div.grippie {
   opacity: .7;
   position: relative;
   top: 2px;
+  padding: 0;
 }
 
 div.crm-accordion-header a.helpicon {
index 1841cb459db68f62ac441b0e8323d7ba22be1bd1..d9504a7943d86d0a8b0827df4c997bb9a059e377 100644 (file)
       }
     };
 
+    $scope.isValidName = function(name) {
+      return !name || name.match(/^[a-zA-Z0-9_]+$/);
+    };
+
     $scope.getWorkflowName = function(activitySet) {
       var result = 'Unknown';
       _.each($scope.workflows, function(value, key) {
index 8e84a394523c854e168b7318313d686a299a2330..3a24b86ee88380e9abdb557cb3844efb07fbdc92 100644 (file)
@@ -34,12 +34,14 @@ The original form used table layout; don't know if we have an alternative, CSS-b
         name="caseTypeName"
         ng-model="caseType.name"
         ng-disabled="locks.caseTypeName"
-        ng-pattern="/^[a-zA-Z0-9_]+$/"
         required
         class="big crm-form-text"/>
 
       <a crm-ui-lock binding="locks.caseTypeName"></a>
 
+      <div ng-show="!isValidName(caseType.name)">
+        <em>WARNING: The case type name includes deprecated characters.</em>
+      </div>
       <div ng-show="caseType.id && !locks.caseTypeName">
         <em>WARNING: If any external files or programs reference the old "Name", then they must be updated manually.</em>
       </div>
index e30695981dd55140968f3cb65b93ee0b0f77cc21..f22a587bfe4d0f8f96626798f3d9d3f4ee353136 100644 (file)
   {/foreach}
 {/foreach}
 <div id="case_custom_edit"></div>
-
-{*currently delete is available only for tab custom data*}
-{if $groupId}
-<script type="text/javascript">
-  {literal}
-  function hideStatus(valueID, groupID) {
-    cj('#statusmessg_' + groupID + '_' + valueID).hide( );
-  }
-
-  function showDelete(valueID, elementID, groupID, contactID) {
-    var confirmMsg = '{/literal}{ts escape='js'}Are you sure you want to delete this record?{/ts}{literal} &nbsp; <a href="#" onclick="deleteCustomValue( ' + valueID + ',\'' + elementID + '\',' + groupID + ',' + contactID + ' ); return false;" style="text-decoration: underline;">{/literal}{ts escape='js'}Yes{/ts}{literal}</a>&nbsp;&nbsp;&nbsp;<a href="#" onclick="hideStatus( ' + valueID + ', ' +  groupID + ' ); return false;" style="text-decoration: underline;">{/literal}{ts escape='js'}No{/ts}{literal}</a>';
-    cj('tr#statusmessg_' + groupID + '_' + valueID).show( ).children().find('span').html( confirmMsg );
-  }
-
-  function deleteCustomValue( valueID, elementID, groupID, contactID ) {
-    var postUrl = {/literal}"{crmURL p='civicrm/ajax/customvalue' h=0 }"{literal};
-    var request = cj.ajax({
-      type: "POST",
-      data:  "valueID=" + valueID + "&groupID=" + groupID +"&contactId=" + contactID + "&key={/literal}{crmKey name='civicrm/ajax/customvalue'}{literal}",
-      url: postUrl,
-      success: function(html){
-        cj('#'+ elementID).hide();
-        hideStatus(valueID, groupID);
-        var element = cj( '.ui-tabs-nav #tab_custom_' + groupID + ' a' );
-        cj(element).html(cj(element).attr('title') + ' ('+ html+') ');
-      }
-    });
-    CRM.status({success: '{/literal}{ts escape="js"}Record Deleted{/ts}{literal}'}, request);
-  }
-  {/literal}
-</script>
-{/if}
-
index 8923334e0188167c78d4691f382238f5b6cfbd17..732830e129a1aedba2f028c6e68ae0bd8937f282 100644 (file)
 
   <script type="text/javascript" >
   CRM.$(function($) {
+    var $form = $("#{/literal}{$form.formName}{literal}");
     var action = "{/literal}{$action}{literal}";
 
     $('.crm-accordion-body').each( function() {
       return true;
     });
     {/literal}{/if}{literal}
+
+    // Handle delete of multi-record custom data
+    $form.on('click', '.crm-custom-value-del', function(e) {
+      e.preventDefault();
+      var $el = $(this),
+        msg = '{/literal}{ts escape="js"}The record will be deleted immediately. This action cannot be undone.{/ts}{literal}';
+      CRM.confirm({title: $el.attr('title'), message: msg})
+        .on('crmConfirm:yes', function() {
+          var url = CRM.url('civicrm/ajax/customvalue');
+          var request = $.post(url, $el.data('post'));
+          CRM.status({success: '{/literal}{ts escape="js"}Record Deleted{/ts}{literal}'}, request);
+          var addClass = '.add-more-link-' + $el.data('post').groupID;
+          $el.closest('div.crm-custom-accordion').remove();
+          $('div' + addClass).last().show();
+        });
+    });
   });
 
 </script>
index d0ea6b03dce584881db894342edfd5d8a518702f..ba1c641c18c47cd2885cfee9f8789d68d9f5523f 100644 (file)
  +--------------------------------------------------------------------+
 *}
 
-<script type="text/javascript">var showTab = Array();</script>
 {foreach from=$groupTree item=cd_edit key=group_id}
   {if $cd_edit.is_multiple eq 1}
     {assign var=tableID value=$cd_edit.table_id}
     {assign var=divName value=$group_id|cat:"_$tableID"}
     <div></div>
-    <div id="{$cd_edit.name|cat:'_$divName'}"
+    <div
      class="crm-accordion-wrapper crm-custom-accordion {if $cd_edit.collapse_display and !$skipTitle}collapsed{/if}">
   {else}
     <div id="{$cd_edit.name}"
       {if $cd_edit.is_multiple eq 1}
         {if $cd_edit.table_id}
           <table class="no-border">
-            <tr id="statusmessg_{$group_id|cat:"_$tableID"}" class="hiddenElement">
-              <td><span class="success-status"></span></td>
-            </tr>
             <tr>
-              <div class="crm-submit-buttons">
-                <a href="#"
-                   onclick="showDelete( {$tableID}, '{$cd_edit.name}_{$group_id|cat:"_$tableID"}', {$group_id}, {$contactId} ); return false;"
-                   class="button delete-button" title="{ts 1=$cv_edit.title}Delete this %1 record{/ts}">
-                  <span><div class="icon delete-icon"></div>{ts}Delete{/ts}</span>
-                </a>
-              </div>
+              <a href="#" class="crm-hover-button crm-custom-value-del" title="{ts 1=$cd_edit.title}Delete %1{/ts}"
+               data-post='{ldelim}"valueID": "{$tableID}", "groupID": "{$group_id}", "contactId": "{$contactId}", "key": "{crmKey name='civicrm/ajax/customvalue'}"{rdelim}'>
+                <span class="icon delete-icon"></span> {ts}Delete{/ts}
+              </a>
               <!-- crm-submit-buttons -->
             </tr>
           </table>
   {/foreach}
 
   {include file="CRM/common/customData.tpl"}
-  <script type="text/javascript">
-    {literal}
-
-    function hideStatus(valueID, groupID) {
-      cj('#statusmessg_' + groupID + '_' + valueID).hide();
-    }
-
-    function showDelete(valueID, elementID, groupID, contactID) {
-      var confirmMsg = '{/literal}{ts escape='js'}Are you sure you want to delete this record?{/ts}{literal} &nbsp; <a href="#" onclick="deleteCustomValue( ' + valueID + ',\'' + elementID + '\',' + groupID + ',' + contactID + ' ); return false;" style="text-decoration: underline;">{/literal}{ts escape='js'}Yes{/ts}{literal}</a>&nbsp;&nbsp;&nbsp;<a href="#" onclick="hideStatus( ' + valueID + ', ' + groupID + ' ); return false;" style="text-decoration: underline;">{/literal}{ts escape='js'}No{/ts}{literal}</a>';
-      cj('tr#statusmessg_' + groupID + '_' + valueID).show().children().find('span').html(confirmMsg);
-    }
-
-    function deleteCustomValue(valueID, elementID, groupID, contactID) {
-      var postUrl = {/literal}"{crmURL p='civicrm/ajax/customvalue' h=0 }"{literal},
-      request = cj.ajax({
-        type: "POST",
-        data: "valueID=" + valueID + "&groupID=" + groupID + "&contactId=" + contactID + "&key={/literal}{crmKey name='civicrm/ajax/customvalue'}{literal}",
-        url: postUrl,
-        success: function (html) {
-          cj('#' + elementID).hide();
-          hideStatus(valueID, groupID);
-          var element = cj('.ui-tabs-nav #tab_custom_' + groupID + ' a');
-          cj(element).html(cj(element).attr('title') + ' (' + html + ') ');
-        }
-      });
-      CRM.status({success: '{/literal}{ts escape="js"}Record Deleted{/ts}{literal}'}, request);
-    }
-
-    {/literal}
-  </script>
 
   {include file="CRM/Form/attachmentjs.tpl"}
index 9a091dd1b990dc102c9533e3885d999b44ec874a..6b302739c5d63d35f39f110503450b0e37ca9d0f 100644 (file)
         {include file="CRM/common/formButtons.tpl" location="top" buttonStyle="width:80px; text-align:center;"}
       </div>
       <div class="crm-submit-buttons reset-advanced-search">
-        <a href="{crmURL p='civicrm/contact/search/advanced' q='reset=1'}" id="resetAdvancedSearch" class="button" style="width:70px; text-align:center;"><span>{ts}Reset Form{/ts}</span></a>
+        <a href="{crmURL p='civicrm/contact/search/advanced' q='reset=1'}" id="resetAdvancedSearch" class="crm-hover-button" title="{ts}Clear all search criteria{/ts}">
+          <span class="icon ui-icon-circle-close"></span>
+          {ts}Reset Form{/ts}
+        </a>
       </div>
     </td>
   </tr>
index 0960fae327c32844ee06f925400530ad3bd94fc3..1a4677d58f43ad91de6c7b1438d9f487a69a5f44 100644 (file)
     <div class="messages help">{$cd_edit.help_post}</div>
   {/if}
   {if $cd_edit.is_multiple and ( ( $cd_edit.max_multiple eq '' )  or ( $cd_edit.max_multiple > 0 and $cd_edit.max_multiple > $cgCount ) ) }
-    <div id="add-more-link-{$cgCount}" class="add-more-link-{$group_id}-{$cgCount}"><a href="#" onclick="CRM.buildCustomData('{$cd_edit.extends}',{if $cd_edit.subtype}'{$cd_edit.subtype}'{else}'{$cd_edit.extends_entity_column_id}'{/if}, '', {$cgCount}, {$group_id}, true ); return false;">{ts 1=$cd_edit.title}Add another %1 record{/ts}</a></div>
+    <div id="add-more-link-{$cgCount}" class="add-more-link-{$group_id} add-more-link-{$group_id}-{$cgCount}">
+      <a href="#" class="crm-hover-button" onclick="CRM.buildCustomData('{$cd_edit.extends}',{if $cd_edit.subtype}'{$cd_edit.subtype}'{else}'{$cd_edit.extends_entity_column_id}'{/if}, '', {$cgCount}, {$group_id}, true ); return false;">
+        <span class="icon ui-icon-circle-plus"></span>
+        {ts 1=$cd_edit.title}Another %1 record{/ts}
+      </a>
+    </div>
   {/if}
 {else}
   {foreach from=$groupTree item=cd_edit key=group_id name=custom_sets}
@@ -61,7 +66,7 @@
      <div class="custom-group custom-group-{$cd_edit.name} crm-accordion-wrapper {if $cd_edit.collapse_display and !$skipTitle}collapsed{/if}">
       {if !$skipTitle}
       <div class="crm-accordion-header">
-        {$cd_edit.title}
+        {$cd_edit.title} {$cgCount}
        </div><!-- /.crm-accordion-header -->
       {/if}
       <div class="crm-accordion-body">
           <em>{ts 1=$cd_edit.title}Click "Edit Contact" to add more %1 records{/ts}</em>
         </div>
       {else}
-        <div id="add-more-link-{$cgCount}"><a href="#" onclick="CRM.buildCustomData('{$cd_edit.extends}',{if $cd_edit.subtype}'{$cd_edit.subtype}'{else}'{$cd_edit.extends_entity_column_id}'{/if}, '', {$cgCount}, {$group_id}, true ); return false;">{ts 1=$cd_edit.title}Add another %1 record{/ts}</a></div>       
+        <div id="add-more-link-{$cgCount}">
+          <a href="#" class="crm-hover-button" onclick="CRM.buildCustomData('{$cd_edit.extends}',{if $cd_edit.subtype}'{$cd_edit.subtype}'{else}'{$cd_edit.extends_entity_column_id}'{/if}, '', {$cgCount}, {$group_id}, true ); return false;">
+            <span class="icon ui-icon-circle-plus"></span>
+            {ts 1=$cd_edit.title}Another %1 record{/ts}
+          </a>
+        </div>
       {/if}
     {/if}
     {/if}
diff --git a/templates/CRM/Custom/Form/MultiValueSearch.js.tpl b/templates/CRM/Custom/Form/MultiValueSearch.js.tpl
new file mode 100644 (file)
index 0000000..a0c7de7
--- /dev/null
@@ -0,0 +1,39 @@
+{*
+ +--------------------------------------------------------------------+
+ | CiviCRM version 4.5                                                |
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC (c) 2004-2014                                |
+ +--------------------------------------------------------------------+
+ | This file is a part of CiviCRM.                                    |
+ |                                                                    |
+ | CiviCRM is free software; you can copy, modify, and distribute it  |
+ | under the terms of the GNU Affero General Public License           |
+ | Version 3, 19 November 2007 and the CiviCRM Licensing Exception.   |
+ |                                                                    |
+ | CiviCRM is distributed in the hope that it will be useful, but     |
+ | WITHOUT ANY WARRANTY; without even the implied warranty of         |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.               |
+ | See the GNU Affero General Public License for more details.        |
+ |                                                                    |
+ | You should have received a copy of the GNU Affero General Public   |
+ | License and the CiviCRM Licensing Exception along                  |
+ | with this program; if not, contact CiviCRM LLC                     |
+ | at info[AT]civicrm[DOT]org. If you have questions about the        |
+ | GNU Affero General Public License or the licensing of CiviCRM,     |
+ | see the CiviCRM license FAQ at http://civicrm.org/licensing        |
+ +--------------------------------------------------------------------+
+*}
+{literal}
+  <script type="text/javascript">
+    CRM.$(function($) {
+      function showHideOperator() {
+        var val = $(this).val();
+        $(this).siblings("span.crm-multivalue-search-op").toggle(!!(val && val.length > 1));
+      }
+      $("span.crm-multivalue-search-op").siblings('select')
+        .off('.crmMultiValue')
+        .on('change.crmMultiValue', showHideOperator)
+        .each(showHideOperator);
+    });
+  </script>
+{/literal}
index 2dd5b37f380cc50c876bd1d6a9d96fe2b5dad262..792e6af02c01c128aedf8936a50be7c91459ba16 100644 (file)
     <div class="crm-accordion-body">
     <table class="form-layout-compressed">
     {foreach from=$cd_edit.fields item=element key=field_id}
-      {assign var="element_name" value='custom_'|cat:$field_id}
-      {if $element.options_per_line != 0}
-         <tr>
-           <td class="label">{$form.$element_name.label}</td>
-           <td>
-            {assign var="count" value="1"}
-            {strip}
-            <table class="form-layout-compressed">
-             <tr>
-                {* sort by fails for option per line. Added a variable to iterate through the element array*}
-                {assign var="index" value="1"}
-                {foreach name=outer key=key item=item from=$form.$element_name}
-                {if $index < 10} {* Hack to skip QF field properties that are not checkbox elements. *}
-                    {assign var="index" value=`$index+1`}
-                {else}
-                    {if $element.html_type EQ 'CheckBox' AND  $smarty.foreach.outer.last EQ 1} {* Put 'match ANY / match ALL' checkbox in separate row. *}
-                        </tr>
-                        <tr>
-                        <td class="op-checkbox" colspan="{$element.options_per_line}" style="padding-top: 0px;">{$form.$element_name.$key.html}</td>
-                    {else}
-                        <td class="labels font-light">{$form.$element_name.$key.html}</td>
-                        {if $count EQ $element.options_per_line}
-                          </tr>
-                          <tr>
-                          {assign var="count" value="1"}
-                        {else}
-                          {assign var="count" value=`$count+1`}
-                        {/if}
-                    {/if}
-                {/if}
-                {/foreach}
-             </tr>
-            </table>
-            {/strip}
-           </td>
-         </tr>
-        {else}
             {assign var="type" value=`$element.html_type`}
             {assign var="element_name" value='custom_'|cat:$field_id}
+            {assign var="operator_name" value='custom_'|cat:$field_id|cat:'_operator'}
             {if $element.is_search_range}
                 {assign var="element_name_from" value=$element_name|cat:"_from"}
                 {assign var="element_name_to" value=$element_name|cat:"_to"}
                 {elseif $element.skip_calendar NEQ true }
                     {include file="CRM/common/jcalendar.tpl" elementName=$element_name}
                 {/if}
+                {if !empty($form.$operator_name)}
+                  <span class="crm-multivalue-search-op" for="{$element_name}">{$form.$operator_name.html}</span>
+                  {assign var="add_multivalue_js" value=true}
+                {/if}
             {/if}
             {if $element.html_type eq 'Autocomplete-Select'}
                 {if $element.data_type eq 'ContactReference'}
             {/if}
             </td>
           </tr>
-      {/if}
       {/foreach}
      </table>
     </div><!-- /.crm-accordion-body -->
   </div><!-- /.crm-accordion-wrapper -->
 
 {/foreach}
+  {if !empty($add_multivalue_js)}
+    {include file="CRM/Custom/Form/MultiValueSearch.js.tpl"}
+  {/if}
 {/if}
 
index 28474618b50ed88637cc4d13e4b020c9260f4e62..66783eaf8feac9b5961d1abef8f9525b645298e5 100644 (file)
@@ -25,6 +25,7 @@
 *}
 {* Custom Data view mode*}
 {assign var="showEdit" value=1}
+{assign var="rowCount" value=1}
 {foreach from=$viewCustomData item=customValues key=customGroupId}
   {foreach from=$customValues item=cd_edit key=cvID}
 {if $multiRecordDisplay neq 'single'}
           <div class="crm-accordion-wrapper {if $cd_edit.collapse_display eq 0 or $skipTitle} {else}collapsed{/if}">
             {if !$skipTitle}
               <div class="crm-accordion-header">
-                {$cd_edit.title}
+                {$cd_edit.title} {$rowCount}
               </div>
             {/if}
             <div class="crm-accordion-body">
               {if $groupId and $cvID and $editCustomData}
                 <div class="crm-submit-buttons">
-                  <a href="#"
-                     onclick="showDelete( {$cvID}, '{$cd_edit.name}_{$index}', {$customGroupId}, {$contactId} ); return false;"
-                     class="button delete-button" title="{ts 1=$cd_edit.title}Delete this %1 record{/ts}">
-                    <span><div class="icon delete-icon"></div>{ts}Delete{/ts}</span>
+                  <a href="#" class="crm-hover-button crm-custom-value-del"
+                     data-post='{ldelim}"valueID": "{$cvID}", "groupID": "{$customGroupId}", "contactId": "{$contactId}", "key": "{crmKey name='civicrm/ajax/customvalue'}"{rdelim}'
+                     title="{ts 1=$cd_edit.title|cat:" `$rowCount`"}Delete %1{/ts}">
+                    <span class="icon delete-icon"></span> {ts}Delete{/ts}
                   </a>
                 </div>
               {/if}
                   </tr>
                 </table>
               {/foreach}
+              {assign var="rowCount" value=$rowCount+1}
             </div>
             <!-- end of body -->
             <div class="clear"></div>
 {if $groupId}
   <script type="text/javascript">
     {literal}
-    function hideStatus(valueID, groupID) {
-      cj('#statusmessg_' + groupID + '_' + valueID).hide();
-    }
-    function showDelete(valueID, elementID, groupID, contactID) {
-      var confirmMsg = '{/literal}{ts escape='js'}Are you sure you want to delete this record?{/ts}{literal} &nbsp; <a href="#" onclick="deleteCustomValue( ' + valueID + ',\'' + elementID + '\',' + groupID + ',' + contactID + ' ); return false;" style="text-decoration: underline;">{/literal}{ts escape='js'}Yes{/ts}{literal}</a>&nbsp;&nbsp;&nbsp;<a href="#" onclick="hideStatus( ' + valueID + ', ' + groupID + ' ); return false;" style="text-decoration: underline;">{/literal}{ts escape='js'}No{/ts}{literal}</a>';
-      cj('tr#statusmessg_' + groupID + '_' + valueID).show().children().find('span').html(confirmMsg);
-    }
-    function deleteCustomValue(valueID, elementID, groupID, contactID) {
-      var postUrl = {/literal}"{crmURL p='civicrm/ajax/customvalue' h=0 }"{literal},
-      request = cj.ajax({
-        type: "POST",
-        data: "valueID=" + valueID + "&groupID=" + groupID + "&contactId=" + contactID + "&key={/literal}{crmKey name='civicrm/ajax/customvalue'}{literal}",
-        url: postUrl,
-        success: function (html) {
-          cj('#' + elementID).hide();
-          hideStatus(valueID, groupID);
-          var element = cj('.ui-tabs-nav #tab_custom_' + groupID + ' a');
-          cj(element).html(cj(element).attr('title') + ' (' + html + ') ');
-        }
+    CRM.$(function($) {
+      // Handle delete of multi-record custom data
+      $('#crm-container')
+        .off('.customValueDel')
+        .on('click.customValueDel', '.crm-custom-value-del', function(e) {
+          e.preventDefault();
+          var $el = $(this),
+            msg = '{/literal}{ts escape="js"}The record will be deleted immediately. This action cannot be undone.{/ts}{literal}';
+          CRM.confirm({title: $el.attr('title'), message: msg})
+            .on('crmConfirm:yes', function() {
+              var url = CRM.url('civicrm/ajax/customvalue');
+              var request = $.post(url, $el.data('post'))
+                .done(CRM.refreshParent($el));
+              CRM.status({success: '{/literal}{ts escape="js"}Record Deleted{/ts}{literal}'}, request);
+            });
+        });
       });
-      CRM.status({success: '{/literal}{ts escape="js"}Record Deleted{/ts}{literal}'}, request);
-    }
     {/literal}
   </script>
 {/if}
index 110c10d4917543a4e1bd883a988c468e7c59f5ef..9cb83280cb9780b6b402d1786696427198055e7e 100644 (file)
@@ -40,6 +40,7 @@
         {continue}
       {/if}
       {assign var=n value=$field.name}
+      {assign var="operator_name" value=$n|cat:'_operator'}
       {if $field.is_search_range}
         {assign var=from value=$field.name|cat:'_from'}
         {assign var=to value=$field.name|cat:'_to'}
               &nbsp;&nbsp;{$form.$to.label}&nbsp;&nbsp;{include file="CRM/common/jcalendar.tpl" elementName=$to}</td>
           </tr>
         {/if}
-      {elseif $field.options_per_line}
-        <tr>
-          <td class="option-label">{$form.$n.label}</td>
-          <td>
-            {assign var="count" value="1"}
-            {strip}
-              <table class="form-layout-compressed">
-              <tr>
-              {* sort by fails for option per line. Added a variable to iterate through the element array*}
-                {assign var="index" value="1"}
-                {foreach name=outer key=key item=item from=$form.$n}
-                  {if $index < 10} {* Hack to skip QF field properties that are not checkbox elements. *}
-                    {assign var="index" value=`$index+1`}
-                  {else}
-                    {if $field.html_type EQ 'CheckBox' AND  $smarty.foreach.outer.last EQ 1} {* Put 'match ANY / match ALL' checkbox in separate row. *}
-                    </tr>
-                    <tr>
-                      <td class="op-checkbox" colspan="{$field.options_per_line}" style="padding-top: 0px;">{$form.$n.$key.html}</td>
-                      {else}
-                      <td class="labels font-light">{$form.$n.$key.html}</td>
-                      {if $count EQ $field.options_per_line}
-                      </tr>
-                      <tr>
-                        {assign var="count" value="1"}
-                      {else}
-                        {assign var="count" value=`$count+1`}
-                      {/if}
-                    {/if}
-                  {/if}
-                {/foreach}
-              </tr>
-              </table>
-            {/strip}
-          </td>
-        </tr>
       {else}
         <tr>
           <td class="label">
               {else}
                 {$form.$n.html}
               {/if}
-              {if $field.html_type eq 'Autocomplete-Select'}
-                {if $field.data_type eq 'ContactReference'}
-                  {include file="CRM/Custom/Form/ContactReference.tpl" element_name = $n}
-                {/if}
+              {if $field.html_type eq 'Autocomplete-Select' and $field.data_type eq 'ContactReference'}
+                {include file="CRM/Custom/Form/ContactReference.tpl" element_name = $n}
+              {/if}
+              {if !empty($form.$operator_name)}
+                <span class="crm-multivalue-search-op" for="{$n}">{$form.$operator_name.html}</span>
+                {assign var="add_multivalue_js" value=true}
               {/if}
             </td>
           {/if}
     });
   </script>
 {/literal}
+
+{if !empty($add_multivalue_js)}
+  {include file="CRM/Custom/Form/MultiValueSearch.js.tpl"}
+{/if}
index 834b586fc84e0b3450d3f93d9e41060896dd06d8..9dca5a9c279cc8df363617082d1479ceafe3dd90 100644 (file)
   #tagtree .highlighted > label {
     background-color: #FEFD7B;
   }
+  #tagtree .helpicon ins {
+    display: none;
+  }
+  #tagtree ins.jstree-icon {
+    cursor: pointer;
+  }
 </style>
 <script type="text/javascript">
   (function($, _){{/literal}
 
       //load js tree.
       $("#tagtree").jstree({
-        "plugins" : ["themes", "html_data"],
-        "themes": {"url": CRM.config.resourceBase + 'packages/jquery/plugins/jstree/themes/default/style.css'}
+        plugins : ["themes", "html_data"],
+        themes: {
+          "theme": 'classic',
+          "dots": false,
+          "icons": false,
+          "url": CRM.config.resourceBase + 'packages/jquery/plugins/jstree/themes/classic/style.css'
+        }
       });
 
       {/literal}
 <div id="Tag" class="view-content">
   <h3>{if !$hideContext}{ts}Tags{/ts}{/if}</h3>
   <div id="tagtree">
-    <ul class="tree">
-    {foreach from=$tree item="node" key="id"}
-      <li id="tag_{$id}">
-        {if ! $node.children}<input name="tagList[{$id}]" id="check_{$id}" type="checkbox" {if $tagged[$id]}checked="checked"{/if}/>{/if}
-        {if $node.children}<input name="tagList[{$id}]" id="check_{$id}" type="checkbox" {if $tagged[$id]}checked="checked"{/if}/>{/if}
-        {if $node.children} <span class="hit"></span> {/if} <label for="check_{$id}" id="tagLabel_{$id}">{$node.name}</label>
-        {if $node.children}
-          <ul>
-            {foreach from=$node.children item="subnode" key="subid"}
-              <li id="tag_{$subid}">
-                <input id="check_{$subid}" name="tagList[{$subid}]" type="checkbox" {if $tagged[$subid]}checked="checked"{/if}/>
-                {if $subnode.children} <span class="hit"></span> {/if} <label for="check_{$subid}" id="tagLabel_{$subid}">{$subnode.name}</label>
-                {if $subnode.children}
-                  <ul>
-                    {foreach from=$subnode.children item="subsubnode" key="subsubid"}
-                      <li id="tag_{$subsubid}">
-                        <input id="check_{$subsubid}" name="tagList[{$subsubid}]" type="checkbox" {if $tagged[$subsubid]}checked="checked"{/if}/>
-                        <label for="check_{$subsubid}" id="tagLabel_{$subsubid}">{$subsubnode.name}</label>
-                      </li>
-                    {/foreach}
-                  </ul>
-                {/if}
-              </li>
-            {/foreach}
-          </ul>
-        {/if}
-      </li>
-    {/foreach}
-    </ul>
+    {include file="CRM/Tag/Form/Tagtree.tpl"}
   </div>
   <br />
 {include file="CRM/common/Tagset.tpl"}
diff --git a/templates/CRM/Tag/Form/Tagtree.hlp b/templates/CRM/Tag/Form/Tagtree.hlp
new file mode 100644 (file)
index 0000000..e5d9719
--- /dev/null
@@ -0,0 +1,30 @@
+{*
+ +--------------------------------------------------------------------+
+ | CiviCRM version 4.5                                                |
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC (c) 2004-2014                                |
+ +--------------------------------------------------------------------+
+ | This file is a part of CiviCRM.                                    |
+ |                                                                    |
+ | CiviCRM is free software; you can copy, modify, and distribute it  |
+ | under the terms of the GNU Affero General Public License           |
+ | Version 3, 19 November 2007 and the CiviCRM Licensing Exception.   |
+ |                                                                    |
+ | CiviCRM is distributed in the hope that it will be useful, but     |
+ | WITHOUT ANY WARRANTY; without even the implied warranty of         |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.               |
+ | See the GNU Affero General Public License for more details.        |
+ |                                                                    |
+ | You should have received a copy of the GNU Affero General Public   |
+ | License and the CiviCRM Licensing Exception along                  |
+ | with this program; if not, contact CiviCRM LLC                     |
+ | at info[AT]civicrm[DOT]org. If you have questions about the        |
+ | GNU Affero General Public License or the licensing of CiviCRM,     |
+ | see the CiviCRM license FAQ at http://civicrm.org/licensing        |
+ +--------------------------------------------------------------------+
+*}
+
+{htxt id=$id}
+  {crmAPI var='result' entity='tag' action='getsingle' return="description" id=$id}
+  {$result.description}
+{/htxt}
diff --git a/templates/CRM/Tag/Form/Tagtree.tpl b/templates/CRM/Tag/Form/Tagtree.tpl
new file mode 100644 (file)
index 0000000..3c017cd
--- /dev/null
@@ -0,0 +1,41 @@
+{*
+ +--------------------------------------------------------------------+
+ | CiviCRM version 4.5                                                |
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC (c) 2004-2014                                |
+ +--------------------------------------------------------------------+
+ | This file is a part of CiviCRM.                                    |
+ |                                                                    |
+ | CiviCRM is free software; you can copy, modify, and distribute it  |
+ | under the terms of the GNU Affero General Public License           |
+ | Version 3, 19 November 2007 and the CiviCRM Licensing Exception.   |
+ |                                                                    |
+ | CiviCRM is distributed in the hope that it will be useful, but     |
+ | WITHOUT ANY WARRANTY; without even the implied warranty of         |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.               |
+ | See the GNU Affero General Public License for more details.        |
+ |                                                                    |
+ | You should have received a copy of the GNU Affero General Public   |
+ | License and the CiviCRM Licensing Exception along                  |
+ | with this program; if not, contact CiviCRM LLC                     |
+ | at info[AT]civicrm[DOT]org. If you have questions about the        |
+ | GNU Affero General Public License or the licensing of CiviCRM,     |
+ | see the CiviCRM license FAQ at http://civicrm.org/licensing        |
+ +--------------------------------------------------------------------+
+*}
+{* This tpl runs recursively to build each level of the tag tree *}
+<ul>
+  {foreach from=$tree item="node" key="id"}
+    <li id="tag_{$id}">
+      <input name="tagList[{$id}]" id="check_{$id}" type="checkbox" {if $tagged[$id]}checked="checked"{/if}/>
+      <label for="check_{$id}" id="tagLabel_{$id}">
+        {$node.name}
+        {if $node.description}{help id=$id title=$node.name file="CRM/Tag/Form/Tagtree"}{/if}
+      </label>
+      {if $node.children}
+        {* Recurse... *}
+        {include file="CRM/Tag/Form/Tagtree.tpl" tree=$node.children}
+      {/if}
+    </li>
+  {/foreach}
+</ul>
index 310d00df632bf2917e06982cbc10f66530a86e39..57c88b5599466b235a5af06253c5379dbe40a791 100644 (file)
@@ -25,7 +25,6 @@
  */
 
 require_once 'CiviTest/CiviSeleniumTestCase.php';
-require_once 'WebTest/Event/AddEventTest.php';
 
 /**
  * Class WebTest_Event_PCPAddTest
index fdddd616f038300ceacd920979d5814ed3386249..41c226f7d2d895634d7758955bd82043434d97b7 100644 (file)
@@ -29,7 +29,7 @@ require_once 'WebTest/Import/ImportCiviSeleniumTestCase.php';
 /**
  * Class WebTest_Import_SavedMapping
  */
-class WebTest_Import_SavedMapping extends ImportCiviSeleniumTestCase {
+class WebTest_Import_SavedMappingTest extends ImportCiviSeleniumTestCase {
 
   protected function setUp() {
     parent::setUp();
index 8123794d5e08dbeafb0998e994c1210782755f11..bd51f8c4a765803e976e3544d420c5d7627a0f1a 100644 (file)
@@ -88,6 +88,74 @@ class WebTest_Member_StandaloneAddTest extends CiviSeleniumTestCase {
     $this->webtestVerifyTabularData($expected);
   }
 
+  function testStandaloneGiftMembership() {
+
+    $this->webtestLogin();
+
+    // create contact
+    $firstName = substr(sha1(rand()), 0, 7);
+    $this->webtestAddContact($firstName, "Memberson", "Memberson{$firstName}@memberson.name");
+    $contactName = "Memberson, $firstName";
+
+    $giftMemberfirstName = substr(sha1(rand()), 0, 7);
+    $this->webtestAddContact($giftMemberfirstName, "Memberson", "Memberson{$giftMemberfirstName}@memberson.name");
+    $giftMembercontactName = "Memberson, $giftMemberfirstName";
+
+    // add membership type
+    $membershipTypes = $this->webtestAddMembershipType();
+
+    // now add membership
+    $this->openCiviPage("member/add", "reset=1&action=add&context=standalone", "_qf_Membership_upload");
+
+    // select contact
+    $this->webtestFillAutocomplete($firstName);
+
+    // fill in Membership Organization
+    $this->select("membership_type_id[0]", "label={$membershipTypes['member_of_contact']}");
+
+    // select membership type
+    $this->select("membership_type_id[1]", "label={$membershipTypes['membership_type']}");
+
+    // fill in Source
+    $this->type("source", "Membership StandaloneAddTest Webtest");
+
+    // fill in Start Date
+    $this->webtestFillDate('start_date');
+
+    // add softcredit details
+    $totalAmount = 100;
+    $financialType = 'Donation';
+    $this->clickLink('is_different_contribution_contact','total_amount',FALSE);
+
+    $this->select('soft_credit_type_id', 'Gift');
+    $this->select2('soft_credit_contact_id', $giftMembercontactName);
+    $this->select('financial_type_id','Donation');
+    $this->type('total_amount', $totalAmount);
+    $this->select('payment_instrument_id', 'Check');
+    $this->select('contribution_status_id', 'Completed');
+
+    $this->click("_qf_Membership_upload");
+
+    //View Membership
+    $this->waitForElementPresent("xpath=//div[@id='memberships']//table//tbody/tr[1]/td[9]/span/a[text()='View']");
+    $this->click("xpath=//div[@id='memberships']//table/tbody/tr[1]/td[9]/span/a[text()='View']");
+    $this->waitForElementPresent("_qf_MembershipView_cancel-bottom");
+
+    // verify soft credit data
+    $expected = array(
+      '1' => $giftMemberfirstName.' Memberson',
+      '2' => $totalAmount,
+      '3' => 'Gift',
+      '4' => 'Donation',
+      '6' => 'Completed',
+    );
+
+    foreach($expected as $key => $value) {
+      $this->verifyText("xpath=//div[@class='crm-accordion-wrapper']//table/tbody//tr/td[$key]", $value);
+    }
+
+  }
+
   function testStandaloneMemberOverrideAdd() {
 
     $this->webtestLogin();
diff --git a/tools/scripts/jmat b/tools/scripts/jmat
new file mode 100755 (executable)
index 0000000..c29dcfa
--- /dev/null
@@ -0,0 +1,105 @@
+#!/bin/bash
+####################################################################
+function show_help() {
+  echo "Jeanine Matthews - Divergent Hunter"
+  echo "summary: Execute test suite in multiple ways and compare results"
+  echo "usage: env [var1=... var2=...] $0 [--bundled-full|--bf] [--bundled-indiv|--bi] [--standalone-full|--sf] [--standalone-indiv|--si] [--compare]"
+  echo "Optional variables:"
+  echo "  - CIVI: Path to Civi installation [$CIVI]"
+  echo "  - PHP: Path to PHP binary [$PHP]"
+  echo "  - PHPUNIT: Path to phpunit binary [$PHPUNIT]"
+  echo "  - TESTCLASS: PHP class name for the test case/suite [$TESTCLASS]"
+  echo "  - TESTPATH: Path for the test file/directory (Note: MUST match TESTCLASS) [$TESTPATH]"
+  echo "  - OUTDIR: Folder to which outputs are written [$OUTDIR]"
+}
+
+function reset_dir() {
+  [ -d "$1" ] && rm -rf "$1"
+  mkdir -p "$1"
+}
+
+####################################################################
+## Env
+export PHP=${PHP:-php}
+export PHPUNIT=${PHPUNIT:-phpunit}
+export TESTCLASS=${TESTCLASS:-api_v3_AllTests}
+export TESTPATH=${TESTPATH:-tests/phpunit/api/v3}
+export CIVI=$(realpath "${CIVI:-.}")
+export OUTDIR=$(realpath "${OUTDIR:-output}")
+
+####################################################################
+## Main
+if [ -z "$1" ];then
+  show_help
+  exit 1
+fi
+
+while [ -n "$1" ]; do
+  OPTION="$1"
+  shift
+
+  case "$OPTION" in
+    --bundled-full|--bf)
+      echo "[[ Prepare $OUTDIR/bundled-full ]]"
+
+      [ -d "packages/PHPUnit.bak" ] && mv "packages/PHPUnit.bak" "packages/PHPUnit"
+      if [ ! -d "$CIVI/packages/PHPUnit" ]; then
+        echo "Missing $CIVI/packages/PHPUnit"
+        exit 2
+      fi
+
+      reset_dir "$OUTDIR/bundled-full"
+
+      pushd "$CIVI/tools"
+        $PHP ./scripts/phpunit --tap --log-json "$OUTDIR/bundled-full/all.json" "$TESTCLASS"
+      popd
+      ;;
+
+    --bundled-indiv|--bi)
+      echo "[[ Prepare $OUTDIR/bundled-indiv ]]"
+
+      [ -d "packages/PHPUnit.bak" ] && mv "packages/PHPUnit.bak" "packages/PHPUnit"
+      if [ ! -d "$CIVI/packages/PHPUnit" ]; then
+        echo "Missing $CIVI/packages/PHPUnit"
+        exit 2
+      fi
+
+      reset_dir "$OUTDIR/bundled-indiv"
+
+      pushd "$CIVI/tools"
+        ./scripts/phpunit-indiv --civi --test-dir "../$TESTPATH" --json-dir "$OUTDIR/bundled-indiv"
+      popd
+
+      cat "$OUTDIR"/bundled-indiv/*-*.json > "$OUTDIR/bundled-indiv/all.json"
+      ;;
+
+    --standalone-full|--sf)
+      echo "[[ Prepare $OUTDIR/standalone-full ]]"
+      reset_dir "$OUTDIR/standalone-full"
+
+      pushd "$CIVI"
+        [ -d "packages/PHPUnit" ] && mv "packages/PHPUnit" "packages/PHPUnit.bak"
+        $PHP $(which $PHPUNIT) --tap --log-json "$OUTDIR/standalone-full/all.json" "$TESTPATH"
+        [ -d "packages/PHPUnit.bak" ] && mv "packages/PHPUnit.bak" "packages/PHPUnit"
+      popd
+      ;;
+
+    --standalone-indiv|--si)
+      echo "[[ Prepare $OUTDIR/standalone-indiv ]]"
+      reset_dir "$OUTDIR/standalone-indiv"
+
+      pushd "$CIVI"
+        [ -d "packages/PHPUnit" ] && mv "packages/PHPUnit" "packages/PHPUnit.bak"
+        ./tools/scripts/phpunit-indiv --test-dir "$TESTPATH" --json-dir "$OUTDIR/standalone-indiv"
+        [ -d "packages/PHPUnit.bak" ] && mv "packages/PHPUnit.bak" "packages/PHPUnit"
+      popd
+
+      cat "$OUTDIR"/standalone-indiv/*-*.json > "$OUTDIR/standalone-indiv/all.json"
+      ;;
+
+    --compare)
+      echo "[[ Compare all results in $OUTDIR ]]"
+      phpunit-compare "$OUTDIR"/*/all.json
+      ;;
+  esac
+done
diff --git a/tools/scripts/phpunit-antagonist b/tools/scripts/phpunit-antagonist
new file mode 100755 (executable)
index 0000000..996c553
--- /dev/null
@@ -0,0 +1,4 @@
+#!/usr/bin/env php
+<?php
+require_once dirname(dirname(__DIR__)) . '/tests/phpunit/CiviTest/bootstrap.php';
+\Civi\CiUtil\Command\AntagonistCommand::main($argv);
diff --git a/tools/scripts/phpunit-compare b/tools/scripts/phpunit-compare
new file mode 100755 (executable)
index 0000000..a04c3d7
--- /dev/null
@@ -0,0 +1,4 @@
+#!/usr/bin/env php
+<?php
+require_once dirname(dirname(__DIR__)) . '/tests/phpunit/CiviTest/bootstrap.php';
+\Civi\CiUtil\Command\CompareCommand::main($argv);
diff --git a/tools/scripts/phpunit-indiv b/tools/scripts/phpunit-indiv
new file mode 100755 (executable)
index 0000000..cdec728
--- /dev/null
@@ -0,0 +1,68 @@
+#!/bin/bash
+function absdirname() {
+  pushd $(dirname $0) >> /dev/null
+    pwd
+  popd >> /dev/null
+}
+
+BINDIR=$(absdirname "$0")
+PHP=${PHP:-php}
+PHPUNIT=${PHPUNIT:-phpunit}
+MODE=standalone
+XMLDIR=
+JSONDIR=
+
+while [ -n "$1" ]; do
+  ARG="$1"
+  shift
+
+  case "$ARG" in
+    --civi)
+      MODE=civi
+      ;;
+    --test-dir)
+      TESTSUITE="$1"
+      shift
+      ;;
+    --json-dir)
+      JSONDIR="$1"
+      [ ! -d "$JSONDIR" ] && mkdir -p "$JSONDIR"
+      shift
+      ;;
+    --xml-dir)
+      XMLDIR="$1"
+      [ ! -d "$XMLDIR" ] && mkdir -p "$XMLDIR"
+      shift
+      ;;
+    *)
+      echo "unrecognized option: $ARG"
+      ;;
+  esac
+done
+
+
+if [ -z "$TESTSUITE" ]; then
+  echo "summary: Executes all tests in a suite (individually)"
+  echo "usage: $0 --test-dir <dir> [--json-dir <dir>] [--xml-dir <dir>] [--civi]"
+  exit 1
+fi
+
+
+#phpunit-ls "$TESTSUITE"
+$BINDIR/phpunit-ls "$TESTSUITE" | while read FILE CLASS METHOD ; do
+  PHPUNITARGS="--tap"
+  if [ -n "$JSONDIR" ]; then
+    PHPUNITARGS="$PHPUNITARGS --log-json $JSONDIR/$CLASS-$METHOD.json"
+  fi
+  if [ -n "$XMLDIR" ]; then
+    PHPUNITARGS="$PHPUNITARGS --log-junit $XMLDIR/$CLASS-$METHOD.xml"
+  fi
+
+
+  if [ "$MODE" == "civi" ]; then
+    $PHP ./scripts/phpunit $PHPUNITARGS --filter $METHOD'( with.*)?$' "$CLASS"
+  fi
+  if [ "$MODE" == "standalone" ]; then
+    $PHP $(which $PHPUNIT) $PHPUNITARGS --filter $METHOD'( with.*)?$' "$FILE"
+  fi
+done
diff --git a/tools/scripts/phpunit-ls b/tools/scripts/phpunit-ls
new file mode 100755 (executable)
index 0000000..6d6ffc2
--- /dev/null
@@ -0,0 +1,5 @@
+#!/usr/bin/env php
+<?php
+require_once dirname(dirname(__DIR__)) . '/tests/phpunit/CiviTest/bootstrap.php';
+error_reporting(E_ALL);
+\Civi\CiUtil\Command\LsCommand::main($argv);
\ No newline at end of file
diff --git a/tools/scripts/runTests.sh.txt b/tools/scripts/runTests.sh.txt
deleted file mode 100755 (executable)
index dadf2a4..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-#!/bin/bash
-
-SELF=$(cd $(dirname $0); pwd -P)/$(basename $0)
-
-case $1 in
-
-       stable-3.4)
-
-               echo
-               echo  §§§§§§§§§§§§§§§§§§§§ EXECUTING TESTS FOR STABLE
-               echo
-
-               echo
-               echo  §§§§§§§§§§§§§§§§§§§§ Updating Selenium tests repository
-               echo
-        cd /var/www/drupal6.dev.civicrm.org/public/sites/devel.drupal6.tests.dev.civicrm.org/modules/civicrm/
-               find . -name *~ -delete
-               svn up
-               echo  §§§§§§§§§§§§§§§§§§§§  ...done.
-
-               echo
-               echo  §§§§§§§§§§§§§§§§§§§§ Resetting Selenium tests database and template files
-               echo
-        rm -rf /tmp/templates_c/
-        cd /var/www/drupal6.dev.civicrm.org/public/sites/devel.drupal6.tests.dev.civicrm.org/modules/civicrm/bin
-               ./setup.sh
-               rm -rf /var/www/drupal6.dev.civicrm.org/public/sites/devel.drupal6.tests.dev.civicrm.org/files/civicrm/
-               chmod -R 777 /var/www/drupal6.dev.civicrm.org/public/sites/devel.drupal6.tests.dev.civicrm.org/files/
-        
-        echo  §§§§§§§§§§§§§§§§§§§§  ...done.
-               echo
-        CODE_DIR="/home/tests/stable-suite"
-
-               echo
-               echo  §§§§§§§§§§§§§§§§§§§§  Running test suite
-               echo
-        
-        rm -rf /tmp/templates_c/
-
-         for testName in api_v2 api_v3 CRM WebTest; do 
-                 cd $CODE_DIR/tools
-          scripts/phpunit --tap --log-junit tests/reports/logfile.$testName.xml -u tests -ptests -h localhost ${testName}_AllTests
-                 cd $CODE_DIR/tools/scripts/
-
-                 echo
-                 echo  §§§§§§§§§§§§§§§§§§§§  Generating test results.
-                 echo
-                 phing $testName
-                 echo  §§§§§§§§§§§§§§§§§§§§  All finished.        
-      done
-
-       ;;
-
-       stable)
-
-        echo
-               echo  §§§§§§§§§§§§§§§§§§§§ EXECUTING TESTS FOR TRUNK 
-               echo
-
-               echo
-               echo  §§§§§§§§§§§§§§§§§§§§ Updating test suite repository
-               echo
-        cd /var/www/drupal7.dev.civicrm.org/public/sites/stable.drupal7.tests.dev.civicrm.org/modules/civicrm/
-               find . -name *~ -delete
-               svn up
-               echo  §§§§§§§§§§§§§§§§§§§§  ...done.
-
-               echo
-               echo  §§§§§§§§§§§§§§§§§§§§ Resetting Selenium tests database and template files
-               echo
-        rm -rf /tmp/templates_c/
-        cd /var/www/drupal7.dev.civicrm.org/public/sites/stable.drupal7.tests.dev.civicrm.org/modules/civicrm/bin
-               ./setup.sh
-       
-        echo  §§§§§§§§§§§§§§§§§§§§  ...done.
-        
-        rm -rf /var/www/drupal7.dev.civicrm.org/public/sites/stable.drupal7.tests.dev.civicrm.org/files/civicrm/
-        chmod -R 777 /var/www/drupal7.dev.civicrm.org/public/sites/stable.drupal7.tests.dev.civicrm.org/files/
-        CODE_DIR="/home/tests/stable-suite"
-
-               echo
-               echo  §§§§§§§§§§§§§§§§§§§§  Running test suite
-               echo
-
-#       for testName in api_v3; do 
-#       for testName in WebTest; do 
-#       for testName in api_v3 CRM; do 
-       for testName in api_v3 CRM WebTest; do 
-#        for testName in CRM; do
-                 cd $CODE_DIR/tools
-         
-          rm -rf /tmp/templates_c/
-          
-          #reset the db before running webtest
-          if [ $testName == WebTest ] ; then
-              echo 
-              echo ============== reloading db for Webtest ===============================
-              echo 
-             /var/www/drupal7.dev.civicrm.org/public/sites/stable.drupal7.tests.dev.civicrm.org/modules/civicrm/bin/setup.sh
-          fi
-
-          scripts/phpunit --tap --log-junit tests/reports/logfile.$testName.xml -u tests -ptests -bstable_drupal7_tests_dev_civicrm -h localhost ${testName}_AllTests
-                 cd $CODE_DIR/tools/scripts/
-
-                 echo
-                 echo  §§§§§§§§§§§§§§§§§§§§  Generating test results.
-                 echo
-                 phing $testName
-                 echo  §§§§§§§§§§§§§§§§§§§§  All finished.        
-      done
-
-    ;;
-
-       trunk)
-
-        echo
-               echo  §§§§§§§§§§§§§§§§§§§§ EXECUTING TESTS FOR TRUNK 
-               echo
-
-               echo
-               echo  §§§§§§§§§§§§§§§§§§§§ Updating test suite repository
-               echo
-        cd /var/www/drupal7.dev.civicrm.org/public/sites/devel.drupal7.tests.dev.civicrm.org/modules/civicrm/
-               find . -name *~ -delete
-               svn up
-               echo  §§§§§§§§§§§§§§§§§§§§  ...done.
-
-               echo
-               echo  §§§§§§§§§§§§§§§§§§§§ Resetting Selenium tests database and template files
-               echo
-        rm -rf /tmp/templates_c/
-        cd /var/www/drupal7.dev.civicrm.org/public/sites/devel.drupal7.tests.dev.civicrm.org/modules/civicrm/bin
-               ./setup.sh
-       
-        echo  §§§§§§§§§§§§§§§§§§§§  ...done.
-        
-        rm -rf /var/www/drupal7.dev.civicrm.org/public/sites/devel.drupal7.tests.dev.civicrm.org/files/civicrm/
-        chmod -R 777 /var/www/drupal7.dev.civicrm.org/public/sites/devel.drupal7.tests.dev.civicrm.org/files/
-        CODE_DIR="/home/tests/devel-suite"
-
-               echo
-               echo  §§§§§§§§§§§§§§§§§§§§  Running test suite
-               echo
-
-#       for testName in api_v3; do 
-#       for testName in WebTest; do 
-#       for testName in api_v2 api_v3 CRM; do 
-       for testName in api_v3 CRM WebTest; do 
-#        for testName in CRM; do
-                 cd $CODE_DIR/tools
-         
-          rm -rf /tmp/templates_c/
-          
-          #reset the db before running webtest
-          if [ $testName == WebTest ] ; then
-              echo 
-              echo ============== reloading db for Webtest ===============================
-              echo 
-             /var/www/drupal7.dev.civicrm.org/public/sites/devel.drupal7.tests.dev.civicrm.org/modules/civicrm/bin/setup.sh
-          fi
-
-          scripts/phpunit --tap --log-junit tests/reports/logfile.$testName.xml -u tests -ptests -bdevel_drupal7_tests_dev_civicrm -h localhost ${testName}_AllTests
-                 cd $CODE_DIR/tools/scripts/
-
-                 echo
-                 echo  §§§§§§§§§§§§§§§§§§§§  Generating test results.
-                 echo
-                 phing $testName
-                 echo  §§§§§§§§§§§§§§§§§§§§  All finished.        
-      done
-
-    ;;
-       
-       *)
-               $SELF trunk 
-       ;;
-esac