Merge remote-tracking branch 'upstream/4.4' into 4.4-4.5-2014-09-08-20-42-29
authorkurund <kurund@civicrm.org>
Mon, 8 Sep 2014 15:20:44 +0000 (20:50 +0530)
committerkurund <kurund@civicrm.org>
Mon, 8 Sep 2014 15:20:44 +0000 (20:50 +0530)
Conflicts:
CRM/Contribute/Form/Contribution/Main.php
templates/CRM/Price/Page/Field.tpl

1  2 
CRM/Contribute/Form/Contribution/Main.php
CRM/Core/Menu.php
CRM/Price/BAO/PriceSet.php
CRM/Price/Page/Field.php
templates/CRM/Price/Page/Field.tpl
tests/phpunit/CRM/Member/BAO/MembershipTest.php

index a60ad3019b29db9e8fb47331e6d86d5c24f94067,cdc7ea57e1d516f69a14352e2f3b921429ec72d2..75c1c1b1d407f5db919fc2d64b788b5f18e14f44
@@@ -1,9 -1,9 +1,9 @@@
  <?php
  /*
    +--------------------------------------------------------------------+
 -  | CiviCRM version 4.4                                                |
 +  | CiviCRM version 4.5                                                |
    +--------------------------------------------------------------------+
 -  | Copyright CiviCRM LLC (c) 2004-2013                                |
 +  | Copyright CiviCRM LLC (c) 2004-2014                                |
    +--------------------------------------------------------------------+
    | This file is a part of CiviCRM.                                    |
    |                                                                    |
@@@ -28,7 -28,7 +28,7 @@@
  /**
   *
   * @package CRM
 - * @copyright CiviCRM LLC (c) 2004-2013
 + * @copyright CiviCRM LLC (c) 2004-2014
   * $Id$
   *
   */
@@@ -111,10 -111,6 +111,10 @@@ class CRM_Contribute_Form_Contribution_
      }
      $this->assign('onBehalfRequired', $this->_onBehalfRequired);
  
 +    if ($this->_honor_block_is_active) {
 +      CRM_Contact_Form_ProfileContact::preprocess($this);
 +    }
 +
      if ($this->_snippet) {
        $this->assign('isOnBehalfCallback', CRM_Utils_Array::value('onbehalf', $_GET, FALSE));
        return;
      }
  
      //CRM-5001
 -    if (CRM_Utils_Array::value('is_for_organization', $this->_values)) {
 +    if (!empty($this->_values['is_for_organization'])) {
        $msg = ts('Mixed profile not allowed for on behalf of registration/sign up.');
 -      if ($preID = CRM_Utils_Array::value('custom_pre_id', $this->_values)) {
 -        $preProfile = CRM_Core_BAO_UFGroup::profileGroups($preID);
 +      $ufJoinParams = array(
 +        'module' => 'onBehalf',
 +        'entity_table' => 'civicrm_contribution_page',
 +        'entity_id' => $this->_id,
 +      );
 +      $onBehalfProfileIDs = CRM_Core_BAO_UFJoin::getUFGroupIds($ufJoinParams);
 +      // getUFGroupIDs returns an array with the first item being the ID we need
 +      $onBehalfProfileID = $onBehalfProfileIDs[0];
 +      if ($onBehalfProfileID) {
 +        $onBehalfProfile = CRM_Core_BAO_UFGroup::profileGroups($onBehalfProfileID);
          foreach (array(
              'Individual', 'Organization', 'Household') as $contactType) {
 -          if (in_array($contactType, $preProfile) &&
 -            (in_array('Membership', $preProfile) ||
 -              in_array('Contribution', $preProfile)
 +          if (in_array($contactType, $onBehalfProfile) &&
 +            (in_array('Membership', $onBehalfProfile) ||
 +              in_array('Contribution', $onBehalfProfile)
              )
            ) {
              CRM_Core_Error::fatal($msg);
      }
    }
  
 +  /**
 +   * set the default values
 +   *
 +   * @return void
 +   * @access public
 +   */
 +  /**
 +   *
 +   */
    function setDefaultValues() {
      // check if the user is registered and we have a contact ID
      $contactID = $this->getContactID();
      //         $this->_defaults['amount']               = 168;
      //         $this->_defaults['credit_card_number']   = '4111111111111111';
      //         $this->_defaults['cvv2']                 = '000';
 -    //         $this->_defaults['credit_card_exp_date'] = array('Y' => '2014', 'M' => '05');
 +    //         $this->_defaults['credit_card_exp_date'] = array('Y' => date('Y')+1, 'M' => '05');
  
      //         // hack to simplify direct debit entry for testing
      //         $this->_defaults['account_holder'] = 'Max Müller';
      //         $this->_defaults['bank_name'] = 'Bankname';
  
      //build set default for pledge overdue payment.
 -    if (CRM_Utils_Array::value('pledge_id', $this->_values)) {
 -      //get all payment statuses.
 -      $statuses = array();
 -      $returnProperties = array('status_id');
 -      CRM_Core_DAO::commonRetrieveAll('CRM_Pledge_DAO_PledgePayment', 'pledge_id', $this->_values['pledge_id'],
 -        $statuses, $returnProperties
 -      );
 +    if (!empty($this->_values['pledge_id'])) {
 +      //get all pledge payment records of current pledge id.
 +      $pledgePayments = array();
 +
 +      //used to record completed pledge payment ids used later for honor default
 +      $completedContributionIds = array();
 +
 +      $pledgePayments = CRM_Pledge_BAO_PledgePayment::getPledgePayments($this->_values['pledge_id']);
  
 -      $paymentStatusTypes = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name');
        $duePayment = FALSE;
 -      foreach ($statuses as $payId => $value) {
 -        if ($paymentStatusTypes[$value['status_id']] == 'Overdue') {
 +      foreach ($pledgePayments as $payId => $value) {
 +        if ($value['status'] == 'Overdue') {
            $this->_defaults['pledge_amount'][$payId] = 1;
          }
 -        elseif (!$duePayment && $paymentStatusTypes[$value['status_id']] == 'Pending') {
 +        elseif (!$duePayment && $value['status'] == 'Pending') {
            $this->_defaults['pledge_amount'][$payId] = 1;
            $duePayment = TRUE;
          }
 +        elseif ($value['status'] == 'Completed' && $value['contribution_id']) {
 +          $completedContributionIds[] = $value['contribution_id'];
 +        }
 +      }
 +
 +      if ($this->_honor_block_is_active && count($completedContributionIds)) {
 +        $softCredit = array();
 +        foreach ($completedContributionIds as $id) {
 +          $softCredit = CRM_Contribute_BAO_ContributionSoft::getSoftContribution($id);
 +        }
 +        if (isset($softCredit['soft_credit'])) {
 +          $this->_defaults['soft_credit_type_id'] = $softCredit['soft_credit'][1]['soft_credit_type'];
 +
 +          //since honoree profile fieldname of fields are prefixed with 'honor'
 +          //we need to reformat the fieldname to append prefix during setting default values
 +          CRM_Core_BAO_UFGroup::setProfileDefaults(
 +            $softCredit['soft_credit'][1]['contact_id'],
 +            CRM_Core_BAO_UFGroup::getFields($this->_honoreeProfileId),
 +            $defaults
 +          );
 +          foreach ($defaults as $fieldName => $value) {
 +            $this->_defaults['honor[' . $fieldName . ']'] = $value;
 +          }
 +        }
        }
      }
 -    elseif (CRM_Utils_Array::value('pledge_block_id', $this->_values)) {
 +    elseif (!empty($this->_values['pledge_block_id'])) {
        //set default to one time contribution.
        $this->_defaults['is_pledge'] = 0;
      }
  
      $config = CRM_Core_Config::singleton();
      // set default country from config if no country set
 -    if (!CRM_Utils_Array::value("billing_country_id-{$this->_bltID}", $this->_defaults)) {
 +    if (empty($this->_defaults["billing_country_id-{$this->_bltID}"])) {
        $this->_defaults["billing_country_id-{$this->_bltID}"] = $config->defaultContactCountry;
      }
  
      // set default state/province from config if no state/province set
 -    if (!CRM_Utils_Array::value("billing_state_province_id-{$this->_bltID}", $this->_defaults)) {
 +    if (empty($this->_defaults["billing_state_province_id-{$this->_bltID}"])) {
        $this->_defaults["billing_state_province_id-{$this->_bltID}"] = $config->defaultContactStateProvince;
      }
  
 -    // now fix all state country selectors
 -    CRM_Core_BAO_Address::fixAllStateSelects($this, $this->_defaults);
 -
      if ($this->_priceSetId) {
        if (($this->_useForMember && !empty($this->_currentMemberships)) || $this->_defaultMemTypeId) {
          $selectedCurrentMemTypes = array();
                }
                $selectedCurrentMemTypes[] = $values['membership_type_id'];
              }
 -            elseif (CRM_Utils_Array::value('is_default', $values) &&
 +            elseif (!empty($values['is_default']) &&
                !$opMemTypeId &&
                (!isset($this->_defaults["price_{$key}"]) ||
                  ($val['html_type'] == 'CheckBox' && !isset($this->_defaults["price_{$key}"][$keys]))
  
      if (!empty($this->_paymentProcessors)) {
        foreach ($this->_paymentProcessors as $pid => $value) {
 -        if (CRM_Utils_Array::value('is_default', $value)) {
 +        if (!empty($value['is_default'])) {
            $this->_defaults['payment_processor'] = $pid;
          }
        }
    /**
     * Function to build the form
     *
 -   * @return None
 +   * @return void
     * @access public
     */
    public function buildQuickForm() {
          $pps[$key] = $name['name'];
        }
      }
 -    if (CRM_Utils_Array::value('is_pay_later', $this->_values)) {
 +    if (!empty($this->_values['is_pay_later'])) {
        $pps[0] = $this->_values['pay_later_text'];
      }
  
      //build pledge block.
      $this->_useForMember = 0;
      //don't build membership block when pledge_id is passed
 -    if (!CRM_Utils_Array::value('pledge_id', $this->_values)) {
 +    if (empty($this->_values['pledge_id'])) {
        $this->_separateMembershipPayment = FALSE;
        if (in_array('CiviMember', $config->enableComponents)) {
          $isTest = 0;
        $this->set('priceSetId', $this->_priceSetId);
        CRM_Price_BAO_PriceSet::buildPriceSet($this);
        if ($this->_values['is_monetary'] &&
 -        $this->_values['is_recur'] && !CRM_Utils_Array::value('pledge_id', $this->_values)
 -      ) {
 +        $this->_values['is_recur'] && empty($this->_values['pledge_id'])) {
          self::buildRecur($this);
        }
      }
      }
  
      //we allow premium for pledge during pledge creation only.
 -    if (!CRM_Utils_Array::value('pledge_id', $this->_values)) {
 +    if (empty($this->_values['pledge_id'])) {
        CRM_Contribute_BAO_Premium::buildPremiumBlock($this, $this->_id, TRUE);
      }
  
 -    if ($this->_values['honor_block_is_active']) {
 -      $this->buildHonorBlock();
 +    //add honor block
 +    if ($this->_honor_block_is_active) {
 +      $this->assign('honor_block_is_active', TRUE);
 +
 +      //build soft-credit section
 +      CRM_Contribute_Form_SoftCredit::buildQuickForm($this);
 +      //build honoree profile section
 +      CRM_Contact_Form_ProfileContact::buildQuickForm($this);
      }
  
  
      //don't build pledge block when mid is passed
      if (!$this->_mid) {
        $config = CRM_Core_Config::singleton();
 -      if (in_array('CiviPledge', $config->enableComponents)
 -        && CRM_Utils_Array::value('pledge_block_id', $this->_values)
 -      ) {
 +      if (in_array('CiviPledge', $config->enableComponents) && !empty($this->_values['pledge_block_id'])) {
          CRM_Pledge_BAO_PledgeBlock::buildPledgeBlock($this);
        }
      }
      $this->addFormRule(array('CRM_Contribute_Form_Contribution_Main', 'formRule'), $this);
    }
  
 -  /**
 -   * Function to add the honor block
 -   *
 -   * @return None
 -   * @access public
 -   */
 -  function buildHonorBlock() {
 -    $this->assign('honor_block_is_active', TRUE);
 -    $this->set('honor_block_is_active', TRUE);
 -
 -    $this->assign('honor_block_title', CRM_Utils_Array::value('honor_block_title', $this->_values));
 -    $this->assign('honor_block_text', CRM_Utils_Array::value('honor_block_text', $this->_values));
 -
 -    $attributes = CRM_Core_DAO::getAttribute('CRM_Contact_DAO_Contact');
 -    $extraOption = array('onclick' => "enableHonorType();");
 -    // radio button for Honor Type
 -    $honorOptions = array();
 -    $honor = CRM_Core_PseudoConstant::get('CRM_Contribute_DAO_Contribution', 'honor_type_id');
 -    foreach ($honor as $key => $var) {
 -      $honorTypes[$key] = $this->createElement('radio', NULL, NULL, $var, $key, $extraOption);
 -    }
 -    $this->addGroup($honorTypes, 'honor_type_id', NULL);
 -
 -    // prefix
 -    $this->addElement('select', 'honor_prefix_id', ts('Prefix'), array('' => ts('- prefix -')) + CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'prefix_id'));
 -    // first_name
 -    $this->addElement('text', 'honor_first_name', ts('First Name'), $attributes['first_name']);
 -
 -    //last_name
 -    $this->addElement('text', 'honor_last_name', ts('Last Name'), $attributes['last_name']);
 -
 -    //email
 -    $this->addElement('text', 'honor_email', ts('Email Address'), array('class' => 'email'));
 -    $this->addRule('honor_email', ts('Honoree Email is not valid.'), 'email');
 -  }
 -
    /**
     * build elements to enable pay on behalf of an organization.
     *
  
      $form->add('checkbox', 'is_recur', ts('I want to contribute this amount'), NULL);
  
 -    if (CRM_Utils_Array::value('is_recur_interval', $form->_values) || $className == 'CRM_Contribute_Form_Contribution') {
 +    if (!empty($form->_values['is_recur_interval']) || $className == 'CRM_Contribute_Form_Contribution') {
        $form->add('text', 'frequency_interval', ts('Every'), $attributes['frequency_interval']);
        $form->addRule('frequency_interval', ts('Frequency must be a whole number (EXAMPLE: Every 3 months).'), 'integer');
      }
        $form->assign('one_frequency_unit', true);
        $unit = $unitVals[0];
        $form->add('hidden', 'frequency_unit', $unit);
 -      if (CRM_Utils_Array::value('is_recur_interval', $form->_values) || $className == 'CRM_Contribute_Form_Contribution') {
 +      if (!empty($form->_values['is_recur_interval']) || $className == 'CRM_Contribute_Form_Contribution') {
          $unit .= "(s)";
        }
        $form->assign('frequency_unit', $unit);
        foreach ($unitVals as $key => $val) {
          if (array_key_exists($val, $frequencyUnits)) {
            $units[$val] = $frequencyUnits[$val];
 -          if (CRM_Utils_Array::value('is_recur_interval', $form->_values) || $className == 'CRM_Contribute_Form_Contribution') {
 +          if (!empty($form->_values['is_recur_interval']) || $className == 'CRM_Contribute_Form_Contribution') {
              $units[$val] = "{$frequencyUnits[$val]}(s)";
            }
          }
    /**
     * global form rule
     *
 -   * @param array $fields  the input form values
 -   * @param array $files   the uploaded files if any
 -   * @param array $options additional user data
 +   * @param array $fields the input form values
 +   * @param array $files the uploaded files if any
 +   * @param $self
 +   *
 +   * @internal param array $options additional user data
     *
     * @return true if no errors, else array of errors
     * @access public
      $errors = array();
      $amount = self::computeAmount($fields, $self);
  
 -    if ((CRM_Utils_Array::value('selectMembership', $fields) &&
 +    if ((!empty($fields['selectMembership']) &&
          $fields['selectMembership'] != 'no_thanks'
        ) ||
 -      (CRM_Utils_Array::value('priceSetId', $fields) &&
 +      (!empty($fields['priceSetId']) &&
          $self->_useForMember
        )
      ) {
      }
  
      //check for atleast one pricefields should be selected
 -    if (CRM_Utils_Array::value('priceSetId', $fields)) {
 +    if (!empty($fields['priceSetId'])) {
        $priceField = new CRM_Price_DAO_PriceField();
        $priceField->price_set_id = $fields['priceSetId'];
        $priceField->orderBy('weight');
            }
          }
          if ($priceField->name == 'other_amount') {
 -          if ($self->_quickConfig && !CRM_Utils_Array::value("price_{$priceField->id}", $fields) &&
 +          if ($self->_quickConfig && empty($fields["price_{$priceField->id}"]) &&
              array_key_exists("price_{$previousId}", $fields) && isset($fields["price_{$previousId}"]) && $self->_values['fee'][$previousId]['name'] == 'contribution_amount' && empty($fields["price_{$previousId}"])) {
              $otherAmount = $priceField->id;
            }
          }
        }
  
 +      $currentMemberships = NULL;
 +      if ($membershipIsActive) {
 +        $is_test = $self->_mode != 'live' ? 1 : 0;
 +        $memContactID = $self->_membershipContactID;
 +       
 +        // For anonymous user check using dedupe rule 
 +        // if user has Cancelled Membership
 +        if (!$memContactID) {
 +          $dedupeParams = CRM_Dedupe_Finder::formatParams($fields, 'Individual');
 +          $dedupeParams['check_permission'] = FALSE;
 +          $ids = CRM_Dedupe_Finder::dupesByParams($dedupeParams, 'Individual');
 +          // if we find more than one contact, use the first one
 +          $memContactID = CRM_Utils_Array::value(0, $ids);
 +        }
 +        $currentMemberships = CRM_Member_BAO_Membership::getContactsCancelledMembership($memContactID,
 +          $is_test
 +        );
 +        
 +        $errorText = 'Your %1 membership was previously cancelled and can not be renewed online. Please contact the site administrator for assistance.';
 +        foreach ($self->_values['fee'] as $fieldKey => $fieldValue) {
 +          if ($fieldValue['html_type'] != 'Text' && CRM_Utils_Array::value('price_' . $fieldKey, $fields)) {
 +            if (!is_array($fields['price_' . $fieldKey])) {
 +              if (array_key_exists('membership_type_id', $fieldValue['options'][$fields['price_' . $fieldKey]]) 
 +                && in_array($fieldValue['options'][$fields['price_' . $fieldKey]]['membership_type_id'], $currentMemberships)) {
 +                $errors['price_' . $fieldKey] = ts($errorText, array(1 => CRM_Member_PseudoConstant::membershipType($fieldValue['options'][$fields['price_' . $fieldKey]]['membership_type_id'])));
 +              }
 +            }
 +            else {
 +              foreach ($fields['price_' . $fieldKey] as $key => $ignore) {
 +                if (array_key_exists('membership_type_id', $fieldValue['options'][$key]) 
 +                  && in_array($fieldValue['options'][$key]['membership_type_id'], $currentMemberships)) {
 +                  $errors['price_' . $fieldKey] = ts($errorText, array(1 => CRM_Member_PseudoConstant::membershipType($fieldValue['options'][$key]['membership_type_id'])));
 +                }
 +              }
 +            }
 +          }
 +        }
 +      }
 + 
        // CRM-12233
        if ($membershipIsActive && !$self->_membershipBlock['is_required']
          && $self->_values['amount_block_is_active']) {
            }
          }
          // $membershipFieldId is set and additional amount is 'No thank you' or NULL then throw error
 -        if ($membershipFieldId && !(CRM_Utils_Array::value('price_' . $contributionFieldId, $fields, -1) > 0)
 -          && !CRM_Utils_Array::value('price_' . $otherFieldId, $fields)) {
 +        if ($membershipFieldId && !(CRM_Utils_Array::value('price_' . $contributionFieldId, $fields, -1) > 0) && empty($fields['price_' . $otherFieldId])) {
            $errors["price_{$errorKey}"] = ts('Additional Contribution is required.');
          }
        }
          $priceFieldMemTypes = array();
  
          foreach ($self->_priceSet['fields'] as $priceId => $value) {
 -          if (!empty($fields['price_' . $priceId]) || ($self->_quickConfig && $value['name'] == 'membership_amount' && !CRM_Utils_Array::value('is_required', $self->_membershipBlock))) {
 -            if (CRM_Utils_Array::value('price_' . $priceId, $fields) && is_array($fields['price_' . $priceId])) {
 +          if (!empty($fields['price_' . $priceId]) || ($self->_quickConfig && $value['name'] == 'membership_amount' && empty($self->_membershipBlock['is_required']))) {
 +            if (!empty($fields['price_' . $priceId]) && is_array($fields['price_' . $priceId])) {
                foreach ($fields['price_' . $priceId] as $priceFldVal => $isSet) {
                  if ($isSet) {
                    $priceFieldIDS[] = $priceFldVal;
                  }
                }
              }
 -            elseif (!$value['is_enter_qty'] && CRM_Utils_Array::value('price_' . $priceId, $fields)) {
 +            elseif (!$value['is_enter_qty'] && !empty($fields['price_' . $priceId])) {
                // The check for {!$value['is_enter_qty']} is done since, quantity fields allow entering
                // quantity. And the quantity can't be conisdered as civicrm_price_field_value.id, CRM-9577
                $priceFieldIDS[] = $fields['price_' . $priceId];
              }
  
 -            if (CRM_Utils_Array::value('options', $value)) {
 +            if (!empty($value['options'])) {
                foreach ($value['options'] as $val) {
-                 if (!empty($val['membership_type_id'])) {
 -                if (CRM_Utils_Array::value('membership_type_id', $val) && (
++                if (!empty($val['membership_type_id']) && (
+                     ($fields['price_' . $priceId] == $val['id']) ||
+                     (isset($fields['price_' . $priceId]) && !empty($fields['price_' . $priceId][$val['id']]))
+                   )
+                 ) {
                    $priceFieldMemTypes[] = $val['membership_type_id'];
                  }
                }
        }
      }
  
 -    if ($self->_values['honor_block_is_active'] && CRM_Utils_Array::value('honor_type_id', $fields)) {
 -      // make sure there is a first name and last name if email is not there
 -      if (!CRM_Utils_Array::value('honor_email', $fields)) {
 -        if (!CRM_Utils_Array::value('honor_first_name', $fields) ||
 -          !CRM_Utils_Array::value('honor_last_name', $fields)
 -        ) {
 -          $errors['honor_last_name'] = ts('In Honor Of - First Name and Last Name, OR an Email Address is required.');
 -        }
 -      }
 -    }
 -
 -    if ( CRM_Utils_Array::value( 'is_recur', $fields ) ) {
 +    if (!empty($fields['is_recur'])) {
        if ($fields['frequency_interval'] <= 0) {
          $errors['frequency_interval'] = ts('Please enter a number for how often you want to make this recurring contribution (EXAMPLE: Every 3 months).');
        }
        }
      }
  
 -    if (CRM_Utils_Array::value('is_recur', $fields) &&
 +    if (!empty($fields['is_recur']) &&
        CRM_Utils_Array::value('payment_processor', $fields) == 0) {
        $errors['_qf_default'] = ts('You cannot set up a recurring contribution if you are not paying online by credit card.');
      }
  
 -    if (CRM_Utils_Array::value('is_for_organization', $fields) &&
 +    if (!empty($fields['is_for_organization']) &&
        !property_exists($self, 'organizationName')
      ) {
  
 -      if (!CRM_Utils_Array::value('organization_name', $fields['onbehalf'])) {
 -        if (CRM_Utils_Array::value('org_option', $fields) && !$fields['onbehalfof_id']) {
 +      if (empty($fields['onbehalf']['organization_name'])) {
 +        if (!empty($fields['org_option']) && !$fields['onbehalfof_id']) {
            $errors['organization_id'] = ts('Please select an organization or enter a new one.');
          }
 -        elseif (!CRM_Utils_Array::value('org_option', $fields)) {
 +        elseif (empty($fields['org_option'])) {
            $errors['onbehalf']['organization_name'] = ts('Please enter the organization name.');
          }
        }
            $emailLocType = explode('-', $key);
          }
        }
 -      if (!CRM_Utils_Array::value("email-{$emailLocType[1]}", $fields['onbehalf'])) {
 +      if (empty($fields['onbehalf']["email-{$emailLocType[1]}"])) {
          $errors['onbehalf']["email-{$emailLocType[1]}"] = ts('Organization email is required.');
        }
      }
  
      // validate PCP fields - if not anonymous, we need a nick name value
 -    if ($self->_pcpId && CRM_Utils_Array::value('pcp_display_in_roll', $fields) &&
 +    if ($self->_pcpId && !empty($fields['pcp_display_in_roll']) &&
        (CRM_Utils_Array::value('pcp_is_anonymous', $fields) == 0) &&
        CRM_Utils_Array::value('pcp_roll_nickname', $fields) == ''
      ) {
      if ($self->_paymentProcessor &&
        $self->_paymentProcessor['billing_mode'] & CRM_Core_Payment::BILLING_MODE_BUTTON
      ) {
 -      if (CRM_Utils_Array::value($self->_expressButtonName . '_x', $fields) ||
 -        CRM_Utils_Array::value($self->_expressButtonName . '_y', $fields) ||
 +      if (!empty($fields[$self->_expressButtonName . '_x']) || !empty($fields[$self->_expressButtonName . '_y']) ||
          CRM_Utils_Array::value($self->_expressButtonName, $fields)
        ) {
          return $errors;
      }
  
      //validate the pledge fields.
 -    if (CRM_Utils_Array::value('pledge_block_id', $self->_values)) {
 +    if (!empty($self->_values['pledge_block_id'])) {
        //validation for pledge payment.
 -      if (CRM_Utils_Array::value('pledge_id', $self->_values)) {
 +      if (!empty($self->_values['pledge_id'])) {
          if (empty($fields['pledge_amount'])) {
            $errors['pledge_amount'] = ts('At least one payment option needs to be checked.');
          }
        }
 -      elseif (CRM_Utils_Array::value('is_pledge', $fields)) {
 +      elseif (!empty($fields['is_pledge'])) {
          if (CRM_Utils_Rule::positiveInteger(CRM_Utils_Array::value('pledge_installments', $fields)) == FALSE) {
            $errors['pledge_installments'] = ts('Please enter a valid number of pledge installments.');
          }
      return empty($errors) ? TRUE : $errors;
    }
  
 +  /**
 +   * @param $params
 +   * @param $form
 +   *
 +   * @return int|mixed|null|string
 +   */
    public static function computeAmount(&$params, &$form) {
      $amount = NULL;
  
        $params['amount_other'] = CRM_Utils_Rule::cleanMoney($params['amount_other']);
      }
  
 -    if (CRM_Utils_Array::value('amount', $params) == 'amount_other_radio' ||
 -      CRM_Utils_Array::value('amount_other', $params)
 -    ) {
 +    if (CRM_Utils_Array::value('amount', $params) == 'amount_other_radio' || !empty($params['amount_other'])) {
        $amount = $params['amount_other'];
      }
      elseif (!empty($params['pledge_amount'])) {
        }
      }
      else {
 -      if (CRM_Utils_Array::value('amount', $form->_values)) {
 +      if (!empty($form->_values['amount'])) {
          $amountID = CRM_Utils_Array::value('amount', $params);
  
          if ($amountID) {
     *
     * @access public
     *
 -   * @return None
 +   * @return void
     */
    public function postProcess() {
      $config = CRM_Core_Config::singleton();
 -
      // we first reset the confirm page so it accepts new values
      $this->controller->resetPage('Confirm');
  
      // get the submitted form values.
      $params = $this->controller->exportValues($this->_name);
  
 -    if (CRM_Utils_Array::value('priceSetId', $params)) {
 +    //carry campaign from profile.
 +    if (array_key_exists('contribution_campaign_id', $params)) {
 +      $params['campaign_id'] = $params['contribution_campaign_id'];
 +    }
 +
 +    if (!empty($params['onbehalfof_id'])) {
 +      $params['organization_id'] = $params['onbehalfof_id'];
 +    }
 +
 +    $params['currencyID'] = $config->defaultCurrency;
 +
 +    if (!empty($params['priceSetId'])) {
        $is_quick_config = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $this->_priceSetId, 'is_quick_config');
 -      $formValue = array();
        if ($is_quick_config) {
          $priceField = new CRM_Price_DAO_PriceField();
          $priceField->price_set_id = $params['priceSetId'];
          $priceField->orderBy('weight');
          $priceField->find();
  
 -        $check = array();
 -        $otherAmount = FALSE;
 +        $priceOptions = array();
          while ($priceField->fetch()) {
 -          CRM_Price_BAO_PriceFieldValue::getValues($priceField->id, $values);
 -          if ($priceField->name == 'membership_amount') {
 -            if ($priceFiledID = CRM_Utils_Array::value("price_{$priceField->id}", $params)) {
 -              $this->_params['selectMembership'] = $params['selectMembership'] = CRM_Utils_Array::value('membership_type_id', $values[$priceFiledID]);
 -              $this->set('selectMembership',CRM_Utils_Array::value('selectMembership', $params));
 -              if (CRM_Utils_Array::value('is_separate_payment', $this->_membershipBlock) == 0) {
 -                $this->_values['amount'] = CRM_Utils_Array::value('amount', $values[$priceFiledID]);
 -              }
 -            }
 -          }
 -          if ($priceField->name == 'contribution_amount') {
 -            $priceFiledID = CRM_Utils_Array::value("price_{$priceField->id}", $params);
 -            if ($priceFiledID > 0 && !empty($priceFiledID)) {
 -              $params['amount'] = $priceFiledID;
 -              $this->_values['amount'] = CRM_Utils_Array::value('amount', $values[$priceFiledID]);
 -              $this->_values[$priceFiledID]['value'] = CRM_Utils_Array::value('amount', $values[$priceFiledID]);
 -              $this->_values[$priceFiledID]['label'] = CRM_Utils_Array::value('label', $values[$priceFiledID]);
 -              $this->_values[$priceFiledID]['amount_id'] = CRM_Utils_Array::value('id', $values[$priceFiledID]);
 -              $this->_values[$priceFiledID]['weight'] = CRM_Utils_Array::value('weight', $values[$priceFiledID]);
 +          CRM_Price_BAO_PriceFieldValue::getValues($priceField->id, $priceOptions);
 +          if ($selectedPriceOptionID = CRM_Utils_Array::value("price_{$priceField->id}", $params)) {
 +            switch ($priceField->name) {
 +              case 'membership_amount':
 +                $this->_params['selectMembership'] = $params['selectMembership'] = CRM_Utils_Array::value('membership_type_id', $priceOptions[$selectedPriceOptionID]);
 +                $this->set('selectMembership', $params['selectMembership']);
 +                if (CRM_Utils_Array::value('is_separate_payment', $this->_membershipBlock) == 0) {
 +                  $this->_values['amount'] = CRM_Utils_Array::value('amount', $priceOptions[$selectedPriceOptionID]);
 +                }
 +                break;
 +
 +              case 'contribution_amount':
 +                $params['amount'] = $selectedPriceOptionID;
 +                $this->_values['amount'] = CRM_Utils_Array::value('amount', $priceOptions[$selectedPriceOptionID]);
 +                $this->_values[$selectedPriceOptionID]['value'] = CRM_Utils_Array::value('amount', $priceOptions[$selectedPriceOptionID]);
 +                $this->_values[$selectedPriceOptionID]['label'] = CRM_Utils_Array::value('label', $priceOptions[$selectedPriceOptionID]);
 +                $this->_values[$selectedPriceOptionID]['amount_id'] = CRM_Utils_Array::value('id', $priceOptions[$selectedPriceOptionID]);
 +                $this->_values[$selectedPriceOptionID]['weight'] = CRM_Utils_Array::value('weight', $priceOptions[$selectedPriceOptionID]);
 +                break;
 +
 +              case 'other_amount':
 +                $params['amount_other'] = $selectedPriceOptionID;
 +                break;
              }
            }
 -          if ($priceField->name == 'other_amount' && $priceFiledID = CRM_Utils_Array::value("price_{$priceField->id}", $params)) {
 -            $params['amount_other'] = $priceFiledID;
 -          }
          }
        }
      }
        $this->assign('pay_later_receipt', $this->_values['pay_later_receipt']);
      }
  
 -    //carry campaign from profile.
 -    if (array_key_exists('contribution_campaign_id', $params)) {
 -      $params['campaign_id'] = $params['contribution_campaign_id'];
 -    }
 -
 -    if (CRM_Utils_Array::value('onbehalfof_id', $params)) {
 -      $params['organization_id'] = $params['onbehalfof_id'];
 -    }
 -
 -    $params['currencyID'] = $config->defaultCurrency;
 +    // from here on down, $params['amount'] holds a monetary value (or null) rather than an option ID
      $params['amount'] = self::computeAmount($params, $this);
      $params['separate_amount'] = $params['amount'];
      $memFee = NULL;
 -    if (CRM_Utils_Array::value('selectMembership', $params)) {
 +    if (!empty($params['selectMembership'])) {
        if (!empty($this->_membershipTypeValues)) {
          $membershipTypeValues = $this->_membershipTypeValues[$params['selectMembership']];
        }
        }
      }
  
 -    //If the membership & contribution is used in contribution page & not seperate payment
 +    //If the membership & contribution is used in contribution page & not separate payment
      $fieldId = $memPresent = $membershipLabel = $fieldOption = $is_quick_config = NULL;
      $proceFieldAmount = 0;
 -    if ($this->_separateMembershipPayment == 0) {
 +    if (property_exists($this, '_separateMembershipPayment') && $this->_separateMembershipPayment == 0) {
        $is_quick_config = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $this->_priceSetId, 'is_quick_config');
        if ($is_quick_config) {
          foreach ($this->_priceSet['fields'] as $fieldKey => $fieldVal) {
 -          if ($fieldVal['name'] == 'membership_amount' && CRM_Utils_Array::value('price_' . $fieldKey , $params)) {
 +          if ($fieldVal['name'] == 'membership_amount' && !empty($params['price_' . $fieldKey ])) {
              $fieldId     = $fieldVal['id'];
              $fieldOption = $params['price_' . $fieldId];
              $proceFieldAmount += $fieldVal['options'][$this->_submitValues['price_' . $fieldId]]['amount'];
              $memPresent  = TRUE;
            }
            else {
 -            if (CRM_Utils_Array::value('price_' . $fieldKey, $params) && $memPresent && ($fieldVal['name'] == 'other_amount' || $fieldVal['name'] == 'contribution_amount')) {
 +            if (!empty($params['price_' . $fieldKey]) && $memPresent && ($fieldVal['name'] == 'other_amount' || $fieldVal['name'] == 'contribution_amount')) {
                $fieldId = $fieldVal['id'];
                if ($fieldVal['name'] == 'other_amount') {
                  $proceFieldAmount += $this->_submitValues['price_' . $fieldId];
        $this->set('lineItem', $lineItem);
      }
  
 -    if ($this->_membershipBlock['is_separate_payment'] && CRM_Utils_Array::value('separate_amount', $params)) {
 +    if ($this->_membershipBlock['is_separate_payment'] && !empty($params['separate_amount'])) {
        $this->set('amount', $params['separate_amount']);
      } else {
        $this->set('amount', $params['amount']);
      $invoiceID = md5(uniqid(rand(), TRUE));
      $this->set('invoiceID', $invoiceID);
  
 -    // required only if is_monetary and valid postive amount
 +    // required only if is_monetary and valid positive amount
      if ($this->_values['is_monetary'] &&
        is_array($this->_paymentProcessor) &&
        ((float ) $params['amount'] > 0.0 || $memFee > 0.0)
          $buttonName = $this->controller->getButtonName();
          if (in_array($buttonName,
              array($this->_expressButtonName, $this->_expressButtonName . '_x', $this->_expressButtonName . '_y')
 -          ) &&
 -          !CRM_Utils_Array::value('is_pay_later', $params)
 -        ) {
 +          ) && empty($params['is_pay_later'])) {
            $this->set('contributeMode', 'express');
  
            $donateURL           = CRM_Utils_System::url('civicrm/contribute', '_qf_Contribute_display=1');
      }
  
      // should we skip the confirm page?
 -    if (!CRM_Utils_Array::value('is_confirm_enabled', $this->_values)) {
 +    if (empty($this->_values['is_confirm_enabled'])) {
        // call the post process hook for the main page before we switch to confirm
        $this->postProcessHook();
  
     */
    static function preProcessPaymentOptions(&$form, $noFees = FALSE) {
      $form->_snippet = CRM_Utils_Array::value('snippet', $_GET);
 -    $form->assign('snippet', $form->_snippet);
  
      $form->_paymentProcessors = $noFees ? array() : $form->get('paymentProcessors');
      $form->_ppType = NULL;
diff --combined CRM/Core/Menu.php
index f6a80befb3d475e3be358f9721a358ad921930ab,0cb7b299655bc5f632f15a7058a7f85d5221d246..75d0516a2ce67c4f4406ccc00ffcff240d2adf0f
@@@ -1,9 -1,9 +1,9 @@@
  <?php
  /*
   +--------------------------------------------------------------------+
 - | CiviCRM version 4.4                                                |
 + | CiviCRM version 4.5                                                |
   +--------------------------------------------------------------------+
 - | Copyright CiviCRM LLC (c) 2004-2013                                |
 + | Copyright CiviCRM LLC (c) 2004-2014                                |
   +--------------------------------------------------------------------+
   | This file is a part of CiviCRM.                                    |
   |                                                                    |
   * This file contains the various menus of the CiviCRM module
   *
   * @package CRM
 - * @copyright CiviCRM LLC (c) 2004-2013
 + * @copyright CiviCRM LLC (c) 2004-2014
   * $Id$
   *
   */
  
  require_once 'CRM/Core/I18n.php';
 +
 +/**
 + * Class CRM_Core_Menu
 + */
  class CRM_Core_Menu {
  
    /**
@@@ -68,9 -64,6 +68,9 @@@
    static $_menuCache = NULL;
    CONST MENU_ITEM = 1;
  
 +  /**
 +   * @return array
 +   */
    static function &xmlItems() {
      if (!self::$_items) {
        $config = CRM_Core_Config::singleton();
      return self::$_items;
    }
  
 +  /**
 +   * @param $name
 +   * @param $menu
 +   *
 +   * @throws Exception
 +   */
    static function read($name, &$menu) {
  
      $config = CRM_Core_Config::singleton();
      return self::xmlItems();
    }
  
 +  /**
 +   * @param $values
 +   *
 +   * @return bool
 +   */
    static function isArrayTrue(&$values) {
      foreach ($values as $name => $value) {
        if (!$value) {
      return TRUE;
    }
  
 +  /**
 +   * @param $menu
 +   * @param $path
 +   *
 +   * @throws Exception
 +   */
    static function fillMenuValues(&$menu, $path) {
      $fieldsToPropagate = array(
        'access_callback',
      self::buildAdminLinks($menu);
    }
  
 +  /**
 +   * @param bool $truncate
 +   */
    static function store($truncate = TRUE) {
      // first clean up the db
      if ($truncate) {
      }
    }
  
 +  /**
 +   * @param $menu
 +   */
    static function buildAdminLinks(&$menu) {
      $values = array();
  
      foreach ($menu as $path => $item) {
 -      if (!CRM_Utils_Array::value('adminGroup', $item)) {
 +      if (empty($item['adminGroup'])) {
          continue;
        }
  
 -      $query = CRM_Utils_Array::value('path_arguments', $item) ? str_replace(',', '&', $item['path_arguments']) . '&reset=1' : 'reset=1';
 +      $query = !empty($item['path_arguments']) ? str_replace(',', '&', $item['path_arguments']) . '&reset=1' : 'reset=1';
  
        $value = array(
          'title' => $item['title'],
              ',' => '_', '/' => '_',
            )
          ),
-         'url' => CRM_Utils_System::url($path, $query, FALSE),
+         'url' => CRM_Utils_System::url($path, $query, 
+             FALSE, // absolute
+             NULL, // fragment
+             TRUE, // htmlize
+             FALSE, // frontend
+             TRUE // forceBackend; CRM-14439 work-around; acceptable for now because we don't display breadcrumbs on frontend
+         ),
          'icon' => CRM_Utils_Array::value('icon', $item),
          'extra' => CRM_Utils_Array::value('extra', $item),
        );
      $menu['admin'] = array('breadcrumb' => $values);
    }
  
 +  /**
 +   * @param bool $all
 +   *
 +   * @return mixed
 +   * @throws Exception
 +   */
    static function &getNavigation($all = FALSE) {
      CRM_Core_Error::fatal();
  
      return $values;
    }
  
 +  /**
 +   * @return null
 +   */
    static function &getAdminLinks() {
      $links = self::get('admin');
  
        if (array_key_exists($currentPath, $menu) &&
          isset($menu[$currentPath]['title'])
        ) {
 -        $urlVar = CRM_Utils_Array::value('path_arguments', $menu[$currentPath]) ? '&' . $menu[$currentPath]['path_arguments'] : '';
 +        $urlVar = !empty($menu[$currentPath]['path_arguments']) ? '&' . $menu[$currentPath]['path_arguments'] : '';
          $crumbs[] = array(
            'title' => $menu[$currentPath]['title'],
            'url' => CRM_Utils_System::url($currentPath,
      return $crumbs;
    }
  
 +  /**
 +   * @param $menu
 +   * @param $path
 +   */
    static function buildReturnUrl(&$menu, $path) {
      if (!isset($menu[$path]['return_url'])) {
        list($menu[$path]['return_url'], $menu[$path]['return_url_args']) = self::getReturnUrl($menu, $path);
      }
    }
  
 +  /**
 +   * @param $menu
 +   * @param $path
 +   *
 +   * @return array
 +   */
    static function getReturnUrl(&$menu, $path) {
      if (!isset($menu[$path]['return_url'])) {
        $pathElements = explode('/', $path);
      }
    }
  
 +  /**
 +   * @param $menu
 +   * @param $path
 +   */
    static function fillComponentIds(&$menu, $path) {
      static $cache = array();
  
      }
    }
  
 +  /**
 +   * @param $path
 +   *
 +   * @return null
 +   */
    static function get($path) {
      // return null if menu rebuild
      $config = CRM_Core_Config::singleton();
@@@ -698,11 -646,6 +704,11 @@@ UNION 
      return $menuPath;
    }
  
 +  /**
 +   * @param $pathArgs
 +   *
 +   * @return mixed
 +   */
    static function getArrayForPathArgs($pathArgs) {
      if (!is_string($pathArgs)) {
        return;
      $elements = explode(',', $pathArgs);
      //CRM_Core_Error::debug( 'e', $elements );
      foreach ($elements as $keyVal) {
 -      list($key, $val) = explode('=', $keyVal);
 +      list($key, $val) = explode('=', $keyVal, 2);
        $arr[$key] = $val;
      }
  
index cb29a7ca757560d1886fc2e32e42f0d12c0c178d,621f2aac281089e5c29ca782950da7b0ec4941bb..2dbbe364193b1c29396fd8001e12f267ce5087c4
@@@ -1,9 -1,9 +1,9 @@@
  <?php
  /*
    +--------------------------------------------------------------------+
 -  | CiviCRM version 4.4                                                |
 +  | CiviCRM version 4.5                                                |
    +--------------------------------------------------------------------+
 -  | Copyright CiviCRM LLC (c) 2004-2013                                |
 +  | Copyright CiviCRM LLC (c) 2004-2014                                |
    +--------------------------------------------------------------------+
    | This file is a part of CiviCRM.                                    |
    |                                                                    |
@@@ -28,7 -28,7 +28,7 @@@
  /**
   *
   * @package CRM
 - * @copyright CiviCRM LLC (c) 2004-2013
 + * @copyright CiviCRM LLC (c) 2004-2014
   * $Id$
   *
   */
   */
  class CRM_Price_BAO_PriceSet extends CRM_Price_DAO_PriceSet {
  
 +  
 +  /**
 +   * static field for default price set details
 +   *
 +   * @var array
 +   * @static
 +   */
 +  static $_defaultPriceSet = NULL;
 +
    /**
     * class constructor
     */
@@@ -65,9 -56,6 +65,9 @@@
     * @static
     */
    static function create(&$params) {
 +    if(empty($params['id']) && empty($params['name'])) {
 +      $params['name'] = CRM_Utils_String::munge($params['title'], '_', 242);
 +    }
      $priceSetBAO = new CRM_Price_BAO_PriceSet();
      $priceSetBAO->copyValues($params);
      if (self::eventPriceSetDomainID()) {
    /**
     * update the is_active flag in the db
     *
 -   * @param  int      $id         id of the database record
 -   * @param  boolean  $is_active  value we want to set the is_active field
 +   * @param  int $id id of the database record
 +   * @param $isActive
 +   *
 +   * @internal param bool $is_active value we want to set the is_active field
     *
     * @return Object             DAO object on sucess, null otherwise
     * @static
     *
     * @param string $entity
     *
 -   * @return id $priceSetID
 +   * @return array $defaultPriceSet default price set
     *
     * @access public
     * @static
     *
     */
    public static function getDefaultPriceSet($entity = 'contribution') {
 -    if ($entity == 'contribution') {
 -      $entityName = 'default_contribution_amount';
 +    if (!empty(self::$_defaultPriceSet[$entity])) {
 +      return self::$_defaultPriceSet[$entity];
      }
 -    else if ($entity == 'membership') {
 +    $entityName = 'default_contribution_amount';
 +    if ($entity == 'membership') {
        $entityName = 'default_membership_type_amount';
      }
  
      $sql = "
 -SELECT      ps.id AS setID, pfv.price_field_id AS priceFieldID, pfv.id AS priceFieldValueID, pfv.name, pfv.label
 +SELECT      ps.id AS setID, pfv.price_field_id AS priceFieldID, pfv.id AS priceFieldValueID, pfv.name, pfv.label, pfv.membership_type_id, pfv.amount, pfv.financial_type_id
  FROM        civicrm_price_set ps
  LEFT JOIN   civicrm_price_field pf ON pf.`price_set_id` = ps.id
  LEFT JOIN   civicrm_price_field_value pfv ON pfv.price_field_id = pf.id
@@@ -140,21 -125,16 +140,21 @@@ WHERE       ps.name = '{$entityName}
  ";
  
      $dao = CRM_Core_DAO::executeQuery($sql);
 -    $defaultPriceSet = array();
 +    self::$_defaultPriceSet[$entity] = array();
      while ($dao->fetch()) {
 -      $defaultPriceSet[$dao->priceFieldValueID]['setID'] = $dao->setID;
 -      $defaultPriceSet[$dao->priceFieldValueID]['priceFieldID'] = $dao->priceFieldID;
 -      $defaultPriceSet[$dao->priceFieldValueID]['name'] = $dao->name;
 -      $defaultPriceSet[$dao->priceFieldValueID]['label'] = $dao->label;
 -      $defaultPriceSet[$dao->priceFieldValueID]['priceFieldValueID'] = $dao->priceFieldValueID;
 +      self::$_defaultPriceSet[$entity][$dao->priceFieldValueID] = array(
 +       'setID' => $dao->setID,
 +       'priceFieldID' => $dao->priceFieldID,
 +       'name' => $dao->name,
 +       'label' => $dao->label,
 +       'priceFieldValueID' => $dao->priceFieldValueID,
 +       'membership_type_id' => $dao->membership_type_id,
 +       'amount' => $dao->amount,
 +       'financial_type_id' => $dao->financial_type_id,
 +      );
      }
  
 -    return $defaultPriceSet;
 +    return self::$_defaultPriceSet[$entity];
    }
  
    /**
    /**
     * Return a list of all forms which use this price set.
     *
 -   * @param int  $id id of price set
 -   * @param str  $simpleReturn - get raw data. Possible values: 'entity', 'table'
 +   * @param int $id id of price set
 +   * @param bool|string $simpleReturn - get raw data. Possible values: 'entity', 'table'
     *
     * @return array
     */
@@@ -352,8 -332,6 +352,8 @@@ WHERE     ct.id = cp.financial_type_id 
     *
     * @param string $entityTable
     * @param integer $entityId
 +   *
 +   * @return mixed
     */
    public static function removeFrom($entityTable, $entityId) {
      $dao               = new CRM_Price_DAO_PriceSetEntity();
     * Used For value for events:1, contribution:2, membership:3
     *
     * @param string $entityTable
 -   * @param int    $entityId
 -   * @param int    $usedFor ( price set that extends/used for particular component )
 +   * @param int $entityId
 +   * @param int $usedFor ( price set that extends/used for particular component )
 +   *
 +   * @param null $isQuickConfig
 +   * @param null $setName
     *
     * @return integer|false price_set_id, or false if none found
     */
    }
  
    /**
 -   * Find a price_set_id associatied with the given option value or  field ID
 +   * Find a price_set_id associated with the given option value or  field ID
     *
     * @param array $params (reference) an assoc array of name/value pairs
     *                      array may contain either option id or
     *                      price field id
     *
 -   * @return price set id on success, null  otherwise
 +   * @return integer|NULL price set id on success, null  otherwise
     * @static
     * @access public
     */
    /**
     * Return an associative array of all price sets
     *
 -   * @param bool   $withInactive        whether or not to include inactive entries
 -   * @param string $extendComponentName name of the component like 'CiviEvent','CiviContribute'
 +   * @param bool $withInactive whether or not to include inactive entries
 +   * @param bool|string $extendComponentName name of the component like 'CiviEvent','CiviContribute'
     *
     * @return array associative array of id => name
     */
     *
     * An array containing price set details (including price fields) is returned
     *
 -   * @param int $setId - price set id whose details are needed
 +   * @param $setID
 +   * @param bool $required
 +   * @param bool $validOnly
 +   *
 +   * @internal param int $setId - price set id whose details are needed
     *
     * @return array $setTree - array consisting of field details
     */
    public static function getSetDetail($setID, $required = TRUE, $validOnly = FALSE) {
      // create a new tree
      $setTree = array();
 -    $select = $from = $where = $orderBy = '';
  
      $priceFields = array(
        'id',
@@@ -576,47 -548,6 +576,47 @@@ WHERE  id = %1"
      return $setTree;
    }
  
 +  /**
 +   * Get the Price Field ID. We call this function when more than one being present would represent an error
 +   * starting format derived from current(CRM_Price_BAO_PriceSet::getSetDetail($priceSetId))
 +   * @param array $priceSet
 +   *
 +   * @throws CRM_Core_Exception
 +   * @return int
 +   */
 +  static function getOnlyPriceFieldID(array $priceSet) {
 +    if(count($priceSet['fields']) > 1) {
 +      throw new CRM_Core_Exception(ts('expected only one price field to be in priceset but multiple are present'));
 +    }
 +    return (int) implode('_', array_keys($priceSet['fields']));
 +  }
 +
 +  /**
 +   * Get the Price Field Value ID. We call this function when more than one being present would represent an error
 +   * current(CRM_Price_BAO_PriceSet::getSetDetail($priceSetId))
 +   * @param array $priceSet
 +   *
 +   * @throws CRM_Core_Exception
 +   * @return int
 +   */
 +  static function getOnlyPriceFieldValueID(array $priceSet) {
 +    $priceFieldID = self::getOnlyPriceFieldID($priceSet);
 +    if(count($priceSet['fields'][$priceFieldID]['options']) > 1) {
 +      throw new CRM_Core_Exception(ts('expected only one price field to be in priceset but multiple are present'));
 +    }
 +    return (int) implode('_', array_keys($priceSet['fields'][$priceFieldID]['options']));
 +  }
 +
 +
 +  /**
 +   * @param CRM_Core_Form $form
 +   * @param $id
 +   * @param string $entityTable
 +   * @param bool $validOnly
 +   * @param null $priceSetId
 +   *
 +   * @return bool|false|int|null
 +   */
    static function initSet(&$form, $id, $entityTable = 'civicrm_event', $validOnly = FALSE, $priceSetId = NULL) {
      if (!$priceSetId) {
        $priceSetId = self::getFor($entityTable, $id);
      return FALSE;
    }
  
 +  /**
 +   * @param $fields
 +   * @param $params
 +   * @param $lineItem
 +   * @param string $component
 +   */
    static function processAmount(&$fields, &$params, &$lineItem, $component = '') {
      // using price set
      $totalPrice = 0;
        $autoRenew[0] = $autoRenew[1] = $autoRenew[2] = 0;
      }
      foreach ($fields as $id => $field) {
 -      if (!CRM_Utils_Array::value("price_{$id}", $params) ||
 +      if (empty($params["price_{$id}"]) ||
          (empty($params["price_{$id}"]) && $params["price_{$id}"] == NULL)
        ) {
          // skip if nothing was submitted for this field
  
        switch ($field['html_type']) {
          case 'Text':
-           $params["price_{$id}"] = array(key($field['options']) => $params["price_{$id}"]);
+           $firstOption = reset($field['options']);
+           $params["price_{$id}"] = array($firstOption['id'] => $params["price_{$id}"]);
            CRM_Price_BAO_LineItem::format($id, $params, $field, $lineItem);
-           $totalPrice += $lineItem[key($field['options'])]['line_total'];
+           $totalPrice += $lineItem[$firstOption['id']]['line_total'];
            break;
  
          case 'Radio':
            if (
              $component &&
              // auto_renew exists and is empty in some workflows, which php treat as a 0
 -            // and hence we explicity check to see if auto_renew is numeric
 +            // and hence we explicitly check to see if auto_renew is numeric
              isset($lineItem[$optionValueId]['auto_renew']) &&
              is_numeric($lineItem[$optionValueId]['auto_renew'])
            ) {
    /**
     * Function to build the price set form.
     *
 -   * @return None
 +   * @param CRM_Core_Form $form
 +   *
 +   * @return void
     * @access public
     */
    static function buildPriceSet(&$form) {
  
      $priceSet           = self::getSetDetail($priceSetId, TRUE, $validFieldsOnly);
      $form->_priceSet    = CRM_Utils_Array::value($priceSetId, $priceSet);
 +    $validPriceFieldIds = array_keys($form->_priceSet['fields']);
      $form->_quickConfig = $quickConfig = 0;
      if (CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $priceSetId, 'is_quick_config')) {
        $quickConfig = 1;
      // call the hook.
      CRM_Utils_Hook::buildAmount($component, $form, $feeBlock);
  
 -    foreach ($feeBlock as $field) {
 +    // CRM-14492 Admin price fields should show up on event registration if user has 'administer CiviCRM' permissions
 +    $adminFieldVisible = false;
 +    if (CRM_Core_Permission::check('administer CiviCRM')) {
 +      $adminFieldVisible = true;
 +    }
 +
 +    foreach ($feeBlock as $id => $field) {
        if (CRM_Utils_Array::value('visibility', $field) == 'public' ||
 +        (CRM_Utils_Array::value('visibility', $field) == 'admin' && $adminFieldVisible == true) ||
          !$validFieldsOnly
        ) {
          $options = CRM_Utils_Array::value('options', $field);
              $form->assign('ispricelifetime', TRUE);
            }
          }
 -        if (!is_array($options)) {
 +        if (!is_array($options) || !in_array($id, $validPriceFieldIds)) {
            continue;
          }
          CRM_Price_BAO_PriceField::addQuickFormElement($form,
      static $_contact_memberships = array();
      $checklifetime = FALSE;
      foreach ($options as $key => $value) {
 -      if (CRM_Utils_Array::value('membership_type_id', $value)) {
 +      if (!empty($value['membership_type_id'])) {
          if (!isset($_contact_memberships[$userid][$value['membership_type_id']])) {
            $_contact_memberships[$userid][$value['membership_type_id']] = CRM_Member_BAO_Membership::getContactMembership($userid, $value['membership_type_id'], FALSE);
          }
          $currentMembership = $_contact_memberships[$userid][$value['membership_type_id']];
 -        if (!empty($currentMembership) && !CRM_Utils_Array::value('end_date', $currentMembership)) {
 +        if (!empty($currentMembership) && empty($currentMembership['end_date'])) {
            unset($options[$key]);
            $checklifetime = TRUE;
          }
    /**
     * Function to set daefult the price set fields.
     *
 +   * @param $form
 +   * @param $defaults
 +   *
     * @return array $defaults
     * @access public
     */
      return $defaults;
    }
  
 +  /**
 +   * Supports event create function by setting up required price sets, not tested but expect
 +   * it will work for contribution page
 +   * @param array $params as passed to api/bao create fn
 +   * @param CRM_Core_DAO $entity object for given entity
 +   * @param string $entityName name of entity - e.g event
 +   */
 +  static function setPriceSets(&$params, $entity, $entityName) {
 +    if(empty($params['price_set_id']) || !is_array($params['price_set_id'])) {
 +      return;
 +    }
 +    // CRM-14069 note that we may as well start by assuming more than one.
 +    // currently the form does not pass in as an array & will be skipped
 +    // test is passing in as an array but I feel the api should have a metadata that allows
 +    // transform of single to array - seems good for managing transitions - in which case all api
 +    // calls that set price_set_id will hit this
 +    // e.g in getfields 'price_set_id' => array('blah', 'bao_type' => 'array') - causing
 +    // all separated values, strings, json half-separated values (in participant we hit this)
 +    // to be converted to json @ api layer
 +    $pse = new CRM_Price_DAO_PriceSetEntity();
 +    $pse->entity_table = 'civicrm_' . $entityName;
 +    $pse->entity_id = $entity->id;
 +    while ($pse->fetch()) {
 +      if(!in_array($pse->price_set_id, $params['price_set_id'])) {
 +        // note an even more aggressive form of this deletion currently happens in event form
 +        // past price sets discounts are made inaccessible by this as the discount_id is set to NULL
 +        // on the participant record
 +        if (CRM_Price_BAO_PriceSet::removeFrom('civicrm_' . $entityName, $entity->id)) {
 +          CRM_Core_BAO_Discount::del($this->_id,'civicrm_' . $entityName);
 +        }
 +      }
 +    }
 +    foreach ($params['price_set_id'] as $priceSetID) {
 +      CRM_Price_BAO_PriceSet::addTo('civicrm_' . $entityName, $entity->id, $priceSetID);
 +      //@todo - how should we do this - copied from form
 +      //if (CRM_Utils_Array::value('price_field_id', $params)) {
 +      //  $priceSetID = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceField', $params['price_field_id'], 'price_set_id');
 +      //  CRM_Price_BAO_PriceSet::setIsQuickConfig($priceSetID, 0);
 +      //}
 +    }
 +  }
    /**
     * Get field ids of a price set
     *
 -   * @param int id Price Set id
 +   * @param int $id Price Set id
     *
     * @return array of the field ids
     *
     * This function is to check price set permission
     *
     * @param int $sid the price set id
 +   *
 +   * @return bool
     */
    static function checkPermission($sid) {
      if ($sid && self::eventPriceSetDomainID()) {
     *
     * @param int $sid the price set id
     *
 +   * @param bool $onlyActive
 +   *
 +   * @return int|null|string
     * @access public
     * @static
     */
@@@ -1167,11 -1034,6 +1168,11 @@@ INNER JOIN  civicrm_price_set pset    O
      return $pricesetFieldCount[$sid];
    }
  
 +  /**
 +   * @param $ids
 +   *
 +   * @return array
 +   */
    public static function getMembershipCount($ids) {
      $queryString = "
  SELECT       count( pfv.id ) AS count, pfv.id AS id
@@@ -1259,9 -1121,6 +1260,9 @@@ GROUP BY     mt.member_of_contact_id"
      return array($dao->duration_interval, $dao->duration_unit);
    }
  
 +  /**
 +   * @return object
 +   */
    static function eventPriceSetDomainID() {
      return CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::MULTISITE_PREFERENCES_NAME,
        'event_price_set_domain_id',
@@@ -1324,16 -1183,13 +1325,16 @@@ WHERE       ps.id = %
      return false;
    }
  
 -  /*
 +  /**
     * Copy priceSet when event/contibution page is copied
     *
     * @params string $baoName  BAO name
     * @params int $id old event/contribution page id
     * @params int $newId newly created event/contribution page id
     *
 +   * @param string $baoName
 +   * @param integer $id
 +   * @param integer $newId
     */
    static function copyPriceSet($baoName, $id, $newId) {
      $priceSetId = CRM_Price_BAO_PriceSet::getFor($baoName, $id);
  
            $copyPriceSet = &CRM_Price_BAO_PriceSet::copy($setId);
  
 -          $copyDiscount = &CRM_Core_DAO::copyGeneric(
 +          CRM_Core_DAO::copyGeneric(
              'CRM_Core_DAO_Discount',
              array(
                'id' => $discountId,
diff --combined CRM/Price/Page/Field.php
index ec19d9238b9adcc535c7889b1607ed08ead86482,dae7188aae0fb50d5901b2a475ee3e3547669474..406927930323f86836dc7d292898113d1df80475
@@@ -1,9 -1,9 +1,9 @@@
  <?php
  /*
   +--------------------------------------------------------------------+
 - | CiviCRM version 4.4                                                |
 + | CiviCRM version 4.5                                                |
   +--------------------------------------------------------------------+
 - | Copyright CiviCRM LLC (c) 2004-2013                                |
 + | Copyright CiviCRM LLC (c) 2004-2014                                |
   +--------------------------------------------------------------------+
   | This file is a part of CiviCRM.                                    |
   |                                                                    |
@@@ -28,7 -28,7 +28,7 @@@
  /**
   *
   * @package CRM
 - * @copyright CiviCRM LLC (c) 2004-2013
 + * @copyright CiviCRM LLC (c) 2004-2014
   * $Id$
   *
   */
@@@ -43,8 -43,6 +43,8 @@@
   */
  class CRM_Price_Page_Field extends CRM_Core_Page {
  
 +  public $useLivePageJS = TRUE;
 +
    /**
     * The price set group id of the field
     *
@@@ -78,6 -76,8 +78,6 @@@
     * @access public
     */ function &actionLinks() {
      if (!isset(self::$_actionLinks)) {
 -      // helper variable for nicer formatting
 -      $deleteExtra = ts('Are you sure you want to delete this price field?');
        self::$_actionLinks = array(
          CRM_Core_Action::UPDATE => array(
            'name' => ts('Edit Price Field'),
          ),
          CRM_Core_Action::DISABLE => array(
            'name' => ts('Disable'),
 -          'extra' => 'onclick = "enableDisable( %%fid%%,\'' . 'CRM_Price_BAO_PriceField' . '\',\'' . 'enable-disable' . '\' );"',
 -          'ref' => 'disable-action',
 +          'ref' => 'crm-enable-disable',
            'title' => ts('Disable Price'),
          ),
          CRM_Core_Action::ENABLE => array(
            'name' => ts('Enable'),
 -          'extra' => 'onclick = "enableDisable( %%fid%%,\'' . 'CRM_Price_BAO_PriceField' . '\',\'' . 'disable-enable' . '\' );"',
 -          'ref' => 'enable-action',
 +          'ref' => 'crm-enable-disable',
            'title' => ts('Enable Price'),
          ),
          CRM_Core_Action::DELETE => array(
            'url' => 'civicrm/admin/price/field',
            'qs' => 'action=delete&reset=1&sid=%%sid%%&fid=%%fid%%',
            'title' => ts('Delete Price'),
 -          'extra' => 'onclick = "return confirm(\'' . $deleteExtra . '\');"',
          ),
        );
      }
  
        // need to translate html types from the db
        $htmlTypes = CRM_Price_BAO_PriceField::htmlTypes();
-       $priceField[$priceFieldBAO->id]['html_type'] = $htmlTypes[$priceField[$priceFieldBAO->id]['html_type']];
+       $priceField[$priceFieldBAO->id]['html_type_display'] = $htmlTypes[$priceField[$priceFieldBAO->id]['html_type']];
        $priceField[$priceFieldBAO->id]['order'] = $priceField[$priceFieldBAO->id]['weight'];
 -      $priceField[$priceFieldBAO->id]['action'] = CRM_Core_Action::formLink(self::actionLinks(), $action,
 +      $priceField[$priceFieldBAO->id]['action'] = CRM_Core_Action::formLink(
 +        self::actionLinks(),
 +        $action,
          array(
            'fid' => $priceFieldBAO->id,
            'sid' => $this->_sid,
 -        )
 +        ),
 +        ts('more'),
 +        FALSE,
 +        'priceField.row.actions',
 +        'PriceField',
 +        $priceFieldBAO->id
        );
      }
  
    /**
     * Preview price field
     *
 -   * @param int  $id    price field id
 +   * @param $fid
 +   *
 +   * @internal param int $id price field id
     *
     * @return void
     * @access public
index 470e131067699edbfe550eba33d4bbd2fc962d94,d5ec72cefa165d03c6c86e35d269143c3dd5280d..c8d0262bf0ac3303a2211c25f62b123355691365
@@@ -1,8 -1,8 +1,8 @@@
  {*
   +--------------------------------------------------------------------+
 - | CiviCRM version 4.4                                                |
 + | CiviCRM version 4.5                                                |
   +--------------------------------------------------------------------+
 - | Copyright CiviCRM LLC (c) 2004-2013                                |
 + | Copyright CiviCRM LLC (c) 2004-2014                                |
   +--------------------------------------------------------------------+
   | This file is a part of CiviCRM.                                    |
   |                                                                    |
      <div id="field_page">
      {strip}
    {* handle enable/disable actions*}
 -   {include file="CRM/common/enableDisable.tpl"}
 -    {include file="CRM/common/jsortable.tpl"}
 -         <table id="options" class="display">
 +   {include file="CRM/common/enableDisableApi.tpl"}
 +   {include file="CRM/common/crmeditable.tpl"}
 +         <table id="options" class="row-highlight">
           <thead>
           <tr>
              <th>{ts}Field Label{/ts}</th>
              <th>{ts}Field Type{/ts}</th>
 -            <th id="order" class="sortable">{ts}Order{/ts}</th>
 +            <th>{ts}Order{/ts}</th>
              <th>{ts}Req?{/ts}</th>
              <th>{ts}Enabled?{/ts}</th>
              <th>{ts}Active On{/ts}</th>
              <th>{ts}Expire On{/ts}</th>
 -            <th id="nosort">{ts}Price{/ts}</th>
 +            <th>{ts}Price{/ts}</th>
              <th></th>
 -            <th class="hiddenElement"></th>
          </tr>
          </thead>
          {foreach from=$priceField key=fid item=row}
 -      <tr id="row_{$row.id}"class="{cycle values="odd-row,even-row"} {$row.class}{if NOT $row.is_active} disabled{/if}">
 -            <td>{$row.label}</td>
 +      <tr id="price_field-{$row.id}" class="crm-entity {cycle values="odd-row,even-row"} {$row.class}{if NOT $row.is_active} disabled{/if}">
 +            <td class="crm-editable" data-field="label">{$row.label}</td>
-             <td>{$row.html_type}</td>
+             <td>{$row.html_type_display}</td>
 -            <td class="nowrap">{$row.order}</td>
 +            <td class="nowrap">{$row.weight}</td>
              <td>{if $row.is_required eq 1} {ts}Yes{/ts} {else} {ts}No{/ts} {/if}</td>
              <td id="row_{$row.id}_status">{if $row.is_active eq 1} {ts}Yes{/ts} {else} {ts}No{/ts} {/if}</td>
              <td>{if $row.active_on}{$row.active_on|date_format:"%Y-%m-%d %T"}{/if}</td>
              <td>{if $row.expire_on}{$row.expire_on|date_format:"%Y-%m-%d %T"}{/if}</td>
-             <td>{if $row.html_type eq "Text / Numeric Quantity"}{$row.price|crmMoney}{else}<a href="{crmURL p="civicrm/admin/price/field/option" q="action=browse&reset=1&sid=$sid&fid=$fid"}">{if $isReserved}{ts}View Price Options{/ts}{else}{ts}Edit Price Options{/ts}{/if}</a>{/if}</td>
+             <td>{if $row.html_type eq "Text"}{$row.price|crmMoney}{else}<a href="{crmURL p="civicrm/admin/price/field/option" q="action=browse&reset=1&sid=$sid&fid=$fid"}">{if $isReserved}{ts}View Price Options{/ts}{else}{ts}Edit Price Options{/ts}{/if}</a>{/if}</td>
              <td class="field-action">{$row.action|replace:'xx':$row.id}</td>
 -            <td class="order hiddenElement">{$row.weight}</td>
          </tr>
          {/foreach}
          </table>
          {if $action eq 16}
          <div class="messages status no-popup">
              <div class="icon inform-icon"></div>
 -            {capture assign=crmURL}{crmURL p='civicrm/admin/price/field q="action=add&reset=1&sid=$sid"}{/capture}
 -            {ts 1=$groupTitle 2=$crmURL}There are no fields for price set '%1', <a href='%2'>add one</a>.{/ts}
 +            {ts 1=$groupTitle 2=$crmURL}There are no fields for price set '%1'.{/ts}
 +        </div>
 +        <div class="action-link">
 +          <a href="{crmURL q="reset=1&action=add&sid=$sid"}" id="newPriceField" class="button"><span><div class="icon add-icon"></div>{ts}Add Price Field{/ts}</span></a>
          </div>
          {/if}
    {/if}
index 1be7073fbc5463559a8afb0b80255f0981ca8958,ef4592a7f8c4437677e3b75c2d8a1e26b89aa928..93623c243e43b9a26aa77c0ec2522eed39612506
@@@ -1,9 -1,9 +1,9 @@@
  <?php
  /*
   +--------------------------------------------------------------------+
 - | CiviCRM version 4.4                                                |
 + | CiviCRM version 4.5                                                |
   +--------------------------------------------------------------------+
 - | Copyright CiviCRM LLC (c) 2004-2013                                |
 + | Copyright CiviCRM LLC (c) 2004-2014                                |
   +--------------------------------------------------------------------+
   | This file is a part of CiviCRM.                                    |
   |                                                                    |
@@@ -33,13 -33,7 +33,13 @@@ require_once 'CiviTest/ContributionPage
  require_once 'CiviTest/Membership.php';
  require_once 'CRM/Core/Controller.php';
  
 +/**
 + * Class CRM_Member_BAO_MembershipTest
 + */
  class CRM_Member_BAO_MembershipTest extends CiviUnitTestCase {
 +  /**
 +   * @return array
 +   */
    function get_info() {
      return array(
        'name' => 'Membership BAOs',
      $membershipRenewal->controller = new CRM_Core_Controller;
      $isTestMembership = 0;
      $MembershipRenew =
 -      CRM_Member_BAO_Membership::renewMembership(
 +      CRM_Member_BAO_Membership::renewMembershipFormWrapper(
          $contactId,
          $this->_membershipTypeID,
          $isTestMembership,
        'membership_id',
        'Database checked on membershiplog record.'
      );
-     $this->assertEquals($MembershipRenew->membership_type_id, $this->_membershipTypeID, 'Verify membership type is changed during renewal.');
-     $this->assertEquals($MembershipRenew->end_date, $endDate, 'Verify correct end date is calculated after membership renewal');
+     $this->assertEquals($this->_membershipTypeID, $MembershipRenew->membership_type_id, 'Verify membership type is changed during renewal.');
+     $this->assertEquals($endDate, $MembershipRenew->end_date, 'Verify correct end date is calculated after membership renewal');
  
      $this->membershipDelete($membershipId);
      Contact::delete($contactId);
  
      $membershipRenewal = new CRM_Core_Form;
      $membershipRenewal->controller = new CRM_Core_Controller;
 -    $MembershipRenew = CRM_Member_BAO_Membership::renewMembership($contactId, $this->_membershipTypeID, $isTestMembership = 0, $membershipRenewal, NULL, NULL);
 +    $MembershipRenew = CRM_Member_BAO_Membership::renewMembershipFormWrapper($contactId, $this->_membershipTypeID, $isTestMembership = 0, $membershipRenewal, NULL, NULL);
  
      $this->assertDBNotNull('CRM_Member_BAO_MembershipLog',
        $MembershipRenew->id,