diff --git a/civicrm/CRM/Contribute/BAO/Contribution.php b/civicrm/CRM/Contribute/BAO/Contribution.php
index 79fdeb3ffb5f55f7a6cafdf417f500a3ef41b576..6e485a5922290048b5c49ecd8bba8dc19a141917 100644
--- a/civicrm/CRM/Contribute/BAO/Contribution.php
+++ b/civicrm/CRM/Contribute/BAO/Contribution.php
@@ -129,6 +129,10 @@ class CRM_Contribute_BAO_Contribution extends CRM_Contribute_DAO_Contribution {
     if (!empty($params['skipCleanMoney'])) {
       unset($moneyFields[0]);
     }
+    else {
+      // @todo put a deprecated here - this should be done in the form layer.
+      $params['skipCleanMoney'] = FALSE;
+    }
 
     foreach ($moneyFields as $field) {
       if (isset($params[$field])) {
@@ -4205,6 +4209,11 @@ WHERE eft.financial_trxn_id IN ({$trxnId}, {$baseTrxnId['financialTrxnId']})
   public static function checkTaxAmount($params, $isLineItem = FALSE) {
     $taxRates = CRM_Core_PseudoConstant::getTaxRates();
 
+    // This function should be only called after standardisation (removal of
+    // thousand separator & using a decimal point for cents separator.
+    // However, we don't know if that is always true :-(
+    // There is a deprecation notice tho :-)
+    $unknownIfMoneyIsClean = empty($params['skipCleanMoney']) && !$isLineItem;
     // Update contribution.
     if (!empty($params['id'])) {
       // CRM-19126 and CRM-19152 If neither total or financial_type_id are set on an update
@@ -4251,7 +4260,7 @@ WHERE eft.financial_trxn_id IN ({$trxnId}, {$baseTrxnId['financialTrxnId']})
       empty($params['skipLineItem']) && !$isLineItem
     ) {
       $taxRateParams = $taxRates[$params['financial_type_id']];
-      $taxAmount = CRM_Contribute_BAO_Contribution_Utils::calculateTaxAmount(CRM_Utils_Array::value('total_amount', $params), $taxRateParams);
+      $taxAmount = CRM_Contribute_BAO_Contribution_Utils::calculateTaxAmount(CRM_Utils_Array::value('total_amount', $params), $taxRateParams, $unknownIfMoneyIsClean);
       $params['tax_amount'] = round($taxAmount['tax_amount'], 2);
 
       // Get Line Item on update of contribution
@@ -4283,9 +4292,9 @@ WHERE eft.financial_trxn_id IN ({$trxnId}, {$baseTrxnId['financialTrxnId']})
     }
     else {
       // update line item of contrbution
-      if (isset($params['financial_type_id']) && array_key_exists($params['financial_type_id'], $taxRates) && $isLineItem) {
+      if (isset($params['financial_type_id']) && array_key_exists($params['financial_type_id'], $taxRates)  && $isLineItem) {
         $taxRate = $taxRates[$params['financial_type_id']];
-        $taxAmount = CRM_Contribute_BAO_Contribution_Utils::calculateTaxAmount($params['line_total'], $taxRate);
+        $taxAmount = CRM_Contribute_BAO_Contribution_Utils::calculateTaxAmount($params['line_total'], $taxRate, $unknownIfMoneyIsClean);
         $params['tax_amount'] = round($taxAmount['tax_amount'], 2);
       }
     }
diff --git a/civicrm/CRM/Contribute/BAO/Contribution/Utils.php b/civicrm/CRM/Contribute/BAO/Contribution/Utils.php
index 3930addfda79f1f62fe04e001cffed6f5735a30c..ce9caf1ab3f7fb792b8a3bc0148c5b28dbea1f2b 100644
--- a/civicrm/CRM/Contribute/BAO/Contribution/Utils.php
+++ b/civicrm/CRM/Contribute/BAO/Contribution/Utils.php
@@ -114,6 +114,9 @@ class CRM_Contribute_BAO_Contribution_Utils {
         $contributionParams['payment_instrument_id'] = $paymentParams['payment_instrument_id'] = $form->_paymentProcessor['payment_instrument_id'];
       }
 
+      // @todo this is the wrong place for this - it should be done as close to form submission
+      // as possible
+      $paymentParams['amount'] = CRM_Utils_Rule::cleanMoney($paymentParams['amount']);
       $contribution = CRM_Contribute_Form_Contribution_Confirm::processFormContribution(
         $form,
         $paymentParams,
@@ -468,15 +471,24 @@ LIMIT 1
    *   Amount of field.
    * @param float $taxRate
    *   Tax rate of selected financial account for field.
+   * @param bool $ugWeDoNotKnowIfItNeedsCleaning_Help
+   *   This should ALWAYS BE FALSE and then be removed. A 'clean' money string uses a standardised format
+   *   such as '1000.99' for one thousand $/Euro/CUR and ninety nine cents/units.
+   *   However, we are in the habit of not necessarily doing that so need to grandfather in
+   *   the new expectation.
    *
    * @return array
    *   array of tax amount
    *
    */
-  public static function calculateTaxAmount($amount, $taxRate) {
+  public static function calculateTaxAmount($amount, $taxRate, $ugWeDoNotKnowIfItNeedsCleaning_Help = FALSE) {
     $taxAmount = array();
+    if ($ugWeDoNotKnowIfItNeedsCleaning_Help) {
+      Civi::log()->warning('Deprecated function, make sure money is in usable format before calling this.', array('civi.tag' => 'deprecated'));
+      $amount = CRM_Utils_Rule::cleanMoney($amount);
+    }
     // There can not be any rounding at this stage - as this is prior to quantity multiplication
-    $taxAmount['tax_amount'] = ($taxRate / 100) * CRM_Utils_Rule::cleanMoney($amount);
+    $taxAmount['tax_amount'] = ($taxRate / 100) * $amount;
 
     return $taxAmount;
   }
diff --git a/civicrm/CRM/Contribute/Form/Contribution/Confirm.php b/civicrm/CRM/Contribute/Form/Contribution/Confirm.php
index abddc63b4772353c7f1ca2c745e1a6d0447b3db6..3a7028a46fc5c326fd7d87325fdf341deed07c18 100644
--- a/civicrm/CRM/Contribute/Form/Contribution/Confirm.php
+++ b/civicrm/CRM/Contribute/Form/Contribution/Confirm.php
@@ -158,7 +158,6 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr
    *
    * @param array $params
    * @param int $financialTypeID
-   * @param float $nonDeductibleAmount
    * @param bool $pending
    * @param array $paymentProcessorOutcome
    * @param string $receiptDate
@@ -167,13 +166,11 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr
    * @return array
    */
   public static function getContributionParams(
-    $params, $financialTypeID, $nonDeductibleAmount, $pending,
+    $params, $financialTypeID, $pending,
     $paymentProcessorOutcome, $receiptDate, $recurringContributionID) {
     $contributionParams = array(
       'financial_type_id' => $financialTypeID,
       'receive_date' => (CRM_Utils_Array::value('receive_date', $params)) ? CRM_Utils_Date::processDate($params['receive_date']) : date('YmdHis'),
-      'non_deductible_amount' => $nonDeductibleAmount,
-      'total_amount' => $params['amount'],
       'tax_amount' => CRM_Utils_Array::value('tax_amount', $params),
       'amount_level' => CRM_Utils_Array::value('amount_level', $params),
       'invoice_id' => $params['invoiceID'],
@@ -202,10 +199,6 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr
       );
     }
 
-    // CRM-4038: for non-en_US locales, CRM_Contribute_BAO_Contribution::add() expects localised amounts
-    $contributionParams['non_deductible_amount'] = trim(CRM_Utils_Money::format($contributionParams['non_deductible_amount'], ' '));
-    $contributionParams['total_amount'] = trim(CRM_Utils_Money::format($contributionParams['total_amount'], ' '));
-
     if ($recurringContributionID) {
       $contributionParams['contribution_recur_id'] = $recurringContributionID;
     }
@@ -299,7 +292,7 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr
     // lineItem isn't set until Register postProcess
     $this->_lineItem = $this->get('lineItem');
     $this->_ccid = $this->get('ccid');
-    $this->_paymentProcessor = $this->get('paymentProcessor');
+
     $this->_params = $this->controller->exportValues('Main');
     $this->_params['ip_address'] = CRM_Utils_System::ipAddress();
     $this->_params['amount'] = $this->get('amount');
@@ -950,7 +943,6 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr
     $params['is_recur'] = $isRecur;
     $params['payment_instrument_id'] = CRM_Utils_Array::value('payment_instrument_id', $contributionParams);
     $recurringContributionID = self::processRecurringContribution($form, $params, $contactID, $financialType);
-    $nonDeductibleAmount = self::getNonDeductibleAmount($params, $financialType, $online, $form);
 
     $now = date('YmdHis');
     $receiptDate = CRM_Utils_Array::value('receipt_date', $params);
@@ -960,10 +952,15 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr
 
     if (isset($params['amount'])) {
       $contributionParams = array_merge(self::getContributionParams(
-        $params, $financialType->id, $nonDeductibleAmount, TRUE,
+        $params, $financialType->id, TRUE,
         $result, $receiptDate,
         $recurringContributionID), $contributionParams
       );
+      $contributionParams['non_deductible_amount'] = self::getNonDeductibleAmount($params, $financialType, $online, $form);
+      $contributionParams['skipCleanMoney'] = TRUE;
+      // @todo this is the wrong place for this - it should be done as close to form submission
+      // as possible
+      $contributionParams['total_amount'] = $params['amount'];
       $contribution = CRM_Contribute_BAO_Contribution::add($contributionParams);
 
       $invoiceSettings = Civi::settings()->get('contribution_invoice_settings');
@@ -1988,6 +1985,7 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr
     }
 
     $priceFields = $priceFields[$priceSetID]['fields'];
+    $lineItems = array();
     CRM_Price_BAO_PriceSet::processAmount($priceFields, $paramsProcessedForForm, $lineItems, 'civicrm_contribution');
     $form->_lineItem = array($priceSetID => $lineItems);
     $membershipPriceFieldIDs = array();
diff --git a/civicrm/CRM/Contribute/Form/ContributionBase.php b/civicrm/CRM/Contribute/Form/ContributionBase.php
index 216c8149e25292794bb5b1ec5d836c92669a4506..933128ea3208145f49faa664a99b55728f0c6d8b 100644
--- a/civicrm/CRM/Contribute/Form/ContributionBase.php
+++ b/civicrm/CRM/Contribute/Form/ContributionBase.php
@@ -294,6 +294,9 @@ class CRM_Contribute_Form_ContributionBase extends CRM_Core_Form {
     $this->_fields = $this->get('fields');
     $this->_bltID = $this->get('bltID');
     $this->_paymentProcessor = $this->get('paymentProcessor');
+    if (!$this->_paymentProcessor) {
+      $this->_paymentProcessor = array('object' => Civi\Payment\System::singleton()->getById(0));
+    }
     $this->_priceSetId = $this->get('priceSetId');
     $this->_priceSet = $this->get('priceSet');
 
diff --git a/civicrm/CRM/Core/InnoDBIndexer.php b/civicrm/CRM/Core/InnoDBIndexer.php
index 5c2c8fb44d201fa5c7354b8c1849dfd78276c5c0..6d7ae283d4b84f9db76df5b4e47a927b9550ef37 100644
--- a/civicrm/CRM/Core/InnoDBIndexer.php
+++ b/civicrm/CRM/Core/InnoDBIndexer.php
@@ -91,6 +91,10 @@ class CRM_Core_InnoDBIndexer {
    *   Specification of the setting (per *.settings.php).
    */
   public static function onToggleFts($oldValue, $newValue, $metadata) {
+    if (empty($oldValue) && empty($newValue)) {
+      return;
+    }
+
     $indexer = CRM_Core_InnoDBIndexer::singleton();
     $indexer->setActive($newValue);
     $indexer->fixSchemaDifferences();
diff --git a/civicrm/CRM/Group/Form/Edit.php b/civicrm/CRM/Group/Form/Edit.php
index 95c0df5cb0d3007a5eb532b3de75477f3d6ccfff..55b9478a0ed132ed7451164110c23b6d9753cd9e 100644
--- a/civicrm/CRM/Group/Form/Edit.php
+++ b/civicrm/CRM/Group/Form/Edit.php
@@ -378,6 +378,11 @@ WHERE  title = %1
         $params['group_organization'] = $this->_groupOrganizationID;
       }
 
+      // CRM-21431 If all group_type are unchecked, the change will not be saved otherwise.
+      if (!isset($params['group_type'])) {
+        $params['group_type'] = array();
+      }
+
       $params['is_reserved'] = CRM_Utils_Array::value('is_reserved', $params, FALSE);
 
       $params['custom'] = CRM_Core_BAO_CustomField::postProcess($params,
diff --git a/civicrm/CRM/Price/BAO/LineItem.php b/civicrm/CRM/Price/BAO/LineItem.php
index 505642d60232b0103f55578c7bee9623db6ee42a..1a90a9d3e8e16b52a5d4577b55aeb8471e372838 100644
--- a/civicrm/CRM/Price/BAO/LineItem.php
+++ b/civicrm/CRM/Price/BAO/LineItem.php
@@ -341,6 +341,11 @@ WHERE li.contribution_id = %1";
    *   this is
    *                          lineItem array)
    * @param string $amount_override
+   *   Amount override must be in format 1000.00 - ie no thousand separator & if
+   *   a decimal point is used it should be a decimal
+   *
+   * @todo - this parameter is only used for partial payments. It's unclear why a partial
+   *  payment would change the line item price.
    */
   public static function format($fid, $params, $fields, &$values, $amount_override = NULL) {
     if (empty($params["price_{$fid}"])) {
@@ -364,10 +369,6 @@ WHERE li.contribution_id = %1";
     foreach ($params["price_{$fid}"] as $oid => $qty) {
       $price = $amount_override === NULL ? $options[$oid]['amount'] : $amount_override;
 
-      // lets clean the price in case it is not yet cleant
-      // CRM-10974
-      $price = CRM_Utils_Rule::cleanMoney($price);
-
       $participantsPerField = CRM_Utils_Array::value('count', $options[$oid], 0);
 
       $values[$oid] = array(
diff --git a/civicrm/CRM/Price/Page/Field.php b/civicrm/CRM/Price/Page/Field.php
index 536195af8fc98829a84029ecc03e743c0f529ad4..68ebdc7e4a38fa65f43a906fd0d2233a7397c0ff 100644
--- a/civicrm/CRM/Price/Page/Field.php
+++ b/civicrm/CRM/Price/Page/Field.php
@@ -149,7 +149,7 @@ class CRM_Price_Page_Field extends CRM_Core_Page {
           $getTaxDetails = TRUE;
         }
         if (isset($priceField[$priceFieldBAO->id]['tax_rate'])) {
-          $taxAmount = CRM_Contribute_BAO_Contribution_Utils::calculateTaxAmount($priceField[$priceFieldBAO->id]['price'], $priceField[$priceFieldBAO->id]['tax_rate']);
+          $taxAmount = CRM_Contribute_BAO_Contribution_Utils::calculateTaxAmount($priceField[$priceFieldBAO->id]['price'], $priceField[$priceFieldBAO->id]['tax_rate'], TRUE);
           $priceField[$priceFieldBAO->id]['tax_amount'] = $taxAmount['tax_amount'];
         }
       }
diff --git a/civicrm/CRM/Price/Page/Option.php b/civicrm/CRM/Price/Page/Option.php
index 0724ebec9b0a4c1cdaf22050687165b65b22b6b6..eab7c0c560c070c0196df8065103cb32595dafd3 100644
--- a/civicrm/CRM/Price/Page/Option.php
+++ b/civicrm/CRM/Price/Page/Option.php
@@ -158,7 +158,7 @@ class CRM_Price_Page_Option extends CRM_Core_Page {
         if ($invoicing && isset($customOption[$id]['tax_rate'])) {
           $getTaxDetails = TRUE;
         }
-        $taxAmount = CRM_Contribute_BAO_Contribution_Utils::calculateTaxAmount($customOption[$id]['amount'], $customOption[$id]['tax_rate']);
+        $taxAmount = CRM_Contribute_BAO_Contribution_Utils::calculateTaxAmount($customOption[$id]['amount'], $customOption[$id]['tax_rate'], TRUE);
         $customOption[$id]['tax_amount'] = $taxAmount['tax_amount'];
       }
       if (!empty($values['financial_type_id'])) {
diff --git a/civicrm/CRM/Upgrade/Form.php b/civicrm/CRM/Upgrade/Form.php
index 76aa53a26fcb093d173673fded70a44709843a0d..10b87ead2e8b92d3456eac22eac38212162f9d06 100644
--- a/civicrm/CRM/Upgrade/Form.php
+++ b/civicrm/CRM/Upgrade/Form.php
@@ -48,9 +48,9 @@ class CRM_Upgrade_Form extends CRM_Core_Form {
   const MINIMUM_UPGRADABLE_VERSION = '4.0.8';
 
   /**
-   * Minimum php version we support
+   * Minimum php version required to run (equal to or lower than the minimum install version)
    */
-  const MINIMUM_PHP_VERSION = '5.3.4';
+  const MINIMUM_PHP_VERSION = '5.4';
 
   protected $_config;
 
diff --git a/civicrm/CRM/Upgrade/Incremental/General.php b/civicrm/CRM/Upgrade/Incremental/General.php
index a2add6413185808b60912b781ed7328152363ce7..56a80610d28ebac6b84f09c9d6f0d3efecb4aca9 100644
--- a/civicrm/CRM/Upgrade/Incremental/General.php
+++ b/civicrm/CRM/Upgrade/Incremental/General.php
@@ -41,25 +41,19 @@ class CRM_Upgrade_Incremental_General {
   /**
    * The recommended PHP version.
    */
-  const MIN_RECOMMENDED_PHP_VER = '5.6';
+  const RECOMMENDED_PHP_VER = '7.0';
 
   /**
    * The previous recommended PHP version.
    */
-  const PREVIOUS_MIN_RECOMMENDED_PHP_VER = '5.5';
+  const MIN_RECOMMENDED_PHP_VER = '5.6';
 
   /**
    * The minimum PHP version required to install Civi.
    *
    * @see install/index.php
    */
-  const MIN_INSTALL_PHP_VER = '5.3.4';
-
-  /**
-   * The minimum PHP version required to avoid known
-   * limits or defects.
-   */
-  const MIN_DEFECT_PHP_VER = '5.3.23';
+  const MIN_INSTALL_PHP_VER = '5.4';
 
   /**
    * Compute any messages which should be displayed before upgrade.
@@ -73,25 +67,11 @@ class CRM_Upgrade_Incremental_General {
     $dateFormat = Civi::Settings()->get('dateformatshortdate');
     if (version_compare(phpversion(), self::MIN_RECOMMENDED_PHP_VER) < 0) {
       $preUpgradeMessage .= '<p>';
-      // CRM-20941 PHP 5.3 end date of End of 2017, PHP 5.4 End date End of Feb 2018 Recommend anyone on PHP 5.5 to move up to 5.6 or later e.g. 7.0
-      if (version_compare(phpversion(), self::PREVIOUS_MIN_RECOMMENDED_PHP_VER) >= 0) {
-        $preUpgradeMessage .= ts('You may proceed with the upgrade and CiviCRM %1 will continue working normally, but future releases will require PHP %2 or above. We recommend you use the most recent php version you can.', array(
-           1 => $latestVer,
-           2 => self::MIN_RECOMMENDED_PHP_VER,
-        ));
-      }
-      elseif (version_compare(phpversion(), 5.5) < 0) {
-        $date = CRM_Utils_Date::customFormat('2018-02-28', $dateFormat);
-        if (version_compare(phpversion(), 5.4) < 0) {
-          $date = CRM_Utils_Date::customFormat('2017-12-31', $dateFormat);
-        }
-        $preUpgradeMessage .= ts('You may proceed with the upgrade and CiviCRM %1 will continue working normally, but PHP %2 will not work in releases published after %3. We recommend you use the most recent php version you can. For more explanation see <a href="%4">the announcement</a>.', array(
-          1 => $currentVer,
-          2 => phpversion(),
-          3 => $date,
-          4 => 'https://civicrm.org/blog/totten/end-of-zombies-php-53-and-54',
-        ));
-      }
+      $preUpgradeMessage .= ts('You may proceed with the upgrade and CiviCRM %1 will continue working normally, but future releases will require PHP %2 or above. We recommend PHP version %3.', array(
+         1 => $latestVer,
+         2 => self::MIN_RECOMMENDED_PHP_VER,
+         3 => self::RECOMMENDED_PHP_VER,
+      ));
       $preUpgradeMessage .= '</p>';
     }
 
diff --git a/civicrm/CRM/Upgrade/Incremental/sql/4.7.29.mysql.tpl b/civicrm/CRM/Upgrade/Incremental/sql/4.7.29.mysql.tpl
new file mode 100644
index 0000000000000000000000000000000000000000..444a0ba0e1ee5cdb9d8ea2785bb33615ccc2c9ab
--- /dev/null
+++ b/civicrm/CRM/Upgrade/Incremental/sql/4.7.29.mysql.tpl
@@ -0,0 +1 @@
+{* file to handle db changes in 4.7.29 during upgrade *}
diff --git a/civicrm/CRM/Utils/Check/Component/Env.php b/civicrm/CRM/Utils/Check/Component/Env.php
index 54b92ac6f714fbea17395264fb2c8a09165dd4d6..294547dac59015095f6b1953c9a7cf8f660bf1da 100644
--- a/civicrm/CRM/Utils/Check/Component/Env.php
+++ b/civicrm/CRM/Utils/Check/Component/Env.php
@@ -37,57 +37,62 @@ class CRM_Utils_Check_Component_Env extends CRM_Utils_Check_Component {
    */
   public function checkPhpVersion() {
     $messages = array();
+    $phpVersion = phpversion();
 
-    if (version_compare(phpversion(), CRM_Upgrade_Incremental_General::MIN_RECOMMENDED_PHP_VER) >= 0) {
+    if (version_compare($phpVersion, CRM_Upgrade_Incremental_General::RECOMMENDED_PHP_VER) >= 0) {
       $messages[] = new CRM_Utils_Check_Message(
         __FUNCTION__,
-        ts('This system uses PHP version %1 which meets or exceeds the minimum recommendation of %2.',
+        ts('This system uses PHP version %1 which meets or exceeds the recommendation of %2.',
           array(
-            1 => phpversion(),
-            2 => CRM_Upgrade_Incremental_General::MIN_RECOMMENDED_PHP_VER,
+            1 => $phpVersion,
+            2 => CRM_Upgrade_Incremental_General::RECOMMENDED_PHP_VER,
           )),
         ts('PHP Up-to-Date'),
         \Psr\Log\LogLevel::INFO,
         'fa-server'
       );
     }
-    elseif (version_compare(phpversion(), CRM_Upgrade_Incremental_General::PREVIOUS_MIN_RECOMMENDED_PHP_VER) >= 0) {
+    elseif (version_compare($phpVersion, CRM_Upgrade_Incremental_General::MIN_RECOMMENDED_PHP_VER) >= 0) {
       $messages[] = new CRM_Utils_Check_Message(
         __FUNCTION__,
-        ts('This system uses PHP version %1. While this meets the minimum requirements for CiviCRM to function, upgrading to PHP version %2 or newer is recommended for maximum compatibility.',
+        ts('This system uses PHP version %1. This meets the minimum recommendations and you do not need to upgrade immediately, but the preferred version is %2.',
           array(
-            1 => phpversion(),
-            2 => CRM_Upgrade_Incremental_General::MIN_RECOMMENDED_PHP_VER,
-            3 => CRM_Upgrade_Incremental_General::MIN_DEFECT_PHP_VER,
+            1 => $phpVersion,
+            2 => CRM_Upgrade_Incremental_General::RECOMMENDED_PHP_VER,
           )),
         ts('PHP Out-of-Date'),
         \Psr\Log\LogLevel::NOTICE,
         'fa-server'
       );
     }
-    else {
-      $date = '';
-      $dateFormat = Civi::Settings()->get('dateformatshortdate');
-      if (version_compare(phpversion(), 5.4) < 0) {
-        $date = CRM_Utils_Date::customFormat('2017-12-31', $dateFormat);
-      }
-      elseif (version_compare(phpversion(), 5.5) < 0) {
-        $date = CRM_Utils_Date::customFormat('2018-02-28', $dateFormat);
-      }
+    elseif (version_compare($phpVersion, CRM_Upgrade_Incremental_General::MIN_INSTALL_PHP_VER) >= 0) {
       $messages[] = new CRM_Utils_Check_Message(
         __FUNCTION__,
-        ts('This system uses PHP version %1. CiviCRM can be installed on this version. However PHP version %1 will not work in releases published after %2, and version %3 is recommended. For more explanation see <a href="%4"> the announcement</a>',
+        ts('This system uses PHP version %1. This meets the minimum requirements for CiviCRM to function but is not recommended. At least PHP version %2 is recommended; the preferrred version is %3.',
           array(
-            1 => phpversion(),
-            2 => $date,
-            3 => CRM_Upgrade_Incremental_General::MIN_RECOMMENDED_PHP_VER,
-            4 => 'https://civicrm.org/blog/totten/end-of-zombies-php-53-and-54',
+            1 => $phpVersion,
+            2 => CRM_Upgrade_Incremental_General::MIN_RECOMMENDED_PHP_VER,
+            3 => CRM_Upgrade_Incremental_General::RECOMMENDED_PHP_VER,
           )),
         ts('PHP Out-of-Date'),
         \Psr\Log\LogLevel::WARNING,
         'fa-server'
       );
     }
+    else {
+      $messages[] = new CRM_Utils_Check_Message(
+        __FUNCTION__,
+        ts('This system uses PHP version %1. To ensure the continued operation of CiviCRM, upgrade your server now. At least PHP version %2 is recommended; the preferrred version is %3.',
+          array(
+            1 => $phpVersion,
+            2 => CRM_Upgrade_Incremental_General::MIN_RECOMMENDED_PHP_VER,
+            3 => CRM_Upgrade_Incremental_General::RECOMMENDED_PHP_VER,
+          )),
+        ts('PHP Out-of-Date'),
+        \Psr\Log\LogLevel::ERROR,
+        'fa-server'
+      );
+    }
 
     return $messages;
   }
diff --git a/civicrm/CRM/Utils/Rule.php b/civicrm/CRM/Utils/Rule.php
index c9a92fa96791f322945b35c3a2e7c7f8ddc40410..0168e63c7871ec3d858da957e1468abf089feddf 100644
--- a/civicrm/CRM/Utils/Rule.php
+++ b/civicrm/CRM/Utils/Rule.php
@@ -502,9 +502,15 @@ class CRM_Utils_Rule {
   }
 
   /**
-   * @param $value
+   * Strip thousand separator from a money string.
+   *
+   * Note that this should be done at the form layer. Once we are processing
+   * money at the BAO or processor layer we should be working with something that
+   * is already in a normalised format.
+   *
+   * @param string $value
    *
-   * @return mixed
+   * @return string
    */
   public static function cleanMoney($value) {
     // first remove all white space
diff --git a/civicrm/CRM/Utils/SQL.php b/civicrm/CRM/Utils/SQL.php
index a82614e465ff2abc66715cf49b5f39d0a98fde6c..dba0c9ebe82c11716372070d138222e07af30a7a 100644
--- a/civicrm/CRM/Utils/SQL.php
+++ b/civicrm/CRM/Utils/SQL.php
@@ -80,7 +80,7 @@ class CRM_Utils_SQL {
     // CRM-21455 MariaDB 10.2 does not support ANY_VALUE
     $version = CRM_Core_DAO::singleValueQuery('SELECT VERSION()');
 
-    if (stripos('mariadb', $version) !== FALSE) {
+    if (stripos($version, 'mariadb') !== FALSE) {
       return FALSE;
     }
 
diff --git a/civicrm/Civi/Core/SettingsBag.php b/civicrm/Civi/Core/SettingsBag.php
index 2aee1eb1c205b2bf799e1f256dc67e9654f564f9..66a663e93bad56665d78bfdf46f5fd6b42b3759f 100644
--- a/civicrm/Civi/Core/SettingsBag.php
+++ b/civicrm/Civi/Core/SettingsBag.php
@@ -352,9 +352,11 @@ class SettingsBag {
     }
     $dao->find(TRUE);
 
-    // string comparison with 0 always return true, so to be ensure the type use ===
-    // ref - https://stackoverflow.com/questions/8671942/php-string-comparasion-to-0-integer-returns-true
-    if (isset($metadata['on_change']) && !($value === 0 && ($dao->value === NULL || unserialize($dao->value) == 0))) {
+    // Call 'on_change' listeners. It would be nice to only fire when there's
+    // a genuine change in the data. However, PHP developers have mixed
+    // expectations about whether 0, '0', '', NULL, and FALSE represent the same
+    // value, so there's no universal way to determine if a change is genuine.
+    if (isset($metadata['on_change'])) {
       foreach ($metadata['on_change'] as $callback) {
         call_user_func(
           \Civi\Core\Resolver::singleton()->get($callback),
diff --git a/civicrm/api/v3/Contribution.php b/civicrm/api/v3/Contribution.php
index 6ed8f2a93eb94a073f874f9332abb0784afa9058..027725ff587456987b7c0abce8bd7be7af5df041 100644
--- a/civicrm/api/v3/Contribution.php
+++ b/civicrm/api/v3/Contribution.php
@@ -45,6 +45,9 @@ function civicrm_api3_contribution_create(&$params) {
   $values = array();
   _civicrm_api3_custom_format_params($params, $values, 'Contribution');
   $params = array_merge($params, $values);
+  // The BAO should not clean money - it should be done in the form layer & api wrapper
+  // (although arguably the api should expect pre-cleaned it seems to do some cleaning.)
+  $params['skipCleanMoney'] = TRUE;
 
   if (CRM_Financial_BAO_FinancialType::isACLFinancialTypeStatus()) {
     if (empty($params['id'])) {
diff --git a/civicrm/civicrm-version.php b/civicrm/civicrm-version.php
index dfe26c0bf442d0f48fb0dd41ddb1dc0024969c1a..473b0949fb7945526665c747d86bc508712a5556 100644
--- a/civicrm/civicrm-version.php
+++ b/civicrm/civicrm-version.php
@@ -1,6 +1,6 @@
 <?php
 function civicrmVersion( ) {
-  return array( 'version'  => '4.7.28',
+  return array( 'version'  => '4.7.29',
                 'cms'      => 'Wordpress',
                 'revision' => '' );
 }
diff --git a/civicrm/install/index.php b/civicrm/install/index.php
index b32c4f530d8614a12430fb3eec0b37ebe3c9882d..117637920012273c6cd044550b42b3e3e7c1d1f1 100644
--- a/civicrm/install/index.php
+++ b/civicrm/install/index.php
@@ -595,12 +595,9 @@ class InstallRequirements {
 
     $this->errors = NULL;
 
-    // See also: CRM_Upgrade_Incremental_General::MIN_INSTALL_PHP_VER
-    $this->requirePHPVersion('5.3.4', array(
+    $this->requirePHPVersion(array(
       ts("PHP Configuration"),
       ts("PHP5 installed"),
-      NULL,
-      ts("PHP version %1", array(1 => phpversion())),
     ));
 
     // Check that we can identify the root folder successfully
@@ -860,36 +857,30 @@ class InstallRequirements {
   }
 
   /**
-   * @param $minVersion
-   * @param $testDetails
-   * @param null $maxVersion
+   * @param array $testDetails
+   * @return bool
    */
-  public function requirePHPVersion($minVersion, $testDetails, $maxVersion = NULL) {
+  public function requirePHPVersion($testDetails) {
 
     $this->testing($testDetails);
 
     $phpVersion = phpversion();
-    $aboveMinVersion = version_compare($phpVersion, $minVersion) >= 0;
-    $belowMaxVersion = $maxVersion ? version_compare($phpVersion, $maxVersion) < 0 : TRUE;
+    $aboveMinVersion = version_compare($phpVersion, CRM_Upgrade_Incremental_General::MIN_INSTALL_PHP_VER) >= 0;
 
-    if ($aboveMinVersion && $belowMaxVersion) {
-      if (version_compare(phpversion(), CRM_Upgrade_Incremental_General::MIN_RECOMMENDED_PHP_VER) < 0) {
-        $testDetails[2] = ts('This webserver is running an outdated version of PHP (%1). It is strongly recommended to upgrade to PHP %2 or later, as older versions can present a security risk.', array(
-          1 => phpversion(),
+    if ($aboveMinVersion) {
+      if (version_compare($phpVersion, CRM_Upgrade_Incremental_General::MIN_RECOMMENDED_PHP_VER) < 0) {
+        $testDetails[2] = ts('This webserver is running an outdated version of PHP (%1). It is strongly recommended to upgrade to PHP %2 or later, as older versions can present a security risk. The preferred version is %3.', array(
+          1 => $phpVersion,
           2 => CRM_Upgrade_Incremental_General::MIN_RECOMMENDED_PHP_VER,
+          3 => CRM_Upgrade_Incremental_General::RECOMMENDED_PHP_VER,
         ));
         $this->warning($testDetails);
       }
       return TRUE;
     }
 
-    if (!$testDetails[2]) {
-      if (!$aboveMinVersion) {
-        $testDetails[2] = ts("You need PHP version %1 or later, only %2 is installed. Please upgrade your server, or ask your web-host to do so.", array(1 => $minVersion, 2 => $phpVersion));
-      }
-      else {
-        $testDetails[2] = ts("PHP version %1 is not supported. PHP version earlier than %2 is required. You might want to downgrade your server, or ask your web-host to do so.", array(1 => $maxVersion, 2 => $phpVersion));
-      }
+    if (empty($testDetails[2])) {
+      $testDetails[2] = ts("You need PHP version %1 or later, only %2 is installed. Please upgrade your server, or ask your web-host to do so.", array(1 => CRM_Upgrade_Incremental_General::MIN_INSTALL_PHP_VER, 2 => $phpVersion));
     }
 
     $this->error($testDetails);
diff --git a/civicrm/release-notes.md b/civicrm/release-notes.md
index 9777c84c6cae099d618403f24f6c1527d76261e5..9edaae73539de116c336347c10ba596820d61625 100644
--- a/civicrm/release-notes.md
+++ b/civicrm/release-notes.md
@@ -14,6 +14,16 @@ Other resources for identifying changes are:
     * https://github.com/civicrm/civicrm-joomla
     * https://github.com/civicrm/civicrm-wordpress
 
+## CiviCRM 4.7.29
+
+Released December 20, 2017
+
+- **[Synopsis](release-notes/4.7.29.md#synopsis)**
+- **[Features](release-notes/4.7.29.md#features)**
+- **[Bugs resolved](release-notes/4.7.29.md#bugs)**
+- **[Credits](release-notes/4.7.29.md#credits)**
+- **[Feedback](release-notes/4.7.29.md#feedback)**
+
 ## CiviCRM 4.7.28
 
 Released December 6, 2017
diff --git a/civicrm/release-notes/4.7.29.md b/civicrm/release-notes/4.7.29.md
new file mode 100644
index 0000000000000000000000000000000000000000..5aba623c9b7a203fd414531e941201ab79f604b3
--- /dev/null
+++ b/civicrm/release-notes/4.7.29.md
@@ -0,0 +1,79 @@
+# CiviCRM 4.7.29
+
+Released December 20, 2017
+
+- **[Synopsis](#synopsis)**
+- **[Features](#features)**
+- **[Bugs resolved](#bugs)**
+- **[Miscellany](#misc)**
+- **[Credits](#credits)**
+- **[Feedback](#feedback)**
+
+## <a name="synopsis"></a>Synopsis
+
+| *Does this version...?*                                     |         |
+|:----------------------------------------------------------- |:-------:|
+| Fix security vulnerabilities?                               |   no    |
+| Change the database schema?                                 |   no    |
+| Alter the API?                                              |   no    |
+| Require attention to configuration options?                 |   no    |
+| Fix problems installing or upgrading to a previous version? |   no    |
+| **Introduce features?**                                     | **yes** |
+| **Fix bugs?**                                               | **yes** |
+
+## <a name="features"></a>Features
+
+### Core CiviCRM
+
+- **[CRM-20941](https://issues.civicrm.org/jira/browse/CRM-20941) Increase minimum PHP required to install CiviCRM
+  ([11416](https://github.com/civicrm/civicrm-core/pull/11416))**
+
+  Increases the minimum PHP version required to install CiviCRM 4.7.29 to be 5.4 as per the [announcement blog post](https://civicrm.org/blog/totten/end-of-zombies-php-53-and-54)
+
+## <a name="bugs"></a>Bugs resolved
+
+### Core CiviCRM
+
+- **[CRM-21445](https://issues.civicrm.org/jira/browse/CRM-20941) Ensure "Pay Later" processor is set so a fatal isn't thrown
+  ([11427](https://github.com/civicrm/civicrm-core/pull/11427))**
+
+  Ensures that the pay later payment processor is set to that a fatal error isn't thrown
+
+- **[CRM-21431](https://issues.civicrm.org/jira/browse/CRM-21431) Fix removing of group types
+  ([11436](https://github.com/civicrm/civicrm-core/pull/11436))**
+
+  Fixes an issue where unchecking both the ACL and Mailing list box when editing a group didn't actually remove those types
+
+- **[CRM-21568](https://issues.civicrm.org/jira/browse/CRM-21568) Move the determination of values of empty from settingsbag to InnodbIndxer
+  ([11423](https://github.com/civicrm/civicrm-core/pull/11423))**
+
+  Fixes an issue where string '0' wasn't being treated as false. So the checking of whether there is an empty value is now done in the on change listener for the full text search switcher
+
+- **[CRM-21562](https://issues.civicrm.org/jira/browse/CRM-21562) Fix line item mis-saving when using a ',' as the thousand separator
+  ([11412](https://github.com/civicrm/civicrm-core/pull/11412))**
+
+  Fixes an issue for currencies which use a ',' as the thousand separator the line item was being incorrectly saved by a significant margin.
+
+- **[CRM-21534](https://issues.civicrm.org/jira/browse/CRM-21534) Fix issue where checking if server was a MariaDB server wasn't working correctly
+  ([11413](https://github.com/civicrm/civicrm-core/pull/11413))**
+
+  Fixes an issue where the check to see if the MySQL server was a MariaDB instance wasn't working right. This lead to hard crashes as queries were being incorrectly re-written
+
+## <a name="credits"></a>Credits
+
+This release was developed by the following code authors:
+
+Australian Greens - Seamus Lee; CiviCRM - Coleman Watts, Tim Otten;
+Coop SymbioTIC - Mathieu Lutfy; Wikimedia Foundation - Eileen McNaughton
+
+Most authors also reviewed code for this release; in addition, the following
+reviewers contributed their comments:
+
+Ben Mango; JMA Consulting - Monish Deb; Megaphone Technology Consulting - Jon
+Goldberg; Richard van Oosterhout
+
+## <a name="feedback"></a>Feedback
+
+These release notes are edited by Andrew Hunt.  If you'd like to provide
+feedback on them, please login to https://chat.civicrm.org/civicrm and contact
+`@agh1`.
diff --git a/civicrm/sql/civicrm_data.mysql b/civicrm/sql/civicrm_data.mysql
index 9e4af9d28bb575c16827805c87b9176465d0fe72..d5589f24a0fbf42ee20548c673be8ae1908474bd 100644
--- a/civicrm/sql/civicrm_data.mysql
+++ b/civicrm/sql/civicrm_data.mysql
@@ -23948,4 +23948,4 @@ INSERT INTO `civicrm_report_instance`
 VALUES
     (  @domainID, 'Survey Details', 'survey/detail', 'Detailed report for canvassing, phone-banking, walk lists or other surveys.', 'access CiviReport', 'a:39:{s:6:"fields";a:2:{s:9:"sort_name";s:1:"1";s:6:"result";s:1:"1";}s:22:"assignee_contact_id_op";s:2:"eq";s:25:"assignee_contact_id_value";s:0:"";s:12:"sort_name_op";s:3:"has";s:15:"sort_name_value";s:0:"";s:17:"street_number_min";s:0:"";s:17:"street_number_max";s:0:"";s:16:"street_number_op";s:3:"lte";s:19:"street_number_value";s:0:"";s:14:"street_name_op";s:3:"has";s:17:"street_name_value";s:0:"";s:15:"postal_code_min";s:0:"";s:15:"postal_code_max";s:0:"";s:14:"postal_code_op";s:3:"lte";s:17:"postal_code_value";s:0:"";s:7:"city_op";s:3:"has";s:10:"city_value";s:0:"";s:20:"state_province_id_op";s:2:"in";s:23:"state_province_id_value";a:0:{}s:13:"country_id_op";s:2:"in";s:16:"country_id_value";a:0:{}s:12:"survey_id_op";s:2:"in";s:15:"survey_id_value";a:0:{}s:12:"status_id_op";s:2:"eq";s:15:"status_id_value";s:1:"1";s:11:"custom_1_op";s:2:"in";s:14:"custom_1_value";a:0:{}s:11:"custom_2_op";s:2:"in";s:14:"custom_2_value";a:0:{}s:17:"custom_3_relative";s:1:"0";s:13:"custom_3_from";s:0:"";s:11:"custom_3_to";s:0:"";s:11:"description";s:75:"Detailed report for canvassing, phone-banking, walk lists or other surveys.";s:13:"email_subject";s:0:"";s:8:"email_to";s:0:"";s:8:"email_cc";s:0:"";s:10:"permission";s:17:"access CiviReport";s:6:"groups";s:0:"";s:9:"domain_id";i:1;}');
 
-UPDATE civicrm_domain SET version = '4.7.28';
+UPDATE civicrm_domain SET version = '4.7.29';
diff --git a/civicrm/sql/civicrm_generated.mysql b/civicrm/sql/civicrm_generated.mysql
index b5d3272108b13fd317e18e43047b026b0dd51ca5..e67d6d0af5ac10083849aeece4b9499f25ce4ddf 100644
--- a/civicrm/sql/civicrm_generated.mysql
+++ b/civicrm/sql/civicrm_generated.mysql
@@ -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.28',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.29',1,NULL,'a:1:{s:5:\"en_US\";a:0:{}}');
 /*!40000 ALTER TABLE `civicrm_domain` ENABLE KEYS */;
 UNLOCK TABLES;
 
diff --git a/civicrm/templates/CRM/common/version.tpl b/civicrm/templates/CRM/common/version.tpl
index 21f4f3f3ef07919aff44a6f641f707f8e83ccb4a..e9b84c35cf05bb1dbbb5716301cfed85c9694961 100644
--- a/civicrm/templates/CRM/common/version.tpl
+++ b/civicrm/templates/CRM/common/version.tpl
@@ -1 +1 @@
-4.7.28
\ No newline at end of file
+4.7.29
\ No newline at end of file
diff --git a/civicrm/vendor/autoload.php b/civicrm/vendor/autoload.php
index 616bd0f7121ea895790686604877923a17b2618b..633ea9eb7a7809c01762ef3b4c51a71a46593241 100644
--- a/civicrm/vendor/autoload.php
+++ b/civicrm/vendor/autoload.php
@@ -4,4 +4,4 @@
 
 require_once __DIR__ . '/composer' . '/autoload_real.php';
 
-return ComposerAutoloaderInit1ebc8b5f142ef547147d855925aa5948::getLoader();
+return ComposerAutoloaderInit5cdee2268f29abd76073fe42de4e8d15::getLoader();
diff --git a/civicrm/vendor/composer/autoload_real.php b/civicrm/vendor/composer/autoload_real.php
index ebaeeb3c7fc21c505a96e03d5a8391f35e4fc3ba..86a01c7ba7808d947c349bbea942ebee836f94ca 100644
--- a/civicrm/vendor/composer/autoload_real.php
+++ b/civicrm/vendor/composer/autoload_real.php
@@ -2,7 +2,7 @@
 
 // autoload_real.php @generated by Composer
 
-class ComposerAutoloaderInit1ebc8b5f142ef547147d855925aa5948
+class ComposerAutoloaderInit5cdee2268f29abd76073fe42de4e8d15
 {
     private static $loader;
 
@@ -19,9 +19,9 @@ class ComposerAutoloaderInit1ebc8b5f142ef547147d855925aa5948
             return self::$loader;
         }
 
-        spl_autoload_register(array('ComposerAutoloaderInit1ebc8b5f142ef547147d855925aa5948', 'loadClassLoader'), true, true);
+        spl_autoload_register(array('ComposerAutoloaderInit5cdee2268f29abd76073fe42de4e8d15', 'loadClassLoader'), true, true);
         self::$loader = $loader = new \Composer\Autoload\ClassLoader();
-        spl_autoload_unregister(array('ComposerAutoloaderInit1ebc8b5f142ef547147d855925aa5948', 'loadClassLoader'));
+        spl_autoload_unregister(array('ComposerAutoloaderInit5cdee2268f29abd76073fe42de4e8d15', 'loadClassLoader'));
 
         $includePaths = require __DIR__ . '/include_paths.php';
         array_push($includePaths, get_include_path());
@@ -31,7 +31,7 @@ class ComposerAutoloaderInit1ebc8b5f142ef547147d855925aa5948
         if ($useStaticLoader) {
             require_once __DIR__ . '/autoload_static.php';
 
-            call_user_func(\Composer\Autoload\ComposerStaticInit1ebc8b5f142ef547147d855925aa5948::getInitializer($loader));
+            call_user_func(\Composer\Autoload\ComposerStaticInit5cdee2268f29abd76073fe42de4e8d15::getInitializer($loader));
         } else {
             $map = require __DIR__ . '/autoload_namespaces.php';
             foreach ($map as $namespace => $path) {
@@ -52,19 +52,19 @@ class ComposerAutoloaderInit1ebc8b5f142ef547147d855925aa5948
         $loader->register(true);
 
         if ($useStaticLoader) {
-            $includeFiles = Composer\Autoload\ComposerStaticInit1ebc8b5f142ef547147d855925aa5948::$files;
+            $includeFiles = Composer\Autoload\ComposerStaticInit5cdee2268f29abd76073fe42de4e8d15::$files;
         } else {
             $includeFiles = require __DIR__ . '/autoload_files.php';
         }
         foreach ($includeFiles as $fileIdentifier => $file) {
-            composerRequire1ebc8b5f142ef547147d855925aa5948($fileIdentifier, $file);
+            composerRequire5cdee2268f29abd76073fe42de4e8d15($fileIdentifier, $file);
         }
 
         return $loader;
     }
 }
 
-function composerRequire1ebc8b5f142ef547147d855925aa5948($fileIdentifier, $file)
+function composerRequire5cdee2268f29abd76073fe42de4e8d15($fileIdentifier, $file)
 {
     if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
         require $file;
diff --git a/civicrm/vendor/composer/autoload_static.php b/civicrm/vendor/composer/autoload_static.php
index a130f3d531b4ecda94aceb3bff2ff307ef42a245..d327aa038249f97768c247f29b844c2960bf845f 100644
--- a/civicrm/vendor/composer/autoload_static.php
+++ b/civicrm/vendor/composer/autoload_static.php
@@ -4,7 +4,7 @@
 
 namespace Composer\Autoload;
 
-class ComposerStaticInit1ebc8b5f142ef547147d855925aa5948
+class ComposerStaticInit5cdee2268f29abd76073fe42de4e8d15
 {
     public static $files = array (
         'decc78cc4436b1292c6c0d151b19445c' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
@@ -344,10 +344,10 @@ class ComposerStaticInit1ebc8b5f142ef547147d855925aa5948
     public static function getInitializer(ClassLoader $loader)
     {
         return \Closure::bind(function () use ($loader) {
-            $loader->prefixLengthsPsr4 = ComposerStaticInit1ebc8b5f142ef547147d855925aa5948::$prefixLengthsPsr4;
-            $loader->prefixDirsPsr4 = ComposerStaticInit1ebc8b5f142ef547147d855925aa5948::$prefixDirsPsr4;
-            $loader->prefixesPsr0 = ComposerStaticInit1ebc8b5f142ef547147d855925aa5948::$prefixesPsr0;
-            $loader->classMap = ComposerStaticInit1ebc8b5f142ef547147d855925aa5948::$classMap;
+            $loader->prefixLengthsPsr4 = ComposerStaticInit5cdee2268f29abd76073fe42de4e8d15::$prefixLengthsPsr4;
+            $loader->prefixDirsPsr4 = ComposerStaticInit5cdee2268f29abd76073fe42de4e8d15::$prefixDirsPsr4;
+            $loader->prefixesPsr0 = ComposerStaticInit5cdee2268f29abd76073fe42de4e8d15::$prefixesPsr0;
+            $loader->classMap = ComposerStaticInit5cdee2268f29abd76073fe42de4e8d15::$classMap;
 
         }, null, ClassLoader::class);
     }