/**
  *
  * @throws EE_Error
  * @return string of html to display the field
  */
 public function display()
 {
     if (!$this->_input instanceof EE_Form_Input_With_Options_Base) {
         throw new EE_Error(sprintf(__('Cannot use Select Multiple Display Strategy with an input that doesn\'t have options', "event_espresso")));
     }
     $html = EEH_HTML::nl(0, 'select');
     $html .= '<select multiple';
     $html .= ' id="' . $this->_input->html_id() . '"';
     $html .= ' name="' . $this->_input->html_name() . '[]"';
     $class = $this->_input->required() ? $this->_input->required_css_class() . ' ' . $this->_input->html_class() : $this->_input->html_class();
     $html .= ' class="' . $class . '"';
     // add html5 required
     $html .= $this->_input->required() ? ' required' : '';
     $html .= ' style="' . $this->_input->html_style() . '"';
     $html .= '>';
     EE_Registry::instance()->load_helper('Array');
     EEH_HTML::indent(1, 'select');
     if (EEH_Array::is_multi_dimensional_array($this->_input->options())) {
         throw new EE_Error(sprintf(__("Select multiple display strategy does not allow for nested arrays of options.", "event_espresso")));
     } else {
         $html .= $this->_display_options($this->_input->options());
     }
     $html .= EEH_HTML::nl(-1, 'select') . "</select>";
     return $html;
 }
 /**
  * Writes $data to the csv file open in $filehandle. uses the array indices of $data for column headers
  *
  * @param string 	$filepath
  * @param array 	$data 2D array, 		first numerically-indexed,
  *                    						and next-level-down preferably indexed by string
  * @param boolean 	$write_column_headers 	whether or not we should add the keys in the bottom-most array
  * 											as a row for headers in the CSV.
  *                                            Eg, if $data looked like:
  *                                            array(
  *                                              	0=>array('EVT_ID'=>1,'EVT_name'=>'monkey'...),
  * 													1=>array(...,...)
  *                                            )
  *
  * @return boolean 		if we successfully wrote to the CSV or not. If there's no $data,
  * 						we consider that a success (because we wrote everything there was...nothing)
  * @throws EE_Error
  */
 public static function write_data_array_to_csv($filepath, $data, $write_column_headers = true)
 {
     $new_file_contents = '';
     //determine if $data is actually a 2d array
     if ($data && is_array($data) && is_array(EEH_Array::get_one_item_from_array($data))) {
         //make sure top level is numerically indexed,
         if (EEH_Array::is_associative_array($data)) {
             throw new EE_Error(sprintf(__("top-level array must be numerically indexed. Does these look like numbers to you? %s", "event_espresso"), implode(",", array_keys($data))));
         }
         $item_in_top_level_array = EEH_Array::get_one_item_from_array($data);
         //now, is the last item in the top-level array of $data an associative or numeric array?
         if ($write_column_headers && EEH_Array::is_associative_array($item_in_top_level_array)) {
             //its associative, so we want to output its keys as column headers
             $keys = array_keys($item_in_top_level_array);
             $new_file_contents .= EEH_Export::get_csv_row($keys);
         }
         //start writing data
         foreach ($data as $data_row) {
             $new_file_contents .= EEH_Export::get_csv_row($data_row);
         }
         return EEH_File::write_to_file($filepath, EEH_File::get_file_contents($filepath) . $new_file_contents);
     } else {
         //no data TO write... so we can assume that's a success
         return true;
     }
 }
 /**
  *
  * @throws EE_Error
  * @return string of html to display the field
  */
 function display()
 {
     if (!$this->_input instanceof EE_Form_Input_With_Options_Base) {
         throw new EE_Error(sprintf(__('Cannot use Select Display Strategy with an input that doesn\'t have options', 'event_espresso')));
     }
     EE_Registry::instance()->load_helper('Array');
     $html = EEH_HTML::nl(0, 'select');
     $html .= '<select';
     $html .= ' id="' . $this->_input->html_id() . '"';
     $html .= ' name="' . $this->_input->html_name() . '"';
     $class = $this->_input->required() ? $this->_input->required_css_class() . ' ' . $this->_input->html_class() : $this->_input->html_class();
     $html .= ' class="' . $class . '"';
     // add html5 required
     $html .= $this->_input->required() ? ' required' : '';
     $html .= ' style="' . $this->_input->html_style() . '"';
     $html .= '>';
     //		EEH_HTML::indent( 1, 'select' );
     if (EEH_Array::is_multi_dimensional_array($this->_input->options())) {
         EEH_HTML::indent(1, 'optgroup');
         foreach ($this->_input->options() as $opt_group_label => $opt_group) {
             $html .= EEH_HTML::nl(0, 'optgroup') . '<optgroup label="' . esc_attr($opt_group_label) . '">';
             EEH_HTML::indent(1, 'option');
             $html .= $this->_display_options($opt_group);
             $html .= EEH_HTML::indent(-1, 'option');
             $html .= EEH_HTML::nl(0, 'optgroup') . '</optgroup>';
         }
         EEH_HTML::indent(-1, 'optgroup');
     } else {
         $html .= $this->_display_options($this->_input->options());
     }
     $html .= EEH_HTML::nl(0, 'select') . '</select>';
     //		$html.= EEH_HTML::nl( -1, 'select' ) . '</select>';
     return $html;
 }
function ee_resurse_into_array($data)
{
    if (is_object($data) || $data instanceof __PHP_Incomplete_Class) {
        //is_object($incomplete_class) actually returns false, hence why we check for it
        $data = (array) $data;
    }
    if (is_array($data)) {
        if (EEH_Array::is_associative_array($data)) {
            ?>
			<table class="widefat">
				<tbody>
					<?php 
            foreach ($data as $data_key => $data_values) {
                ?>
						<tr>
							<td>
								<?php 
                echo $data_key;
                ?>
							</td>
							<td>
								<?php 
                ee_resurse_into_array($data_values);
                ?>
							</td>
						</tr>
						<?php 
            }
            ?>
				</tbody>
			</table>
			<?php 
        } else {
            ?>
			<ul>
				<?php 
            foreach ($data as $datum) {
                echo "<li>";
                ee_resurse_into_array($datum);
                echo "</li>";
            }
            ?>
			</ul>
			<?php 
        }
    } else {
        //simple value
        echo $data;
    }
}
 /**
  * @param array $input_settings     {
  * @type string $model_name         the name of model to be used for searching, both via the REST API and server-side model queries
  * @type array  $query_params       default query parameters which will apply to both REST API queries and server-side queries. This should be 
  *									in the exact format that will be used for server-side model usage (eg use index 0 for where conditions, not 
  *									the string "where")
  * @type string $value_field_name   the name of the model field on this model to
  *                                  be used for the HTML select's option's values
  * @type string $display_field_name the name of the model field on this model
  *                                  to be used for the HTML select's option's display text
  * @type array  $select2_args       arguments to be passed directly into the select2's JS constructor
  *                                  }
  *                                  And the arguments accepted by EE_Form_Input_With_Options_Base
  * @throws \EE_Error
  */
 public function __construct($input_settings = array())
 {
     //needed input settings:
     //select2_args
     $this->_model_name = EEH_Array::is_set($input_settings, 'model_name', null);
     $model = $this->_get_model();
     $query_params = EEH_Array::is_set($input_settings, 'query_params', array('limit' => 10, 'caps' => EEM_Base::caps_read_admin));
     $this->_value_field_name = EEH_Array::is_set($input_settings, 'value_field_name', $model->primary_key_name());
     $this->_display_field_name = EEH_Array::is_set($input_settings, 'display_field_name', $model->get_a_field_of_type('EE_Text_Field_Base')->get_name());
     $this->_add_validation_strategy(new EE_Model_Matching_Query_Validation_Strategy('', $this->_model_name, $query_params, $this->_value_field_name));
     //get resource endpoint
     $rest_controller = new EventEspresso\core\libraries\rest_api\controllers\model\Read();
     $rest_controller->set_requested_version(EED_Core_Rest_Api::latest_rest_api_version());
     $url = $rest_controller->get_versioned_link_to(EEH_Inflector::pluralize_and_lower($this->_model_name));
     $default_select2_args = array('ajax' => array('url' => $url, 'dataType' => 'json', 'delay' => '250', 'data_interface' => 'EE_Select2_REST_API_Interface', 'data_interface_args' => array('default_query_params' => (object) Model_Data_Translator::prepare_query_params_for_rest_api($query_params, $model), 'display_field' => $this->_display_field_name, 'value_field' => $this->_value_field_name, 'nonce' => wp_create_nonce('wp_rest'))), 'cache' => true, 'width' => '100');
     $select2_args = array_replace_recursive($default_select2_args, (array) EEH_Array::is_set($input_settings, 'select2_args', array()));
     $this->set_display_strategy(new EE_Select2_Display_Strategy($select2_args));
     parent::__construct(array(), $input_settings);
 }
 /**
  * 		generates HTML for the Registration main meta box
  *		@access public
  *		@return void
  */
 public function _reg_attendees_meta_box()
 {
     $REG = EEM_Registration::instance();
     //get all other registrations on this transaction, and cache
     //the attendees for them so we don't have to run another query using force_join
     $registrations = $REG->get_all(array(array('TXN_ID' => $this->_registration->transaction_ID(), 'REG_ID' => array('!=', $this->_registration->ID())), 'force_join' => array('Attendee')));
     $this->_template_args['attendees'] = array();
     $this->_template_args['attendee_notice'] = '';
     EE_Registry::instance()->load_helper('Array');
     if (empty($registrations) || is_array($registrations) && !EEH_Array::get_one_item_from_array($registrations)) {
         EE_Error::add_error(__('There are no records attached to this registration. Something may have gone wrong with the registration', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
         $this->_template_args['attendee_notice'] = EE_Error::get_notices();
     } else {
         $att_nmbr = 1;
         foreach ($registrations as $registration) {
             /* @var $registration EE_Registration */
             $attendee = $registration->attendee() ? $registration->attendee() : EEM_Attendee::instance()->create_default_object();
             $this->_template_args['attendees'][$att_nmbr]['fname'] = $attendee->fname();
             //( isset( $registration->ATT_fname ) & ! empty( $registration->ATT_fname ) ) ? $registration->ATT_fname : '';
             $this->_template_args['attendees'][$att_nmbr]['lname'] = $attendee->lname();
             //( isset( $registration->ATT_lname ) & ! empty( $registration->ATT_lname ) ) ? $registration->ATT_lname : '';
             $this->_template_args['attendees'][$att_nmbr]['email'] = $attendee->email();
             //( isset( $registration->ATT_email ) & ! empty( $registration->ATT_email ) ) ? $registration->ATT_email : '';
             $this->_template_args['attendees'][$att_nmbr]['final_price'] = $registration->final_price();
             //( isset( $registration->REG_final_price ) & ! empty( $registration->REG_final_price ) ) ? $registration->REG_final_price : '';
             $this->_template_args['attendees'][$att_nmbr]['address'] = implode(', ', $attendee->full_address_as_array());
             $this->_template_args['attendees'][$att_nmbr]['att_link'] = self::add_query_args_and_nonce(array('action' => 'edit_attendee', 'post' => $attendee->ID()), REG_ADMIN_URL);
             $att_nmbr++;
         }
         //EEH_Debug_Tools::printr( $attendees, '$attendees  <br /><span style="font-size:10px;font-weight:normal;">( file: '. __FILE__ . ' - line no: ' . __LINE__ . ' )</span>', 'auto' );
         $this->_template_args['event_name'] = $this->_registration->event_obj()->name();
         $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
         //			$this->_template_args['registration_form_url'] = add_query_arg( array( 'action' => 'edit_registration', 'process' => 'attendees'  ), REG_ADMIN_URL );
     }
     $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_attendees.template.php';
     echo EEH_Template::display_template($template_path, $this->_template_args, TRUE);
 }
 /**
  * Writes $data to the csv file open in $filehandle. uses the array indices of $data for column headers
  * @param array $data 2D array, first numerically-indexed, and next-level-down preferably indexed by string
  * @param boolean $add_csv_column_names whether or not we should add the keys in the bottom-most array as a row for headers in the CSV.
  * Eg, if $data looked like array(0=>array('EVT_ID'=>1,'EVT_name'=>'monkey'...), 1=>array(...),...))
  * then the first row we'd write to the CSV would be "EVT_ID,EVT_name,..."
  * @return boolean if we successfully wrote to the CSV or not. If there's no $data, we consider that a success (because we wrote everything there was...nothing)
  */
 public function write_data_array_to_csv($filehandle, $data)
 {
     EE_Registry::instance()->load_helper('Array');
     //determine if $data is actually a 2d array
     if ($data && is_array($data) && is_array(EEH_Array::get_one_item_from_array($data))) {
         //make sure top level is numerically indexed,
         if (EEH_Array::is_associative_array($data)) {
             throw new EE_Error(sprintf(__("top-level array must be numerically indexed. Does these look like numbers to you? %s", "event_espresso"), implode(",", array_keys($data))));
         }
         $item_in_top_level_array = EEH_Array::get_one_item_from_array($data);
         //now, is the last item in the top-level array of $data an associative or numeric array?
         if (EEH_Array::is_associative_array($item_in_top_level_array)) {
             //its associative, so we want to output its keys as column headers
             $keys = array_keys($item_in_top_level_array);
             echo $this->fputcsv2($filehandle, $keys);
         }
         //start writing data
         foreach ($data as $data_row) {
             echo $this->fputcsv2($filehandle, $data_row);
         }
         return true;
     } else {
         //no data TO write... so we can assume that's a success
         return true;
     }
     //		//if 2nd level is indexed by strings, use those as csv column headers (ie, the first row)
     //
     //
     //		$no_table = TRUE;
     //
     //		// loop through data and add each row to the file/stream as csv
     //		foreach ( $data as $model_name => $model_data ) {
     //			// test first row to see if it is data or a model name
     //			$model = 	EE_Registry::instance();->load_model($model_name);
     //			//if the model really exists,
     //			if ( $model ) {
     //
     //				// we have a table name
     //				$no_table = FALSE;
     //
     //				// put the tablename into an array cuz that's how fputcsv rolls
     //				$model_name_row = array( 'MODEL', $model_name );
     //
     //				// add table name to csv output
     //				echo self::fputcsv2($filehandle, $model_name_row);
     //
     //				// now get the rest of the data
     //				foreach ( $model_data as $row ) {
     //					// output the row
     //					echo self::fputcsv2($filehandle, $row);
     //				}
     //
     //			}
     //
     //			if ( $no_table ) {
     //				// no table so just put the data
     //				echo self::fputcsv2($filehandle, $model_data);
     //			}
     //		} 		//		END OF foreach ( $data )
 }
 /**
  * Looks at all the models which are included in this query, and asks each
  * for their universal_where_params, and returns them in the same format as $query_params[0] (where),
  * so they can be merged
  * @param EE_Model_Query_Info_Carrier $query_info_carrier
  * @param string                      $use_default_where_conditions can be 'none','other_models_only', or 'all'.  'none' means NO default where conditions will be used AT ALL during this query.
  * 'other_models_only' means default where conditions from other models will be used, but not for this primary model. 'all', the default, means
  * default where conditions will apply as normal
  * @param array                       $where_query_params           like EEM_Base::get_all's $query_params[0]
  * @throws EE_Error
  * @return array like $query_params[0], see EEM_Base::get_all for documentation
  */
 private function _get_default_where_conditions_for_models_in_query(EE_Model_Query_Info_Carrier $query_info_carrier, $use_default_where_conditions = 'all', $where_query_params = array())
 {
     $allowed_used_default_where_conditions_values = array('all', 'this_model_only', 'other_models_only', 'minimum', 'none');
     if (!in_array($use_default_where_conditions, $allowed_used_default_where_conditions_values)) {
         throw new EE_Error(sprintf(__("You passed an invalid value to the query parameter 'default_where_conditions' of '%s'. Allowed values are %s", "event_espresso"), $use_default_where_conditions, implode(", ", $allowed_used_default_where_conditions_values)));
     }
     $universal_query_params = array();
     if ($use_default_where_conditions === 'all' || $use_default_where_conditions === 'this_model_only') {
         $universal_query_params = $this->_get_default_where_conditions();
     } else {
         if ($use_default_where_conditions === 'minimum') {
             $universal_query_params = $this->_get_minimum_where_conditions();
         }
     }
     if (in_array($use_default_where_conditions, array('all', 'other_models_only'))) {
         foreach ($query_info_carrier->get_model_names_included() as $model_relation_path => $model_name) {
             $related_model = $this->get_related_model_obj($model_name);
             $related_model_universal_where_params = $related_model->_get_default_where_conditions($model_relation_path);
             $overrides = $this->_override_defaults_or_make_null_friendly($related_model_universal_where_params, $where_query_params, $related_model, $model_relation_path);
             $universal_query_params = EEH_Array::merge_arrays_and_overwrite_keys($universal_query_params, $overrides);
         }
     }
     return $universal_query_params;
 }
 /**
  * Value provided should definetely be a serialized string. We should unserialize into an array
  * @param string $value_found_in_db_for_model_object
  * @return array
  */
 function prepare_for_set_from_db($value_found_in_db_for_model_object)
 {
     return EEH_Array::maybe_unserialize($value_found_in_db_for_model_object);
 }
 /**
  * Returns TRUE is this payment was set to approved during this request (or
  * is approved and was created during this request). False otherwise.
  * @return boolean
  */
 public function just_approved()
 {
     EE_Registry::instance()->load_helper('Array');
     $original_status = EEH_Array::is_set($this->_props_n_values_provided_in_constructor, 'STS_ID', $this->get_model()->field_settings_for('STS_ID')->get_default_value());
     $current_status = $this->status();
     if ($original_status !== EEM_Payment::status_id_approved && $current_status === EEM_Payment::status_id_approved) {
         return TRUE;
     } else {
         return FALSE;
     }
 }
    /**
     * Gets HTML for laying out a deeply-nested array (and objects) in a format
     * that's nice for presenting in the wp admin
     * @param mixed $data
     * @return string
     */
    public static function layout_array_as_table($data)
    {
        if (is_object($data) || $data instanceof __PHP_Incomplete_Class) {
            $data = (array) $data;
        }
        EE_Registry::instance()->load_helper('Array');
        ob_start();
        if (is_array($data)) {
            if (EEH_Array::is_associative_array($data)) {
                ?>
			<table class="widefat">
				<tbody>
					<?php 
                foreach ($data as $data_key => $data_values) {
                    ?>
						<tr>
							<td>
								<?php 
                    echo $data_key;
                    ?>
							</td>
							<td>
								<?php 
                    echo self::layout_array_as_table($data_values);
                    ?>
							</td>
						</tr>
						<?php 
                }
                ?>
				</tbody>
			</table>
			<?php 
            } else {
                ?>
			<ul>
				<?php 
                foreach ($data as $datum) {
                    echo "<li>";
                    echo self::layout_array_as_table($datum);
                    echo "</li>";
                }
                ?>
			</ul>
			<?php 
            }
        } else {
            //simple value
            echo $data;
        }
        return ob_get_clean();
    }
 /**
  * Value provided should definetely be a serialized string. We should unserialize into an array
  * @param string $value_found_in_db_for_model_object
  * @return array
  */
 function prepare_for_set_from_db($value_found_in_db_for_model_object)
 {
     EE_Registry::instance()->load_helper('Array');
     return EEH_Array::maybe_unserialize($value_found_in_db_for_model_object);
 }
 /**
  *    test_insert_into_array_with_mixed_indexes
  */
 function test_insert_into_array_with_mixed_indexes()
 {
     // starting data
     $fruits = array(1 => 'one', 'p' => 'potato');
     // add to start
     $fruits = EEH_Array::insert_into_array($fruits, array(2 => 'two'));
     //echo '$fruits: ', var_dump( $fruits );
     $this->assertEquals('two', reset($fruits));
     $this->assertEquals('one', next($fruits));
     $this->assertEquals('potato', next($fruits));
     // add to end
     $fruits = EEH_Array::insert_into_array($fruits, array('t' => 'tomato'), null, false);
     //echo '$fruits: ', var_dump( $fruits );
     $this->assertEquals('two', reset($fruits));
     $this->assertEquals('one', next($fruits));
     $this->assertEquals('potato', next($fruits));
     $this->assertEquals('tomato', next($fruits));
     // add to middle before potato
     $fruits = EEH_Array::insert_into_array($fruits, array(3 => 'three'), 'p');
     //echo '$fruits: ', var_dump( $fruits );
     $this->assertEquals('two', reset($fruits));
     $this->assertEquals('one', next($fruits));
     $this->assertEquals('three', next($fruits));
     $this->assertEquals('potato', next($fruits));
     $this->assertEquals('tomato', next($fruits));
     // try to bork keys and add onto the end while also specifying the last known key
     $fruits = EEH_Array::insert_into_array($fruits, array(6 => 'tornado'), 't', false);
     $this->assertEquals('two', reset($fruits));
     $this->assertEquals('one', next($fruits));
     $this->assertEquals('three', next($fruits));
     $this->assertEquals('potato', next($fruits));
     $this->assertEquals('tomato', next($fruits));
     $this->assertEquals('tornado', next($fruits));
     // add to end and reindex keys
     $fruits = EEH_Array::insert_into_array($fruits, array('g' => 'GO NATO'), null, false, false);
     $this->assertEquals('two', reset($fruits));
     $this->assertEquals('one', next($fruits));
     $this->assertEquals('three', next($fruits));
     $this->assertEquals('potato', next($fruits));
     $this->assertEquals('tomato', next($fruits));
     $this->assertEquals('tornado', next($fruits));
     $this->assertEquals('GO NATO', next($fruits));
     // now test keys
     reset($fruits);
     $this->assertEquals(0, key($fruits));
     next($fruits);
     $this->assertEquals(1, key($fruits));
     next($fruits);
     $this->assertEquals(2, key($fruits));
     next($fruits);
     $this->assertEquals('p', key($fruits));
     next($fruits);
     $this->assertEquals('t', key($fruits));
     next($fruits);
     $this->assertEquals(3, key($fruits));
     next($fruits);
     $this->assertEquals(4, key($fruits));
 }
 /**
  * Makes sure $arr is a flat array, not a multidimensional one
  * @param array $arr
  * @return array
  */
 protected function _flatten_select_options($arr)
 {
     $flat_array = array();
     EE_Registry::instance()->load_helper('Array');
     if (EEH_Array::is_multi_dimensional_array($arr)) {
         foreach ($arr as $sub_array) {
             foreach ($sub_array as $key => $value) {
                 $flat_array[$key] = $value;
                 $this->_set_label_size($value);
             }
         }
     } else {
         foreach ($arr as $key => $value) {
             $flat_array[$key] = $value;
             $this->_set_label_size($value);
         }
     }
     return $flat_array;
 }
 /**
  * add_subsections
  * Adds the listed subsections to the form section.
  * If $subsection_name_to_target is provided,
  * then new subsections are added before or after that subsection,
  * otherwise to the start or end of the entire subsections array.
  *
  * @param EE_Form_Section_Base[] $new_subsections                                                 array of new form subsections where keys are their names
  * @param string                 $subsection_name_to_target                                       an existing for section that $new_subsections should be added before or after
  *                                                                                                IF $subsection_name_to_target is null, then $new_subsections will be added to
  *                                                                                                the beginning or end of the entire subsections array
  * @param boolean                $add_before                                                      whether to add $new_subsections, before or after $subsection_name_to_target,
  *                                                                                                or if $subsection_name_to_target is null, before or after entire subsections array
  * @return void
  * @throws \EE_Error
  */
 public function add_subsections($new_subsections, $subsection_name_to_target = NULL, $add_before = true)
 {
     foreach ($new_subsections as $subsection_name => $subsection) {
         if (!$subsection instanceof EE_Form_Section_Base) {
             EE_Error::add_error(sprintf(__("Trying to add a %s as a subsection (it was named '%s') to the form section '%s'. It was removed.", "event_espresso"), get_class($subsection), $subsection_name, $this->name()));
             unset($new_subsections[$subsection_name]);
         }
     }
     $this->_subsections = EEH_Array::insert_into_array($this->_subsections, $new_subsections, $subsection_name_to_target, $add_before);
     /*$subsections_before = array();
     		if( $subsection_name_to_target ){
     			foreach( $this->_subsections as $subsection_name => $subsection ) {
     				if ( $add_before && $subsection_name == $subsection_name_to_target ) {
     					break;
     				}
     				$subsections_before[$subsection_name] = $subsection;
     				if ( ! $add_before && $subsection_name == $subsection_name_to_target ) {
     					break;
     				}
     			}
     			$subsections_after = array_diff_key($this->_subsections, $subsections_before);
     			$this->_subsections = array_merge($subsections_before,$new_subsections,$subsections_after);
     		}else{
     			if( $add_before ) {
     				//add before nothing, meaning nothing should be after it
     				//don't use array_merge because keys might be numeric and we want to preserve their keys
     				foreach( $new_subsections as $key => $subsection ){
     					$this->_subsections[ $key ] = $subsection;
     				}
     			}else{
     				//add after nothing, meaning nothing should be before it
     				//again don't use array_merge because we want
     				foreach( $this->_subsections as $key => $subsection ) {
     					$new_subsections[ $key ] = $subsection;
     				}
     				$this->_subsections = $new_subsections;
     			}
     		}*/
     if ($this->_construction_finalized) {
         foreach ($this->_subsections as $name => $subsection) {
             $subsection->_construct_finalize($this, $name);
         }
     }
 }
 /**
  * This is a method for restoring this_obj using details from the given $revision_id
  *
  * @param int $revision_id 		ID of the revision we're getting data from
  * @param array $related_obj_names if included this will be used to restore for related obj
  *                                 if not included then we just do restore on the meta.
  *                                 We will accept an array of related_obj_names for restoration here.
  * @param array $where_query       You can optionally include an array of key=>value pairs
  *                                 that allow you to further constrict the relation to being added.
  *                                 However, keep in mind that the columns (keys) given
  *                                 must match a column on the JOIN table and currently
  *                                 only the HABTM models accept these additional conditions.
  *                                 Also remember that if an exact match isn't found for these extra cols/val pairs,
  *                                 then a NEW row is created in the join table.
  *                                 This array is INDEXED by RELATED OBJ NAME (so it corresponds with the obj_names sent);
  * @return void
  */
 public function restore_revision($revision_id, $related_obj_names = array(), $where_query = array())
 {
     //get revision object
     $revision_obj = $this->get_model()->get_one_by_ID($revision_id);
     if ($revision_obj instanceof EE_CPT_Base) {
         //no related_obj_name so we assume we're saving a revision on this object.
         if (empty($related_obj_names)) {
             $fields = $this->get_model()->get_meta_table_fields();
             foreach ($fields as $field) {
                 $this->set($field, $revision_obj->get($field));
             }
             $this->save();
         }
         $related_obj_names = (array) $related_obj_names;
         foreach ($related_obj_names as $related_name) {
             //related_obj_name so we're saving a revision on an object related to this object
             //do we have $where_query params for this related object?  If we do then we include that.
             $cols_n_values = isset($where_query[$related_name]) ? $where_query[$related_name] : array();
             $where_params = !empty($cols_n_values) ? array($cols_n_values) : array();
             $related_objs = $this->get_many_related($related_name, $where_params);
             $revision_related_objs = $revision_obj->get_many_related($related_name, $where_params);
             //load helper
             EE_Registry::instance()->load_helper('Array');
             //remove related objs from this object that are not in revision
             //array_diff *should* work cause I think objects are indexed by ID?
             $related_to_remove = EEH_Array::object_array_diff($related_objs, $revision_related_objs);
             foreach ($related_to_remove as $rr) {
                 $this->_remove_relation_to($rr, $related_name, $cols_n_values);
             }
             //add all related objs attached to revision to this object
             foreach ($revision_related_objs as $r_obj) {
                 $this->_add_relation_to($r_obj, $related_name, $cols_n_values);
             }
         }
     }
 }
 public function test_process_payment__offline()
 {
     /** @type EE_Payment_Method $pm */
     $pm = $this->new_model_obj_with_dependencies('Payment_Method', array('PMD_type' => 'Admin_Only'));
     $transaction = $this->_new_typical_transaction();
     global $wp_actions;
     EE_Registry::instance()->load_helper('Array');
     $successful_payment_actions = EEH_Array::is_set($wp_actions, 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__no_payment_made', 0);
     /** @type EE_Payment_Processor $payment_processor */
     $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
     $payment = $payment_processor->process_payment($pm, $transaction, NULL, NULL, 'success', 'CART', TRUE, TRUE);
     // offline payments are not saved... because no payment ever actually happened
     $this->assertEquals(0, $payment->ID());
     $this->assertEquals(EEM_Transaction::incomplete_status_code, $transaction->status_ID());
     $this->assertEquals($successful_payment_actions + 1, $wp_actions['AHEE__EE_Payment_Processor__update_txn_based_on_payment__no_payment_made']);
 }
 /**
  * Returns TRUE is this payment was set to approved during this request (or
  * is approved and was created during this request). False otherwise.
  *
  * @return boolean
  * @throws \EE_Error
  */
 public function just_approved()
 {
     $original_status = EEH_Array::is_set($this->_props_n_values_provided_in_constructor, 'STS_ID', $this->get_model()->field_settings_for('STS_ID')->get_default_value());
     $current_status = $this->status();
     if ($original_status !== EEM_Payment::status_id_approved && $current_status === EEM_Payment::status_id_approved) {
         return true;
     } else {
         return false;
     }
 }