Merge branch '4.7.21-rc' into master
authorColeman Watts <coleman@civicrm.org>
Wed, 21 Jun 2017 19:11:31 +0000 (15:11 -0400)
committerColeman Watts <coleman@civicrm.org>
Wed, 21 Jun 2017 19:11:31 +0000 (15:11 -0400)
45 files changed:
CRM/Activity/Tokens.php
CRM/Admin/Form/Setting/Localization.php
CRM/Admin/Page/AJAX.php
CRM/Contact/Form/Contact.php
CRM/Contact/Form/Edit/TagsAndGroups.php
CRM/Contribute/BAO/Contribution.php
CRM/Contribute/Form/Contribution.php
CRM/Contribute/Form/SoftCredit.php
CRM/Contribute/Tokens.php
CRM/Core/BAO/File.php
CRM/Core/BAO/OptionGroup.php
CRM/Core/BAO/Tag.php
CRM/Core/I18n.php
CRM/Core/Payment/BaseIPN.php
CRM/Core/Permission.php
CRM/Core/SelectValues.php
CRM/Event/Form/Registration/ParticipantConfirm.php
CRM/Event/Tokens.php
CRM/Logging/Schema.php
CRM/Mailing/BAO/Mailing.php
CRM/Mailing/Event/BAO/Resubscribe.php
CRM/Member/BAO/Membership.php
CRM/Member/Form/MembershipType.php
CRM/Member/Page/DashBoard.php
CRM/Member/Tokens.php
CRM/Tag/Form/Edit.php
CRM/Upgrade/Incremental/sql/4.7.22.mysql.tpl [new file with mode: 0644]
CRM/Utils/Token.php
Civi/Core/Container.php
Civi/Core/LocalizationInitializer.php [new file with mode: 0644]
Civi/Token/AbstractTokenSubscriber.php
install/index.php
settings/Localization.setting.php
sql/civicrm_generated.mysql
templates/CRM/Contact/Form/Edit/TagsAndGroups.tpl
templates/CRM/Contribute/Form/ContributionPage/Amount.tpl
templates/CRM/Contribute/Form/ContributionPage/Delete.tpl
templates/CRM/Profile/Form/Dynamic.tpl
templates/CRM/Tag/Page/Tag.tpl
tests/phpunit/CRM/Contact/Page/AjaxTest.php
tests/phpunit/CRM/Contribute/Form/ContributionTest.php
tests/phpunit/CRM/Core/Payment/PayPalProIPNTest.php
tests/phpunit/api/v3/ContributionTest.php
tests/phpunit/api/v3/MembershipTest.php
xml/version.xml

index 7a0ba27d4096204f4149d950031c3766f9a2d781..eb5ad34b827bc133a0e24a20b5a00c9eca5dfb00 100644 (file)
@@ -57,7 +57,7 @@ class CRM_Activity_Tokens extends \Civi\Token\AbstractTokenSubscriber {
         'details' => ts('Activity Details'),
         'activity_date_time' => ts('Activity Date-Time'),
       ),
-      $this->getCustomTokens('Activity')
+      CRM_Utils_Token::getCustomFieldTokens('Activity')
     ));
   }
 
index 8e2b2718ab23ddb7b25a5337920f4178cc8b9f75..21cd8f8a3a49052a117c98fe0a4d0e6e742234cf 100644 (file)
@@ -191,40 +191,16 @@ class CRM_Admin_Form_Setting_Localization extends CRM_Admin_Form_Setting {
     // we do this only to initialize monetary decimal point and thousand separator
     $config = CRM_Core_Config::singleton();
 
-    // save enabled currencies and defaul currency in option group 'currencies_enabled'
+    // save enabled currencies and default currency in option group 'currencies_enabled'
     // CRM-1496
     if (empty($values['currencyLimit'])) {
       $values['currencyLimit'] = array($values['defaultCurrency']);
     }
-    elseif (!in_array($values['defaultCurrency'],
-      $values['currencyLimit']
-    )
-    ) {
+    elseif (!in_array($values['defaultCurrency'], $values['currencyLimit'])) {
       $values['currencyLimit'][] = $values['defaultCurrency'];
     }
 
-    // sort so that when we display drop down, weights have right value
-    sort($values['currencyLimit']);
-
-    // get labels for all the currencies
-    $options = array();
-
-    $currencySymbols = self::getCurrencySymbols();
-    for ($i = 0; $i < count($values['currencyLimit']); $i++) {
-      $options[] = array(
-        'label' => $currencySymbols[$values['currencyLimit'][$i]],
-        'value' => $values['currencyLimit'][$i],
-        'weight' => $i + 1,
-        'is_active' => 1,
-        'is_default' => $values['currencyLimit'][$i] == $values['defaultCurrency'],
-      );
-    }
-
-    $dontCare = NULL;
-    CRM_Core_OptionGroup::createAssoc('currencies_enabled',
-      $options,
-      $dontCare
-    );
+    self::updateEnabledCurrencies($values['currencyLimit'], $values['defaultCurrency']);
 
     // unset currencyLimit so we dont store there
     unset($values['currencyLimit']);
@@ -269,6 +245,38 @@ class CRM_Admin_Form_Setting_Localization extends CRM_Admin_Form_Setting {
     }
   }
 
+
+  /**
+   * Replace available currencies by the ones provided
+   *
+   * @param $currencies array of currencies ['USD', 'CAD']
+   * @param $default default currency
+   */
+  public static function updateEnabledCurrencies($currencies, $default) {
+
+    // sort so that when we display drop down, weights have right value
+    sort($currencies);
+
+    // get labels for all the currencies
+    $options = array();
+
+    $currencySymbols = CRM_Admin_Form_Setting_Localization::getCurrencySymbols();
+    for ($i = 0; $i < count($currencies); $i++) {
+      $options[] = array(
+        'label' => $currencySymbols[$currencies[$i]],
+        'value' => $currencies[$i],
+        'weight' => $i + 1,
+        'is_active' => 1,
+        'is_default' => $currencies[$i] == $default,
+      );
+    }
+
+    $dontCare = NULL;
+    CRM_Core_OptionGroup::createAssoc('currencies_enabled', $options, $dontCare);
+
+  }
+
+
   /**
    * @return array
    */
@@ -351,6 +359,26 @@ class CRM_Admin_Form_Setting_Localization extends CRM_Admin_Form_Setting {
     }
   }
 
+  public static function onChangeDefaultCurrency($oldCurrency, $newCurrency, $metadata) {
+    if ($oldCurrency == $newCurrency) {
+      return;
+    }
+
+    // ensure that default currency is always in the list of enabled currencies
+    $currencies = array_keys(CRM_Core_OptionGroup::values('currencies_enabled'));
+    if (!in_array($newCurrency, $currencies)) {
+      if (empty($currencies)) {
+        $currencies = array($values['defaultCurrency']);
+      }
+      else {
+        $currencies[] = $newCurrency;
+      }
+
+      CRM_Admin_Form_Setting_Localization::updateEnabledCurrencies($currencies, $newCurrency);
+    }
+
+  }
+
   /**
    * @return array
    */
index 35f5f2aabd567ed603b412846db8899c148f68b5..1aa2d5c0ad23961dfd62689a7eef81320b024c69 100644 (file)
@@ -304,20 +304,24 @@ class CRM_Admin_Page_AJAX {
     $parent = CRM_Utils_Type::escape(CRM_Utils_Array::value('parent_id', $_GET, 0), 'Integer');
     $result = array();
 
-    $parentClause = $parent ? "AND tag.parent_id = $parent" : 'AND tag.parent_id IS NULL';
-    $sql = "SELECT tag.*, child.id AS child, COUNT(et.id) as usages
-      FROM civicrm_tag tag
-      LEFT JOIN civicrm_entity_tag et ON et.tag_id = tag.id
-      LEFT JOIN civicrm_tag child ON child.parent_id = tag.id
-      WHERE tag.is_tagset <> 1 $parentClause
-      GROUP BY tag.id
-      ORDER BY tag.name";
+    $parentClause = $parent ? "AND parent_id = $parent" : 'AND parent_id IS NULL';
+    $sql = "SELECT *
+      FROM civicrm_tag
+      WHERE is_tagset <> 1 $parentClause
+      GROUP BY id
+      ORDER BY name";
+
+    // fetch all child tags in Array('parent_tag' => array('child_tag_1', 'child_tag_2', ...)) format
+    $childTagIDs = CRM_Core_BAO_Tag::getChildTags();
+
     $dao = CRM_Core_DAO::executeQuery($sql);
     while ($dao->fetch()) {
       $style = '';
       if ($dao->color) {
         $style = "background-color: {$dao->color}; color: " . CRM_Utils_Color::getContrast($dao->color);
       }
+      $hasChildTags = empty($childTagIDs[$dao->id]) ? FALSE : TRUE;
+      $usedFor = (array) explode(',', $dao->used_for);
       $result[] = array(
         'id' => $dao->id,
         'text' => $dao->name,
@@ -330,18 +334,25 @@ class CRM_Admin_Page_AJAX {
           'style' => $style,
           'class' => 'crm-tag-item',
         ),
-        'children' => (bool) $dao->child,
+        'children' => $hasChildTags,
         'data' => array(
           'description' => (string) $dao->description,
           'is_selectable' => (bool) $dao->is_selectable,
           'is_reserved' => (bool) $dao->is_reserved,
-          'used_for' => $dao->used_for ? explode(',', $dao->used_for) : array(),
+          'used_for' => $usedFor,
           'color' => $dao->color ? $dao->color : '#ffffff',
-          'usages' => (int) $dao->usages,
+          'usages' => civicrm_api3('EntityTag', 'getcount', array(
+            'entity_table' => array('IN' => $usedFor),
+            'tag_id' => $dao->id,
+          )),
         ),
       );
     }
 
+    if (!empty($_REQUEST['is_unit_test'])) {
+      return $result;
+    }
+
     CRM_Utils_JSON::output($result);
   }
 
index 0a1c077b62c1c1c594aa826cca116cac53b3ff5e..7102c404d9c307b9e16031ba11c7a216c41e5b03 100644 (file)
@@ -992,7 +992,10 @@ class CRM_Contact_Form_Contact extends CRM_Core_Form {
 
     if (array_key_exists('TagsAndGroups', $this->_editOptions)) {
       //add contact to tags
-      CRM_Core_BAO_EntityTag::create($params['tag'], 'civicrm_contact', $params['contact_id']);
+      if (isset($params['tag']) && !empty($params['tag'])) {
+        $params['tag'] = array_flip(explode(',', $params['tag']));
+        CRM_Core_BAO_EntityTag::create($params['tag'], 'civicrm_contact', $params['contact_id']);
+      }
 
       //save free tags
       if (isset($params['contact_taglist']) && !empty($params['contact_taglist'])) {
index def736d726e8eb8860deb2df56ef349ba6592e98..1518c2a119e0d07e787c053a2e90f78ae2292bc9 100644 (file)
@@ -128,7 +128,7 @@ class CRM_Contact_Form_Edit_TagsAndGroups {
 
         if ($groupElementType == 'select' && !empty($groupsOptions)) {
           $form->add('select', $fName, $groupName, $groupsOptions, FALSE,
-            array('id' => $fName, 'multiple' => 'multiple', 'class' => 'crm-select2')
+            array('id' => $fName, 'multiple' => 'multiple', 'class' => 'crm-select2 twenty')
           );
           $form->assign('groupCount', count($groupsOptions));
         }
@@ -145,40 +145,10 @@ class CRM_Contact_Form_Edit_TagsAndGroups {
     }
 
     if ($type & self::TAG) {
-      $fName = 'tag';
-      if ($fieldName) {
-        $fName = $fieldName;
-      }
-      $form->_tagGroup[$fName] = 1;
-
-      // get the list of all the categories
-      $tags = new CRM_Core_BAO_Tag();
-      $tree = $tags->getTree('civicrm_contact', TRUE);
-      // let's not load jstree if there are not children. This also fixes blank
-      // display at the beginning of checkboxes
-      $loadJsTree = CRM_Utils_Array::retrieveValueRecursive($tree, 'children');
-      $form->assign('loadjsTree', FALSE);
-      if (!empty($loadJsTree)) {
-        // CODE FROM CRM/Tag/Form/Tag.php //
-        CRM_Core_Resources::singleton()
-          ->addScriptFile('civicrm', 'packages/jquery/plugins/jstree/jquery.jstree.js', 0, 'html-header', FALSE)
-          ->addStyleFile('civicrm', 'packages/jquery/plugins/jstree/themes/default/style.css', 0, 'html-header');
-        $form->assign('loadjsTree', TRUE);
-      }
-
-      $elements = array();
-      self::climbtree($form, $tree, $elements);
+      $tags = CRM_Core_BAO_Tag::getColorTags('civicrm_contact');
 
-      $form->addGroup($elements, $fName, $tagName, '<br />');
-      $form->assign('tagCount', count($elements));
-      $form->assign('tree', $tree);
-      $form->assign('tag', $tree);
-      $form->assign('entityID', $contactId);
-      $form->assign('entityTable', 'civicrm_contact');
-      $form->assign('allTags', CRM_Core_BAO_Tag::getTagsUsedFor('civicrm_contact', FALSE));
-
-      if ($isRequired) {
-        $form->addRule($fName, ts('%1 is a required field.', array(1 => $tagName)), 'required');
+      if (!empty($tags)) {
+        $form->add('select2', 'tag', ts('Tag(s)'), $tags, FALSE, array('class' => 'huge', 'placeholder' => ts('- select -'), 'multiple' => TRUE));
       }
 
       // build tag widget
@@ -188,31 +158,6 @@ class CRM_Contact_Form_Edit_TagsAndGroups {
     $form->assign('tagGroup', $form->_tagGroup);
   }
 
-  /**
-   * Climb tree.
-   *
-   * @param $form
-   * @param $tree
-   * @param $elements
-   *
-   * @return mixed
-   */
-  public static function climbtree($form, $tree, &$elements) {
-    foreach ($tree as $tagID => $varValue) {
-      $tagAttribute = array(
-        'onclick' => "return changeRowColor(\"rowidtag_$tagID\")",
-        'id' => "tag_{$tagID}",
-      );
-
-      $elements[$tagID] = $form->createElement('checkbox', $tagID, '', $varValue['name'], $tagAttribute);
-
-      if (array_key_exists('children', $varValue)) {
-        self::climbtree($form, $varValue['children'], $elements);
-      }
-    }
-    return $elements;
-  }
-
   /**
    * Set defaults for relevant form elements.
    *
@@ -249,17 +194,7 @@ class CRM_Contact_Form_Edit_TagsAndGroups {
     }
 
     if ($type & self::TAG) {
-      $fName = 'tag';
-      if ($fieldName) {
-        $fName = $fieldName;
-      }
-
-      $contactTag = CRM_Core_BAO_EntityTag::getTag($id);
-      if ($contactTag) {
-        foreach ($contactTag as $tag) {
-          $defaults[$fName . '[' . $tag . ']'] = 1;
-        }
-      }
+      $defaults['tag'] = implode(',', CRM_Core_BAO_EntityTag::getTag($id, 'civicrm_contact'));
     }
   }
 
index de047c5c0ea315ca07886535d6ffd150d80654b9..884ea0bc0d718006e085dadd2119bf8e1ab6e5aa 100644 (file)
@@ -2467,6 +2467,9 @@ INNER JOIN civicrm_activity ON civicrm_activity_contact.activity_id = civicrm_ac
       $ids['paymentProcessor'] = $paymentProcessorID;
       $this->_relatedObjects['paymentProcessor'] = $paymentProcessor;
     }
+
+    // Add contribution id to $ids. CRM-20401
+    $ids['contribution'] = $this->id;
     return TRUE;
   }
 
@@ -4601,6 +4604,7 @@ WHERE eft.financial_trxn_id IN ({$trxnId}, {$baseTrxnId['financialTrxnId']})
               'contact_id' => $membership->contact_id,
               'is_test' => $membership->is_test,
               'membership_type_id' => $membership->membership_type_id,
+              'membership_activity_status' => 'Completed',
             );
 
             $currentMembership = CRM_Member_BAO_Membership::getContactMembership($membershipParams['contact_id'],
index aa9c74f74674fe2c158c0262fb0f37cb87cfde71..2ef73e37443a006e1620a43d604f23760bd6f800 100644 (file)
@@ -154,8 +154,6 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
 
   protected $_formType;
 
-  public $_honoreeProfileType;
-
   /**
    * Array of the payment fields to be displayed in the payment fieldset (pane) in billingBlock.tpl
    * this contains all the information to describe these fields from quickform. See CRM_Core_Form_Payment getPaymentFormFieldsMetadata
@@ -301,10 +299,6 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
     else {
       $this->setPageTitle($this->_ppID ? ts('Pledge Payment') : ts('Contribution'));
     }
-
-    if ($this->_id) {
-      CRM_Contribute_Form_SoftCredit::preprocess($this);
-    }
   }
 
   /**
@@ -1156,6 +1150,9 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
     if (!empty($this->_params['receive_date'])) {
       $this->_params['receive_date'] = CRM_Utils_Date::processDate($this->_params['receive_date'], $this->_params['receive_date_time']);
     }
+    else {
+      $this->_params['receive_date'] = $now;
+    }
 
     $this->_params['pcp_display_in_roll'] = CRM_Utils_Array::value('pcp_display_in_roll', $params);
     $this->_params['pcp_roll_nickname'] = CRM_Utils_Array::value('pcp_roll_nickname', $params);
@@ -1199,8 +1196,6 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
       $paymentParams['receive_date'] = $this->_params['receive_date'];
     }
 
-    $this->_params['receive_date'] = $now;
-
     if (!empty($this->_params['is_email_receipt'])) {
       $this->_params['receipt_date'] = $now;
     }
index 21b5dcf292dbd6a381bc663e9a72d7d1d1680d72..5ffc5e59f00b2be61fadb216756b9a8c25b81a1d 100644 (file)
  */
 class CRM_Contribute_Form_SoftCredit {
 
-  /**
-   * Set variables up before form is built.
-   *
-   * @param CRM_Core_Form $form
-   */
-  public static function preProcess(&$form) {
-    $contriDAO = new CRM_Contribute_DAO_Contribution();
-    $contriDAO->id = $form->_id;
-    $contriDAO->find(TRUE);
-    if ($contriDAO->contribution_page_id) {
-      $ufJoinParams = array(
-        'module' => 'soft_credit',
-        'entity_table' => 'civicrm_contribution_page',
-        'entity_id' => $contriDAO->contribution_page_id,
-      );
-      $profileId = CRM_Core_BAO_UFJoin::getUFGroupIds($ufJoinParams);
-
-      //check if any honree profile is enabled if yes then assign its profile type to $_honoreeProfileType
-      // which will be used to constraint soft-credit contact type in formRule, CRM-13981
-      if (!empty($profileId[0]) && !empty($profileId[2])) {
-        $form->_honoreeProfileType = CRM_Core_BAO_UFGroup::getContactType($profileId[0]);
-      }
-    }
-  }
-
   /**
    * Function used to build form element for soft credit block.
    *
@@ -242,10 +217,6 @@ class CRM_Contribute_Form_SoftCredit {
           if (empty($fields['soft_credit_amount'][$key])) {
             $errors["soft_credit_amount[$key]"] = ts('Please enter the soft credit amount.');
           }
-          $contactType = CRM_Contact_BAO_Contact::getContactType($fields['soft_credit_contact_id'][$key]);
-          if ($self->_honoreeProfileType && $self->_honoreeProfileType != $contactType) {
-            $errors["soft_credit_contact_id[$key]"] = ts('Please choose a contact of type %1', array(1 => $self->_honoreeProfileType));
-          }
         }
       }
     }
index 40a5c832a9beeb8cf8fc7ec5818c657fc44c27f5..441906fa7e77d7ca39d2786ddb898260d48df4e5 100644 (file)
@@ -85,7 +85,7 @@ class CRM_Contribute_Tokens extends \Civi\Token\AbstractTokenSubscriber {
     $tokens['source'] = ts('Contribution Source');
     $tokens['status'] = ts('Contribution Status');
     $tokens['type'] = ts('Financial Type');
-    $tokens = array_merge($tokens, $this->getCustomTokens('Contribution'));
+    $tokens = array_merge($tokens, CRM_Utils_Token::getCustomFieldTokens('Contribution'));
     parent::__construct('contribution', $tokens);
   }
 
index 21e1e0787408f321316eee82160b9b3a1e1cfd3d..ed6ce21e80d0be62ec0b511a89ae3194c9dd3533 100644 (file)
@@ -453,7 +453,7 @@ AND       CEF.entity_id    = %2";
 
     // add attachments
     for ($i = 1; $i <= $numAttachments; $i++) {
-      $form->addElement('file', "attachFile_$i", ts('Attach File'), 'size=30 maxlength=60');
+      $form->addElement('file', "attachFile_$i", ts('Attach File'), 'size=30 maxlength=221');
       $form->addUploadElement("attachFile_$i");
       $form->setMaxFileSize($maxFileSize * 1024 * 1024);
       $form->addRule("attachFile_$i",
index d0f0afc71b45f901d632606f9d4de40622ff9f57..b06e37251bcc43ec8ab18972c497309bcd8ea029 100644 (file)
@@ -219,4 +219,36 @@ class CRM_Core_BAO_OptionGroup extends CRM_Core_DAO_OptionGroup {
     return \Civi::$statics[__CLASS__]['titles_by_name'];
   }
 
+  /**
+   * Set the given values to active, and set all other values to inactive.
+   *
+   * @param string $optionGroupName
+   *   e.g "languages"
+   * @param array<string> $activeValues
+   *   e.g. array("en_CA","fr_CA")
+   */
+  public static function setActiveValues($optionGroupName, $activeValues) {
+    $params = array(
+      1 => array($optionGroupName, 'String'),
+    );
+
+    // convert activeValues into placeholders / params in the query
+    $placeholders = array();
+    $i = count($params) + 1;
+    foreach ($activeValues as $value) {
+      $placeholders[] = "%{$i}";
+      $params[$i] = array($value, 'String');
+      $i++;
+    }
+    $placeholders = implode(', ', $placeholders);
+
+    CRM_Core_DAO::executeQuery("
+UPDATE civicrm_option_value cov
+       LEFT JOIN civicrm_option_group cog ON cov.option_group_id = cog.id
+SET cov.is_active = CASE WHEN cov.name IN ({$placeholders}) THEN 1 ELSE 0 END
+WHERE cog.name = %1",
+      $params
+    );
+  }
+
 }
index 31722e897d7ff13a2162cd792a119ad55184bbdc..f2840268ea5081297f4da9518276dbb3df474295 100644 (file)
@@ -413,6 +413,20 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag {
       return NULL;
     }
 
+    // Check permission to create or modify reserved tag
+    if (!empty($params['check_permissions']) && !CRM_Core_Permission::check('administer reserved tags')) {
+      if (!empty($params['is_reserved']) || ($id && CRM_Core_DAO::getFieldValue('CRM_Core_DAO_Tag', $id, 'is_reserved'))) {
+        throw new CRM_Core_Exception('Insufficient permission to administer reserved tag.');
+      }
+    }
+
+    // Check permission to create or modify tagset
+    if (!empty($params['check_permissions']) && !CRM_Core_Permission::check('administer Tagsets')) {
+      if (!empty($params['is_tagset']) || ($id && CRM_Core_DAO::getFieldValue('CRM_Core_DAO_Tag', $id, 'is_tagset'))) {
+        throw new CRM_Core_Exception('Insufficient permission to administer tagset.');
+      }
+    }
+
     $tag = new CRM_Core_DAO_Tag();
 
     // if parent id is set then inherit used for and is hidden properties
@@ -531,4 +545,40 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag {
     return $tags;
   }
 
+  /**
+   * Get child tags IDs
+   *
+   * @return array $childTagIDs
+   *   associated array of child tags in Array('Parent Tag ID' => Array('Child Tag 1', ...)) format
+   */
+  public static function getChildTags() {
+    $childTagIDs = array();
+
+    // only fetch those tags which has child tags
+    $getChildGroupSQL = "SELECT parent.id as parent_id, GROUP_CONCAT(child.id) as child_id
+        FROM civicrm_tag parent,
+        civicrm_tag child
+        WHERE parent.is_tagset <> 1 AND child.parent_id = parent.id
+        GROUP BY parent.id
+    ";
+    $dao = CRM_Core_DAO::executeQuery($getChildGroupSQL);
+    while ($dao->fetch()) {
+      $childTagIDs[$dao->parent_id] = (array) explode(',', $dao->child_id);
+    }
+
+    // check if child tag has any childs, if found then include those child tags inside parent tag
+    //  i.e. format Array('parent_tag' => array('child_tag_1', ...), 'child_tag_1' => array(child_tag_1_1, ..), ..)
+    //  to Array('parent_tag' => array('child_tag_1', 'child_tag_1_1'...), ..)
+    foreach ($childTagIDs as $parentTagID => $childTags) {
+      foreach ($childTags as $childTag) {
+        // if $childTag has any child tag of its own
+        if (array_key_exists($childTag, $childTagIDs)) {
+          $childTagIDs[$parentTagID] = array_merge($childTagIDs[$parentTagID], $childTagIDs[$childTag]);
+        }
+      }
+    }
+
+    return $childTagIDs;
+  }
+
 }
index ca7706cd9d5caf7f5c428b7b35fc1df71ebef29f..9e20536dfe3854345203734dca639356d89a4872 100644 (file)
@@ -163,6 +163,14 @@ class CRM_Core_I18n {
     if (!$all) {
       $all = CRM_Contact_BAO_Contact::buildOptions('preferred_language');
 
+      // get labels
+      $rows = array();
+      $labels = array();
+      CRM_Core_OptionValue::getValues(array('name' => 'languages'), $rows);
+      foreach ($rows as $id => $row) {
+        $labels[$row['name']] = $row['label'];
+      }
+
       // check which ones are available; add them to $all if not there already
       $codes = array();
       if (is_dir(CRM_Core_I18n::getResourceDir()) && $dir = opendir(CRM_Core_I18n::getResourceDir())) {
@@ -170,7 +178,7 @@ class CRM_Core_I18n {
           if (preg_match('/^[a-z][a-z]_[A-Z][A-Z]$/', $filename)) {
             $codes[] = $filename;
             if (!isset($all[$filename])) {
-              $all[$filename] = $filename;
+              $all[$filename] = $labels[$filename];
             }
           }
         }
@@ -186,6 +194,8 @@ class CRM_Core_I18n {
           unset($all[$code]);
         }
       }
+
+      ksort($all);
     }
 
     if ($enabled === NULL) {
index c4a1af336ce7c440d0453b396669ee91b8c5088c..a9f62e75fa83ed2a50972a0a2567ee2f0210de7a 100644 (file)
@@ -125,6 +125,14 @@ class CRM_Core_Payment_BaseIPN {
 
     $objects['contact'] = &$contact;
     $objects['contribution'] = &$contribution;
+
+    // CRM-19478: handle oddity when p=null is set in place of contribution page ID,
+    if (!empty($ids['contributionPage']) && !is_numeric($ids['contributionPage'])) {
+      // We don't need to worry if about removing contribution page id as it will be set later in
+      //  CRM_Contribute_BAO_Contribution::loadRelatedObjects(..) using $objects['contribution']->contribution_page_id
+      unset($ids['contributionPage']);
+    }
+
     if (!$this->loadObjects($input, $ids, $objects, $required, $paymentProcessorID)) {
       return FALSE;
     }
index 0b9979d599f0aa50d1048c9050cdcb0c70da68f8..39847006c03de5cc9dcb834936d72e4ba0eaac3b 100644 (file)
@@ -127,7 +127,7 @@ class CRM_Core_Permission {
         foreach ($permission as $orPerm) {
           if (self::check($orPerm)) {
             //one of our 'or' permissions has succeeded - stop checking this permission
-            return TRUE;;
+            return TRUE;
           }
         }
         //none of our our conditions was met
index 22416b15d222d8c1105c5d97ff3d6b51f6546c40..ece069395cb36d36fde903825157bbab0de8c88a 100644 (file)
@@ -559,7 +559,7 @@ class CRM_Core_SelectValues {
    * @return array
    */
   public static function contributionTokens() {
-    return array(
+    return array_merge(array(
       '{contribution.contribution_id}' => ts('Contribution ID'),
       '{contribution.total_amount}' => ts('Total Amount'),
       '{contribution.fee_amount}' => ts('Fee Amount'),
@@ -583,7 +583,7 @@ class CRM_Core_SelectValues {
       //'{contribution.address_id}' => ts('Address ID'),
       '{contribution.check_number}' => ts('Check Number'),
       '{contribution.campaign}' => ts('Contribution Campaign'),
-    );
+    ), CRM_Utils_Token::getCustomFieldTokens('contribution', TRUE));
   }
 
   /**
index ff7d7b856b0e64d6be45fadc9909317e57e038cf..2d134f3950dcf30a5f0f8660a61b0f020b8d6ae1 100644 (file)
@@ -213,9 +213,8 @@ class CRM_Event_Form_Registration_ParticipantConfirm extends CRM_Event_Form_Regi
       }
 
       $this->postProcessHook();
-
-      CRM_Core_Error::statusBounce($statusMessage,
-        CRM_Utils_System::url('civicrm/event/info',
+      CRM_Core_Session::setStatus($statusMessage);
+      CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/event/info',
           "reset=1&id={$this->_eventId}&noFullMsg=1",
           FALSE, NULL, FALSE, TRUE
         )
index e947ade45f79f568c7db28f049ef07f7dddf1f3f..423dd79a1d7a474014e3227f4abf1c17703fff56 100644 (file)
@@ -61,7 +61,7 @@ class CRM_Event_Tokens extends \Civi\Token\AbstractTokenSubscriber {
         'contact_phone' => ts('Event Contact (Phone)'),
         'balance' => ts('Event Balance'),
       ),
-      $this->getCustomTokens('Event')
+      CRM_Utils_Token::getCustomFieldTokens('Event')
     ));
   }
 
index 0cbe435c5eb071404b5aca176b730339e41d65a8..b34806019f3c6ef12625fe64d576bae0e440873a 100644 (file)
@@ -542,7 +542,7 @@ AND    (TABLE_NAME LIKE 'log_civicrm_%' $nonStandardTableNameString )
       }
       \Civi::$statics[__CLASS__]['columnsOf'][$table] = array();
       while ($dao->fetch()) {
-        \Civi::$statics[__CLASS__]['columnsOf'][$table][] = $dao->Field;
+        \Civi::$statics[__CLASS__]['columnsOf'][$table][] = CRM_Utils_type::escape($dao->Field, 'MysqlColumnNameOrAlias');
       }
     }
     return \Civi::$statics[__CLASS__]['columnsOf'][$table];
index bcf318b6d1da7ada70e49955f423572c964e07de..3d3cced20b13e20d6b8a4f1d544fabfeda38b7a7 100644 (file)
@@ -1787,7 +1787,7 @@ ORDER BY   civicrm_email.is_bulkmail DESC
       // Populate the recipients.
       if (empty($params['_skip_evil_bao_auto_recipients_'])) {
         // check if it's sms
-        $mode = $mailing->sms_provider_id ? 'sms' : NULL;
+        $mode = $mailing->sms_provider_id && $mailing->sms_provider_id != 'null' ? 'sms' : NULL;
         self::getRecipients($job->id, $mailing->id, TRUE, $mailing->dedupe_email, $mode);
       }
       // Schedule the job now that it has recipients.
index 67639702e7f5220370e6abb5c8629d2a2a1e17ee..ac361de23c9ab0a532d17b044a8a558093fd0be2 100644 (file)
@@ -260,7 +260,7 @@ class CRM_Mailing_Event_BAO_Resubscribe {
       $message->setHTMLBody($html);
     }
     if (!$html || $eq->format == 'Text' || $eq->format == 'Both') {
-      $text = CRM_Utils_Token::replaceDomainTokens($html, $domain, TRUE, $tokens['text']);
+      $text = CRM_Utils_Token::replaceDomainTokens($text, $domain, TRUE, $tokens['text']);
       $text = CRM_Utils_Token::replaceResubscribeTokens($text, $domain, $groups, FALSE, $eq->contact_id, $eq->hash);
       $text = CRM_Utils_Token::replaceActionTokens($text, $addresses, $urls, FALSE, $tokens['text']);
       $text = CRM_Utils_Token::replaceMailingTokens($text, $dao, NULL, $tokens['text']);
index 7cedc4318c76c0fac40c87727dd9d6d50df110a7..6d206aa137b10365629e19600d18df5dc846214a 100644 (file)
@@ -189,7 +189,7 @@ class CRM_Member_BAO_Membership extends CRM_Member_DAO_Membership {
         );
         // 1. Update Schedule Membership Signup/Renwal activity to completed on successful payment of pending membership
         // 2. OR Create renewal activity scheduled if its membership renewal will be paid later
-        if (!empty($activityParams['id']) || $activityType == 'Membership Renewal') {
+        if (!empty($params['membership_activity_status']) && (!empty($activityParams['id']) || $activityType == 'Membership Renewal')) {
           CRM_Activity_BAO_Activity::addActivity($membership, $activityType, $targetContactID, $activityParams);
           break;
         }
@@ -1170,6 +1170,7 @@ AND civicrm_membership.is_test = %2";
     $currentMembership['today_date'] = $today;
 
     if ($status['id'] !== $currentMembership['status_id']) {
+      $oldStatus = $currentMembership['status_id'];
       $memberDAO = new CRM_Member_DAO_Membership();
       $memberDAO->id = $currentMembership['id'];
       $memberDAO->find(TRUE);
@@ -1216,6 +1217,19 @@ AND civicrm_membership.is_test = %2";
       else {
         $logParams['modified_id'] = $currentMembership['contact_id'];
       }
+
+      //Create activity for status change.
+      $allStatus = CRM_Member_BAO_Membership::buildOptions('status_id', 'get');
+      CRM_Activity_BAO_Activity::addActivity($memberDAO,
+        'Change Membership Status',
+        NULL,
+        array(
+          'subject' => "Status changed from {$allStatus[$oldStatus]} to {$allStatus[$status['id']]}",
+          'source_contact_id' => $logParams['modified_id'],
+          'priority_id' => 'Normal',
+        )
+      );
+
       CRM_Member_BAO_MembershipLog::add($logParams, CRM_Core_DAO::$_nullArray);
     }
   }
@@ -1946,6 +1960,7 @@ INNER JOIN  civicrm_contact contact ON ( contact.id = membership.contact_id AND
         if (!empty($currentMembership['id'])) {
           $ids['membership'] = $currentMembership['id'];
         }
+        $memParams['membership_activity_status'] = ($pending || $isPayLater) ? 'Scheduled' : 'Completed';
       }
       //CRM-4555
       if ($pending) {
index 026f7ab70e3ee6e3da5b53019d4625d4e8432358..62788066985c76bd46d628074367a85065e7a0ac 100644 (file)
@@ -187,10 +187,9 @@ class CRM_Member_Form_MembershipType extends CRM_Member_Form_MembershipConfig {
 
     $membershipRecords = FALSE;
     if ($this->_action & CRM_Core_Action::UPDATE) {
-      $membershipType = new CRM_Member_BAO_Membership();
-      $membershipType->membership_type_id = $this->_id;
-      if ($membershipType->find(TRUE)) {
-        $membershipRecords = TRUE;
+      $result = civicrm_api3("Membership", "get", array("membership_type_id" => $this->_id, "options" => array("limit" => 1)));
+      $membershipRecords = ($result["count"] > 0);
+      if ($membershipRecords) {
         $memberRel->freeze();
       }
     }
index ac9b8c434d43961182d502a5631ee793f63239d3..84ace2eba77cc4795a31675dc5a9cd41f9d24c8d 100644 (file)
@@ -428,9 +428,9 @@ class CRM_Member_Page_DashBoard extends CRM_Core_Page {
 
     $this->assign('membershipSummary', $membershipSummary);
     $this->assign('totalCount', $totalCount);
-    $this->assign('month', date('F', $monthStartTs));
+    $this->assign('month', CRM_Utils_Date::customFormat($monthStartTs, '%B'));
     $this->assign('year', date('Y', $monthStartTs));
-    $this->assign('premonth', date('F', strtotime($preMonth)));
+    $this->assign('premonth', CRM_Utils_Date::customFormat($preMonth, '%B'));
     $this->assign('currentMonth', date('F'));
     $this->assign('currentYear', date('Y'));
     $this->assign('isCurrent', $isCurrentMonth);
index 7fe6496a292d3048d585762cb86eb48f3f696fb8..cc664cfec4a707754e57f0192d97c9722f6d00b7 100644 (file)
@@ -54,7 +54,7 @@ class CRM_Member_Tokens extends \Civi\Token\AbstractTokenSubscriber {
         'status' => ts('Membership Status'),
         'type' => ts('Membership Type'),
       ),
-      $this->getCustomTokens('Membership')
+      CRM_Utils_Token::getCustomFieldTokens('Membership')
     ));
   }
 
index 0919c7f07005656bdd88f236200d2573b34e4a9e..e8afa5838a5a705e2b24a717802a04d9302d6496 100644 (file)
@@ -54,24 +54,24 @@ class CRM_Tag_Form_Edit extends CRM_Admin_Form {
    * Build the form object.
    */
   public function buildQuickForm() {
+    $bounceUrl = CRM_Utils_System::url('civicrm/tag');
     if ($this->_action == CRM_Core_Action::DELETE) {
-      $url = CRM_Utils_System::url('civicrm/tag');
       if (!$this->_id) {
         $this->_id = explode(',', CRM_Utils_Request::retrieve('id', 'String'));
       }
       $this->_id = (array) $this->_id;
       if (!$this->_id) {
-        CRM_Core_Error::statusBounce(ts("Unknown tag."), $url);
+        CRM_Core_Error::statusBounce(ts("Unknown tag."), $bounceUrl);
       }
       foreach ($this->_id as $id) {
         if (!CRM_Utils_Rule::positiveInteger($id)) {
-          CRM_Core_Error::statusBounce(ts("Unknown tag."), $url);
+          CRM_Core_Error::statusBounce(ts("Unknown tag."), $bounceUrl);
         }
         if ($tag = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_Tag', $id, 'name', 'parent_id')) {
-          CRM_Core_Error::statusBounce(ts("This tag cannot be deleted. You must delete all its child tags ('%1', etc) prior to deleting this tag.", array(1 => $tag)), $url);
+          CRM_Core_Error::statusBounce(ts("This tag cannot be deleted. You must delete all its child tags ('%1', etc) prior to deleting this tag.", array(1 => $tag)), $bounceUrl);
         }
         if (!CRM_Core_Permission::check('administer reserved tags') && CRM_Core_DAO::getFieldValue('CRM_Core_DAO_Tag', $id, 'is_reserved')) {
-          CRM_Core_Error::statusBounce(ts("You do not have sufficient permission to delete this reserved tag."), $url);
+          CRM_Core_Error::statusBounce(ts("You do not have sufficient permission to delete this reserved tag."), $bounceUrl);
         }
       }
       if (count($this->_id) > 1) {
@@ -79,6 +79,9 @@ class CRM_Tag_Form_Edit extends CRM_Admin_Form {
       }
     }
     else {
+      $adminTagset = CRM_Core_Permission::check('administer Tagsets');
+      $adminReservedTags = CRM_Core_Permission::check('administer reserved tags');
+
       $this->_isTagSet = CRM_Utils_Request::retrieve('tagset', 'Positive', $this);
 
       if (!$this->_isTagSet && $this->_id &&
@@ -86,6 +89,12 @@ class CRM_Tag_Form_Edit extends CRM_Admin_Form {
       ) {
         $this->_isTagSet = TRUE;
       }
+      if ($this->_isTagSet && !$adminTagset) {
+        CRM_Core_Error::statusBounce(ts("You do not have sufficient permission to edit this tagset."), $bounceUrl);
+      }
+      if ($this->_id && !$adminReservedTags && CRM_Core_DAO::getFieldValue('CRM_Core_DAO_Tag', $this->_id, 'is_reserved')) {
+        CRM_Core_Error::statusBounce(ts("You do not have sufficient permission to edit this reserved tag."), $bounceUrl);
+      }
 
       if ($this->_id) {
         $parentId = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_Tag', $this->_id, 'parent_id');
@@ -133,16 +142,10 @@ class CRM_Tag_Form_Edit extends CRM_Admin_Form {
         $this->addSelect('used_for', array('multiple' => TRUE, 'option_url' => NULL));
       }
 
-      $adminTagset = TRUE;
-      if (!CRM_Core_Permission::check('administer Tagsets')) {
-        $adminTagset = FALSE;
-      }
       $this->assign('adminTagset', $adminTagset);
 
-      $adminReservedTags = TRUE;
-      if (!CRM_Core_Permission::check('administer reserved tags')) {
+      if (!$adminReservedTags) {
         $isReserved->freeze();
-        $adminReservedTags = FALSE;
       }
       $this->assign('adminReservedTags', $adminReservedTags);
     }
@@ -162,6 +165,9 @@ class CRM_Tag_Form_Edit extends CRM_Admin_Form {
       $params = array('id' => $cloneFrom);
       CRM_Core_BAO_Tag::retrieve($params, $this->_values);
       $this->_values['name'] .= ' (' . ts('copy') . ')';
+      if (!empty($this->_values['is_reserved']) && !CRM_Core_Permission::check('administer reserved tags')) {
+        $this->_values['is_reserved'] = 0;
+      }
       $defaults = $this->_values;
     }
     if (empty($defaults['color'])) {
diff --git a/CRM/Upgrade/Incremental/sql/4.7.22.mysql.tpl b/CRM/Upgrade/Incremental/sql/4.7.22.mysql.tpl
new file mode 100644 (file)
index 0000000..c4fca4d
--- /dev/null
@@ -0,0 +1 @@
+{* file to handle db changes in 4.7.22 during upgrade *}
index 257a1b18931251b41596f401f6c1cb8eddc512da..402667069954a12eb1389883f0c3a7c906d0bdf9 100644 (file)
@@ -1517,7 +1517,8 @@ class CRM_Utils_Token {
     $key = 'contribution';
     if (self::$_tokens[$key] == NULL) {
       self::$_tokens[$key] = array_keys(array_merge(CRM_Contribute_BAO_Contribution::exportableFields('All'),
-        array('campaign', 'financial_type')
+        array('campaign', 'financial_type'),
+        self::getCustomFieldTokens('Contribution')
       ));
     }
   }
@@ -1797,6 +1798,25 @@ class CRM_Utils_Token {
     );
   }
 
+  /**
+   * Get all custom field tokens of $entity
+   *
+   * @param string $entity
+   * @param bool $usedForTokenWidget
+   *
+   * @return array $customTokens
+   *   return custom field tokens in array('custom_N' => 'label') format
+   */
+  public static function getCustomFieldTokens($entity, $usedForTokenWidget = FALSE) {
+    $customTokens = array();
+    $tokenName = $usedForTokenWidget ? "{contribution.custom_%d}" : "custom_%d";
+    foreach (CRM_Core_BAO_CustomField::getFields($entity) as $id => $info) {
+      $customTokens[sprintf($tokenName, $id)] = $info['label'];
+    }
+
+    return $customTokens;
+  }
+
   /**
    * Formats a token list for the select2 widget
    *
index efe6a656c5d55531385ac462369881bb49afcd8d..0c35bcd1baa4804f5a0c96599f83310ba4ae10bc 100644 (file)
@@ -249,6 +249,7 @@ class Container {
     $dispatcher = new CiviEventDispatcher($container);
     $dispatcher->addListener(SystemInstallEvent::EVENT_NAME, array('\Civi\Core\InstallationCanary', 'check'));
     $dispatcher->addListener(SystemInstallEvent::EVENT_NAME, array('\Civi\Core\DatabaseInitializer', 'initialize'));
+    $dispatcher->addListener(SystemInstallEvent::EVENT_NAME, array('\Civi\Core\LocalizationInitializer', 'initialize'));
     $dispatcher->addListener('hook_civicrm_pre', array('\Civi\Core\Event\PreEvent', 'dispatchSubevent'), 100);
     $dispatcher->addListener('hook_civicrm_post', array('\Civi\Core\Event\PostEvent', 'dispatchSubevent'), 100);
     $dispatcher->addListener('hook_civicrm_post::Activity', array('\Civi\CCase\Events', 'fireCaseChange'));
diff --git a/Civi/Core/LocalizationInitializer.php b/Civi/Core/LocalizationInitializer.php
new file mode 100644 (file)
index 0000000..6eb8935
--- /dev/null
@@ -0,0 +1,104 @@
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | CiviCRM version 4.7                                                |
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC (c) 2004-2015                                |
+ +--------------------------------------------------------------------+
+ | 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        |
+ +--------------------------------------------------------------------+
+ */
+
+namespace Civi\Core;
+
+use Civi;
+use Civi\Core\Event\SystemInstallEvent;
+
+/**
+ * Class LocalizationInitializer
+ * @package Civi\Core
+ */
+class LocalizationInitializer {
+
+  /**
+   * Load the locale settings based on the installation language
+   *
+   * @param \Civi\Core\Event\SystemInstallEvent $event
+   * @throws \CRM_Core_Exception
+   */
+  public static function initialize(SystemInstallEvent $event) {
+
+    // get the current installation language
+    global $tsLocale;
+    $seedLanguage = $tsLocale;
+    if (!$seedLanguage) {
+      return;
+    }
+
+    // get the corresponding settings file if any
+    $localeDir = \CRM_Core_I18n::getResourceDir();
+    $fileName = $localeDir . $seedLanguage . DIRECTORY_SEPARATOR . 'settings.default.json';
+
+    // initalization
+    $settingsParams = array();
+
+    if (file_exists($fileName)) {
+
+      // load the file and parse it
+      $json = file_get_contents($fileName);
+      $settings = json_decode($json, TRUE);
+
+      if (!empty($settings)) {
+        // get all valid settings
+        $results = civicrm_api3('Setting', 'getfields', array());
+        $validSettings = array_keys($results['values']);
+        // add valid settings to params to send to api
+        foreach ($settings as $setting => $value) {
+          if (in_array($setting, $validSettings)) {
+            $settingsParams[$setting] = $value;
+          }
+
+        }
+
+        // ensure we don't mess with multilingual
+        unset($settingsParams['languageLimit']);
+
+        // support for enabled languages (option group)
+        if (isset($settings['languagesOption']) && count($settings['languagesOption']) > 0) {
+          \CRM_Core_BAO_OptionGroup::setActiveValues('languages', $settings['languagesOption']);
+        }
+
+        // set default currency in currencies_enabled (option group)
+        if (isset($settings['defaultCurrency'])) {
+          \CRM_Admin_Form_Setting_Localization::updateEnabledCurrencies(array($settings['defaultCurrency']), $settings['defaultCurrency']);
+        }
+
+      }
+
+    }
+
+    // in any case, enforce the seedLanguage as the default language
+    $settingsParams['lcMessages'] = $seedLanguage;
+
+    // apply the config
+    civicrm_api3('Setting', 'create', $settingsParams);
+
+  }
+
+}
index 1164032de84c384de0cb3d938fef5fd2c50829f5..450955bfd5b0b3cf43a96beebb5625b3f71990c6 100644 (file)
@@ -117,22 +117,6 @@ abstract class AbstractTokenSubscriber implements EventSubscriberInterface {
     }
   }
 
-  /**
-   * Get all custom field tokens of $entity
-   *
-   * @param string $entity
-   * @return array $customTokens
-   *   return custom field tokens in array('custom_N' => 'label') format
-   */
-  public function getCustomTokens($entity) {
-    $customTokens = array();
-    foreach (\CRM_Core_BAO_CustomField::getFields($entity) as $id => $info) {
-      $customTokens["custom_$id"] = $info['label'];
-    }
-
-    return $customTokens;
-  }
-
   /**
    * Alter the query which prepopulates mailing data
    * for scheduled reminders.
index ca739c9606ec98e3041bc16972416995562bfd6c..cdd7012d3c5190677715084f053a16aa985459b5 100644 (file)
@@ -177,7 +177,7 @@ foreach ($langs as $locale => $_) {
   }
 }
 
-// Set the locale (required by CRM_Core_Config)
+// Set the CMS
 // This is mostly sympbolic, since nothing we do during the install
 // really requires CIVICRM_UF to be defined.
 $installTypeToUF = array(
@@ -189,6 +189,7 @@ $installTypeToUF = array(
 $uf = (isset($installTypeToUF[$installType]) ? $installTypeToUF[$installType] : 'Drupal');
 define('CIVICRM_UF', $uf);
 
+// Set the Locale (required by CRM_Core_Config)
 global $tsLocale;
 
 $tsLocale = 'en_US';
@@ -1487,6 +1488,13 @@ class Installer extends InstallRequirements {
         // now enable civicrm module.
         module_enable(array('civicrm', 'civicrmtheme'));
 
+        // SystemInstallEvent will be called from here with the first call of CRM_Core_Config,
+        // which calls Core_BAO_ConfigSetting::applyLocale(), who will default to calling
+        // Civi::settings()->get('lcMessages');
+        // Therefore, we need to pass the seedLanguage before that.
+        global $civicrm_setting;
+        $civicrm_setting['domain']['lcMessages'] = $config['seedLanguage'];
+
         // clear block, page, theme, and hook caches
         drupal_flush_all_caches();
 
@@ -1497,15 +1505,6 @@ class Installer extends InstallRequirements {
         $GLOBALS['user'] = $original_user;
         drupal_save_session(TRUE);
 
-        //change the default language to one chosen
-        if (isset($config['seedLanguage']) && $config['seedLanguage'] != 'en_US') {
-          civicrm_api3('Setting', 'create', array(
-              'domain_id' => 'current_domain',
-              'lcMessages' => $config['seedLanguage'],
-            )
-          );
-        }
-
         $output .= '</ul>';
         $output .= '</div>';
         $output .= '</body>';
index dd1764d3f3d029b17a43a64cd095ad85308d24ff..76cc771d779be118871cc6ee77f999debf105d48 100644 (file)
@@ -142,6 +142,9 @@ return array(
     'pseudoconstant' => array(
       'callback' => 'CRM_Admin_Form_Setting_Localization::getCurrencySymbols',
     ),
+    'on_change' => array(
+      'CRM_Admin_Form_Setting_Localization::onChangeDefaultCurrency',
+    ),
   ),
   'defaultContactCountry' => array(
     'group_name' => 'Localization Preferences',
index 5eca0ce7fa0aab842cd0194030deafeec755d73f..55ea04cd9cdd05bda37af45bd308d7a03b2128e7 100644 (file)
@@ -399,7 +399,7 @@ UNLOCK TABLES;
 
 LOCK TABLES `civicrm_domain` WRITE;
 /*!40000 ALTER TABLE `civicrm_domain` DISABLE KEYS */;
-INSERT INTO `civicrm_domain` (`id`, `name`, `description`, `config_backend`, `version`, `contact_id`, `locales`, `locale_custom_strings`) VALUES (1,'Default Domain Name',NULL,NULL,'4.7.21',1,NULL,'a:1:{s:5:\"en_US\";a:0:{}}');
+INSERT INTO `civicrm_domain` (`id`, `name`, `description`, `config_backend`, `version`, `contact_id`, `locales`, `locale_custom_strings`) VALUES (1,'Default Domain Name',NULL,NULL,'4.7.22',1,NULL,'a:1:{s:5:\"en_US\";a:0:{}}');
 /*!40000 ALTER TABLE `civicrm_domain` ENABLE KEYS */;
 UNLOCK TABLES;
 
index df271f19d194c1ce6f2eaa1359021676af04e905..e13c4c50d23f2839436b903ac302a6b7029d9d81 100644 (file)
  | see the CiviCRM license FAQ at http://civicrm.org/licensing        |
  +--------------------------------------------------------------------+
 *}
-{literal}
-<style>
-  #tagtree .highlighted > span {
-    background-color: #fefca6;
-  }
-  #tagtree .helpicon ins {
-    display: none;
-  }
-  #tagtree ins.jstree-icon {
-    cursor: pointer;
-  }
-</style>
-<script type="text/javascript">
-  (function($, _){{/literal}
-    var entityID='{$entityID}',
-      entityTable='{$entityTable}',
-      $form = $('form.{$form.formClass}');
-    {literal}
-
-    $(function() {
-      function highlightSelected() {
-        $("ul input:not(:checked)", '#tagtree').each(function () {
-          $(this).closest("li").removeClass('highlighted');
-        });
-        $("ul input:checked", '#tagtree').each(function () {
-          $(this).parents("li[id^=tag]").addClass('highlighted');
-        });
-      }
-      highlightSelected();
-
-      $("#tagtree input").change(function(){
-        highlightSelected();
-      });
-
-      var childTag = "{/literal}{$loadjsTree}{literal}";
-      if (childTag) {
-        //load js tree.
-        $("#tagtree").jstree({
-          plugins : ["themes", "html_data"],
-          themes: {
-            "theme": 'classic',
-            "dots": false,
-            "icons": false,
-            "url": CRM.config.resourceBase + 'packages/jquery/plugins/jstree/themes/classic/style.css'
-          }
-        });
-      }
-         {/literal}
-      {if !empty($permission) && $permission neq 'edit'}
-        {literal}
-          $("#tagtree input").prop('disabled', true);
-        {/literal}
-      {/if}
-      {literal}
-    });
-  })(CRM.$, CRM._);
-  {/literal}
-</script>
-
 {if $title}
 <div class="crm-accordion-wrapper crm-tagGroup-accordion collapsed">
   <div class="crm-accordion-header">{$title}</div>
 {/if}
     <table class="form-layout-compressed{if $context EQ 'profile'} crm-profile-tagsandgroups{/if}">
       <tr>
+        {if !$type || $type eq 'tag'}
+          <td>
+            <div class="crm-section tag-section">
+              {if $title}{$form.tag.label}{/if}
+              {$form.tag.html}
+            </div>
+            {if $context NEQ 'profile'}
+              {include file="CRM/common/Tagset.tpl"}
+            {/if}
+          </td>
+        {/if}
         {if !$type || $type eq 'group'}
           <td>
             {if $groupElementType eq 'select'}
-              <span class="label">{if $title}{$form.group.label}{/if}</span>
+              <div class="crm-section group-section">
+              {if $title}{$form.group.label}{/if}
               {$form.group.html}
+            </div>
             {else}
               {foreach key=key item=item from=$tagGroup.group}
                 <div class="group-wrapper">
             {/if}
           </td>
         {/if}
-        {if (!$type || $type eq 'tag') && $tree}
-          <td width="70%">{if $title}<span class="label">{$form.tag.label}</span>{/if}
-            <div id="tagtree">
-              {include file="CRM/Contact/Form/Edit/Tagtree.tpl" level=1}
-            </div>
-          </td>
-          <tr><td>{include file="CRM/common/Tagset.tpl"}</td></tr>
-        {/if}
       </tr>
     </table>
 {if $title}
index 6d0b338fecd6cd365f200ce99db3d76efc16a1d4..5a3e24e99747b1991ce7119a854ddeab9a6987ec 100644 (file)
     }
   }
 
-  function showHideAmountBlock( element, elementName )
-        {
-     // show / hide when amount section is active check/uncheck.
-
-     var priceSetID = {/literal}'{$priceSetID}'{literal};
-
-     switch ( elementName ) {
+  function showHideAmountBlock(element, elementName) {
+    // show / hide when amount section is active check/uncheck.
+    var priceSetID = {/literal}'{$priceSetID}'{literal};
+    switch (elementName) {
       case 'price_set_id':
-           if ( element ) {
-               cj('#amountFields').hide();
-           } else {
-               cj('#amountFields').show();
-           }
-           cj("#amount_block_is_active").prop('checked', true );
-      break;
-
-      case 'is_pledge_active' :
-      case 'is_allow_other_amount' :
-           if ( element.checked ) {
-               if ( priceSetID ) cj( "#price_set_id" ).val( '' );
-             cj('#amountFields').show();
-                 }
-           cj("#amount_block_is_active").prop('checked', true );
-      break;
-
-         case 'amount_block_is_active' :
-           if ( element.checked ) {
-               if ( priceSetID ) {
-           cj('#amountFields').hide();
-           cj( "#price_set_id" ).val( priceSetID );
-        } else {
-           cj('#amountFields').show();
-           cj( "#price_set_id" ).val( '' );
+        if (element) {
+          cj('#amountFields').hide();
         }
-        cj('#priceSet, #recurringFields').show();
-           } else {
-            cj( "#price_set_id" ).val( '' );
-            cj('#amountFields, #priceSet, #recurringFields').hide();
-           }
-      break;
-     }
-   }
+        break;
+
+      case 'is_pledge_active':
+      case 'is_allow_other_amount':
+        if (element.checked) {
+          if (priceSetID) cj( "#price_set_id" ).val('');
+          cj('#amountFields').show();
+        }
+        cj("#amount_block_is_active").prop('checked', true );
+        break;
+
+      case 'amount_block_is_active':
+        if (element.checked) {
+          if (priceSetID) {
+            cj('#amountFields').hide();
+            cj( "#price_set_id" ).val(priceSetID);
+          }
+          else {
+            cj('#amountFields').show();
+            cj( "#price_set_id" ).val('');
+          }
+          cj('#priceSet, #recurringFields').show();
+        }
+        else {
+          cj( "#price_set_id" ).val('');
+          cj('#amountFields, #priceSet, #recurringFields').hide();
+        }
+        break;
+      }
+    }
 
     function showRecurring( paymentProcessorIds ) {
         var display = true;
index f2eba025f6a53ffbb1443d56f38927526690c929..a3d2894ca98f4c6c309dafff85d190745383d842 100644 (file)
@@ -29,7 +29,7 @@
           {if $relatedContributions}
            {ts 1=$title}You cannot delete this Contribution Page because it has already been used to submit a contribution or membership payment. It is recommended that your disable the page instead of deleting it, to preserve the integrity of your contribution records. If you do want to completely delete this contribution page, you first need to search for and delete all of the contribution transactions associated with this page in CiviContribute.{/ts}
           {else}
-           WARNING: Are you sure you want to Delete the selected Contribution Page? A Delete operation cannot be undone. Do you want to continue?
+           {ts}WARNING: Are you sure you want to Delete the selected Contribution Page? A Delete operation cannot be undone. Do you want to continue?{/ts}
         {/if}
       </div>
 <div class="form-item">
index 7b7725af99f677912f14511af81265042cd8cef6..dd4782168e81cc12cf18a9cb9e356650abe97268 100644 (file)
               {if $n eq 'email_greeting' or  $n eq 'postal_greeting' or $n eq 'addressee'}
                 {include file="CRM/Profile/Form/GreetingType.tpl"}
               {elseif ( $n eq 'group' && $form.group ) || ( $n eq 'tag' && $form.tag )}
-                {include file="CRM/Contact/Form/Edit/TagsAndGroups.tpl" type=$n context="profile"}
+                {include file="CRM/Contact/Form/Edit/TagsAndGroups.tpl" type=$n context="profile" tableLayout=1}
               {elseif ( $form.$n.name eq 'image_URL' )}
                 {$form.$n.html}
                 {if !empty($imageURL)}
index c30187d1b6018dd14c27c07b63947070c1d3e049..81729b5fd8ac3452b9a2c90a45218ec0545fa345 100644 (file)
   div.tag-info input[type=color] {
     cursor: pointer;
   }
+  div.tag-info input[disabled] {
+    cursor: default;
+  }
   div.tag-info .tdl {
     font-weight: bold;
     color: #999;
 <script type="text/template" id="oneSelectedTpl">
   <div class="crm-entity" data-entity="Tag" data-id="<%= id %>">
     <h4>
-      <input type="color" value="<%= data.color %>" title="{ts}Select color{/ts}"/>
-      <span class="crm-editable" data-field="name"><%- text %></span>
+      <input type="color" value="<%= data.color %>" <% if (!data.is_reserved || adminReserved) {ldelim} %>title="{ts}Select color{/ts}" <% {rdelim} else {ldelim} %>disabled<% {rdelim} %> />
+      <span class="<% if (!data.is_reserved || adminReserved) {ldelim} %>crm-editable<% {rdelim} %>" data-field="name"><%- text %></span>
     </h4>
     <hr />
     <div><span class="tdl">{ts}Description:{/ts}</span>
-      <span class="crm-editable" data-field="description"><%- data.description %></span>
+      <span class="<% if (!data.is_reserved || adminReserved) {ldelim} %>crm-editable<% {rdelim} %>" data-field="description"><%- data.description %></span>
     </div>
     <div><span class="tdl">{ts}Selectable:{/ts}</span>
-      <span class="crm-editable" data-field="is_selectable" data-type="select"><% if (data.is_selectable) {ldelim} %> {ts}Yes{/ts} <% {rdelim} else {ldelim} %> {ts}No{/ts} <% {rdelim} %></span>
+      <span class="<% if (!data.is_reserved || adminReserved) {ldelim} %>crm-editable<% {rdelim} %>" data-field="is_selectable" data-type="select"><% if (data.is_selectable) {ldelim} %> {ts}Yes{/ts} <% {rdelim} else {ldelim} %> {ts}No{/ts} <% {rdelim} %></span>
     </div>
     <div><span class="tdl">{ts}Reserved:{/ts}</span>
       <span class="<% if (adminReserved) {ldelim} %>crm-editable<% {rdelim} %>" data-field="is_reserved" data-type="select"><% if (data.is_reserved) {ldelim} %> {ts}Yes{/ts} <% {rdelim} else {ldelim} %> {ts}No{/ts} <% {rdelim} %></span>
       <div>
         <span class="tdl">{ts}Used For:{/ts}</span>
         {literal}
-          <span class="crm-editable-enabled used-for-toggle">
+          <span class="<% if (!data.is_reserved || adminReserved) { %>crm-editable-enabled used-for-toggle<% } %>">
             <% if (!data.used_for.length) { %><i class="crm-i fa-pencil crm-editable-placeholder"></i><% } %>
             <% _.forEach(data.used_for, function(key, i) { %><%- (i ? ', ' : '') + usedFor[key] %><% }) %>
           </span>
index cbc02de1b601732374f06aeb32460b6b8e73465c..acc0eb8cfee4ea0a627c75d492bd775afda7dce1 100644 (file)
@@ -210,6 +210,89 @@ class CRM_Contact_Page_AjaxTest extends CiviUnitTestCase {
     $this->assertEquals(array('data' => array(), 'recordsTotal' => 0, 'recordsFiltered' => 0), $result);
   }
 
+  /**
+   * CRM-20621 : Test to check usage count of Tag tree
+   */
+  public function testGetTagTree() {
+    $contacts = array();
+    // create three contacts
+    for ($i = 0; $i < 3; $i++) {
+      $contacts[] = $this->individualCreate();
+    }
+
+    // Create Tag called as 'Parent Tag'
+    $parentTag = $this->tagCreate(array(
+      'name' => 'Parent Tag',
+      'used_for' => 'civicrm_contact',
+    ));
+    //assign first contact to parent tag
+    $params = array(
+      'entity_id' => $contacts[0],
+      'entity_table' => 'civicrm_contact',
+      'tag_id' => $parentTag['id'],
+    );
+    // TODO: EntityTag.create API is not working
+    CRM_Core_BAO_EntityTag::add($params);
+
+    // Create child Tag of $parentTag
+    $childTag1 = $this->tagCreate(array(
+      'name' => 'Child Tag Level 1',
+      'parent_id' => $parentTag['id'],
+      'used_for' => 'civicrm_contact',
+    ));
+    //assign contact to this level 1 child tag
+    $params = array(
+      'entity_id' => $contacts[1],
+      'entity_table' => 'civicrm_contact',
+      'tag_id' => $childTag1['id'],
+    );
+    CRM_Core_BAO_EntityTag::add($params);
+
+    // Create child Tag of $childTag1
+    $childTag2 = $this->tagCreate(array(
+      'name' => 'Child Tag Level 2',
+      'parent_id' => $childTag1['id'],
+      'used_for' => 'civicrm_contact',
+    ));
+    //assign contact to this level 2 child tag
+    $params = array(
+      'entity_id' => $contacts[2],
+      'entity_table' => 'civicrm_contact',
+      'tag_id' => $childTag2['id'],
+    );
+    CRM_Core_BAO_EntityTag::add($params);
+
+    // CASE I : check the usage count of parent tag which need to be 1
+    //  as the one contact added
+    $_REQUEST['is_unit_test'] = TRUE;
+    $parentTagTreeResult = CRM_Admin_Page_AJAX::getTagTree();
+    foreach ($parentTagTreeResult as $result) {
+      if ($result['id'] == $parentTag['id']) {
+        $this->assertEquals(1, $result['data']['usages']);
+      }
+    }
+
+    // CASE 2 : check the usage count of level 1 child tag, which needs to be 1
+    //  as it should include the count of added one contact
+    $_GET['parent_id'] = $parentTag['id'];
+    $childTagTree = CRM_Admin_Page_AJAX::getTagTree();
+    $this->assertEquals(1, $childTagTree[0]['data']['usages']);
+
+    // CASE 2 : check the usage count of child tag at level 2
+    //which needs to be 1 as it has no child tag
+    $_GET['parent_id'] = $childTag1['id'];
+    $childTagTree = CRM_Admin_Page_AJAX::getTagTree();
+    $this->assertEquals(1, $childTagTree[0]['data']['usages']);
+
+    //cleanup
+    foreach ($contacts as $id) {
+      $this->callAPISuccess('Contact', 'delete', array('id' => $id));
+    }
+    $this->callAPISuccess('Tag', 'delete', array('id' => $childTag2['id']));
+    $this->callAPISuccess('Tag', 'delete', array('id' => $childTag1['id']));
+    $this->callAPISuccess('Tag', 'delete', array('id' => $parentTag['id']));
+  }
+
   /**
    * Test to check contact reference field
    */
index 4441fd37569a262805e01c021d263f89fdbe0070..f24154d1b80f1a62b8001ef71849e9d0c7b3fd78 100644 (file)
@@ -560,7 +560,35 @@ class CRM_Contribute_Form_ContributionTest extends CiviUnitTestCase {
     $this->callAPISuccessGetSingle('Address', array(
       'id' => $contribution['address_id'],
     ));
+  }
 
+  /**
+   * CRM-20745: Test the submit function correctly sets the
+   * receive date for recurring contribution.
+   */
+  public function testSubmitCreditCardWithRecur() {
+    $form = new CRM_Contribute_Form_Contribution();
+    $receiveDate = date('m/d/Y', strtotime('+1 month'));
+    $form->testSubmit(array(
+      'total_amount' => 50,
+      'financial_type_id' => 1,
+      'is_recur' => 1,
+      'frequency_interval' => 2,
+      'frequency_unit' => 'month',
+      'installments' => 2,
+      'receive_date' => $receiveDate,
+      'receive_date_time' => '11:27PM',
+      'contact_id' => $this->_individualId,
+      'payment_instrument_id' => array_search('Credit Card', $this->paymentInstruments),
+      'payment_processor_id' => $this->paymentProcessorID,
+      'credit_card_exp_date' => array('M' => 5, 'Y' => 2025),
+      'credit_card_number' => '411111111111111',
+      'billing_city-5' => 'Vancouver',
+    ), CRM_Core_Action::ADD,
+      'live'
+    );
+    $contribution = $this->callAPISuccessGetSingle('Contribution', array('return' => 'receive_date'));
+    $this->assertEquals(date("m/d/Y", strtotime($contribution['receive_date'])), $receiveDate);
   }
 
   /**
index 573ddaeb6d6fd6eef5835e8a8cfccdd45aa5e6a6..e51ff0141ac1445066b299547150bbd096fd3b8b 100644 (file)
@@ -76,6 +76,8 @@ class CRM_Core_Payment_PayPalProIPNTest extends CiviUnitTestCase {
    */
   public function testIPNPaymentRecurSuccess() {
     $this->setupRecurringPaymentProcessorTransaction();
+    global $_GET;
+    $_GET = $this->getPaypalProRecurTransaction();
     $paypalIPN = new CRM_Core_Payment_PayPalProIPN($this->getPaypalProRecurTransaction());
     $paypalIPN->main();
     $contribution = $this->callAPISuccess('contribution', 'getsingle', array('id' => $this->_contributionID));
@@ -338,7 +340,7 @@ class CRM_Core_Payment_PayPalProIPNTest extends CiviUnitTestCase {
       'amount_per_cycle' => '15.00',
       'mc_gross' => '15.00',
       'payment_date' => '03:59:05 Jul 14, 2013 PDT',
-      'rp_invoice_id' => 'i=' . $this->_invoiceID . '&m=contribute&c=' . $this->_contactID . '&r=' . $this->_contributionRecurID . '&b=' . $this->_contributionID . '&p=' . $this->_contributionPageID,
+      'rp_invoice_id' => 'i=' . $this->_invoiceID . '&m=contribute&c=' . $this->_contactID . '&r=' . $this->_contributionRecurID . '&b=' . $this->_contributionID . '&p=null',
       'payment_status' => 'Completed',
       'business' => 'nowhere@civicrm.org',
       'last_name' => 'Roberty',
index 7d81aac3afebe6c274fbe24c7e017853f14c4379..8356be760e9c5069785b504cd7965fc39a302b89 100644 (file)
@@ -2473,7 +2473,7 @@ class api_v3_ContributionTest extends CiviUnitTestCase {
 
     $this->mut->checkMailLog(array(
       'is_recur:::1',
-      'cancelSubscriptionUrl:::http://dummy.com',
+      'cancelSubscriptionUrl:::' . CIVICRM_UF_BASEURL,
     ));
     $this->mut->stop();
     $this->revertTemplateToReservedTemplate();
index 7e2579e3f3572b4f55c2eba52b0cd52870473242..3738afe9281499bdd973c19c719bf9e59bf98dde 100644 (file)
@@ -848,6 +848,19 @@ class api_v3_MembershipTest extends CiviUnitTestCase {
     );
 
     $result = $this->callAPISuccess('membership', 'create', $params);
+
+    //Update Status and check activities created.
+    $updateStatus = array(
+      'id' => $result['id'],
+      'status_id' => CRM_Core_PseudoConstant::getKey('CRM_Member_BAO_Membership', 'status_id', 'Cancelled'),
+    );
+    $this->callAPISuccess('Membership', 'create', $updateStatus);
+    $activities = CRM_Activity_BAO_Activity::getContactActivity($this->_contactID);
+    $this->assertEquals(2, count($activities));
+    $activityNames = array_flip(CRM_Utils_Array::collect('activity_name', $activities));
+    $this->assertArrayHasKey('Membership Signup', $activityNames);
+    $this->assertArrayHasKey('Change Membership Status', $activityNames);
+
     $this->callAPISuccess('Membership', 'Delete', array(
       'id' => $result['id'],
     ));
index b989623d0cbbfdcf423e92c5770e46bce6e76ec8..4c5afec5233f7dd8efc1b1db98c2e076b718b7d7 100644 (file)
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="iso-8859-1" ?>
 <version>
-  <version_no>4.7.21</version_no>
+  <version_no>4.7.22</version_no>
 </version>