steveosoule
5/2/2016 - 9:45 PM

Miva Data To PHP Array

Miva Data To PHP Array

#--------------------------------------------------------#
# Miva Data To PHP Array
#--------------------------------------------------------#
# @author: Patrick Stearns <pstearns@miva.com> - 2015
#--------------------------------------------------------#
# Converts a serialized Miva structure into a PHP multi-
# dimensional associative array
#
# @param string, $mv_serialized_str:
#   - Miva data converted to serialized string
#     Example input str: ':email=pstearns%2B1@miva.com,:gross_amount=1085.43,
#                         :net_amount=989.00,:order_date=09%2F23%2F2015,
#                         :order_id=1018,:order_time=14%3A11%3A36+PST'
#
# @return array, $result:
#   - Converted multi-dimenional associative array
#--------------------------------------------------------#
function mvDataToArray($mv_serialized_str)
{
	$result = [];

	// Split the comma separated list into an array
	$csl_arr = explode(',', $mv_serialized_str);

	// Loop through the items that were formerly comma separated
	foreach ($csl_arr as $item) {
		// These values are for checking if the array key is Miva array key. Reset these to null
		// for each loop iteration.
		$mv_array_key   = null;
		$mv_array_index = null;

		// The first ':' is always deadweight, we can go ahead and trim it off
		$item = ltrim($item, ':');

		// Split each item by the ':' delimiter and store it into a new array
		$col_sep_arr = explode(':', $item);

		// If there is only one item left in the colon separated array, we can go ahead and
		// map it to the final result
		if (count($col_sep_arr) === 1) {
			// Split the item by the '=' delimiter ([0] = key, [1] = value)
			$target_arr = explode('=', $col_sep_arr[0]);

			// Check if the key is a Miva array
			preg_match('/(\w+)?\[(\d+)\]/', $target_arr[0], $match);

			// The key is a Miva array
			if ($match) {
				// Store the Miva array key name
				$mv_array_key = $match[1];

				// Store the Miva array index value and ensure the value is an int
				$mv_array_index = (int)$match[2];

				// The key has a name and index (Ex: example[1]).
				if ($mv_array_key && $mv_array_index) {
					// Decode url-encoding and set the value of the array element
					$result[$mv_array_key][$mv_array_index] = urldecode($target_arr[1]);

					continue;
				}
				// The key has an index only (Ex: [1]).
				else if (!$mv_array_key && $mv_array_index) {
					// Decode url-encoding and set the value of the array element
					$result[$mv_array_index] = urldecode($target_arr[1]);

					continue;
				}
			}

			// Decode url-encoding and set the value of the array element
			$result[$target_arr[0]] = urldecode($target_arr[1]);
		}
		// Else there are multiple items left in the colon separated array
		// ...and so it begins...
		else {
			// Our target is the last item in the colon separated array, let's pop it off
			// of the array
			$target_item = array_pop($col_sep_arr);

			// Time to break up the party. Split the target item by the '=' delimiter.
			$target_arr = explode('=', $target_item);

			// Decode the value's url-encoding
			$target_val = urldecode($target_arr[1]);

			// Push the target item's key back onto the colon separated array
			array_push($col_sep_arr, $target_arr[0]);

			// Now for the fun part...
			// Create a reference of the results array to keep track of its current dimension
			$result_ref = &$result;

			// Loop through the colon separated array, which should now only contain the keys
			// to map to the proper dimension of the results array
			while ($key = array_shift($col_sep_arr)) {
				// Check if the key is a Miva array
				preg_match('/(\w+)?\[(\d+)\]/', $key, $match);

				// The key is a Miva array
				if ($match) {
					// Store the Miva array key name
					$mv_array_key = $match[1];

					// Store the Miva array index value and ensure the value is an int
					$mv_array_index = (int)$match[2];

					// The key has a name and index (Ex: example[1])
					if ($mv_array_key && $mv_array_index) {
						// Rename the key to the Miva array key minus the index
						$key = $mv_array_key;

						// If the key doesn't already exist in the results array, add it as a layer
						// by setting the key to an empty array and the array index that follows it
						if (!isset($result_ref[$key])) {
							$result_ref[$key] = [];
							$result_ref[$key][$mv_array_index] = [];
						}

						// Move the reference index deeper and continue to the next key
						$result_ref = &$result_ref[$key][$mv_array_index];

						continue;
					}
					// The key has an index only (Ex: [1]). Store this value to keep track of
					// which index we are at in the array
					else if (!$mv_array_key && $mv_array_index) {
						// Move the reference to point to the index and continue to the next key
						$result_ref = &$result_ref[$mv_array_index];

						continue;
					}
				}

				// If the key doesn't already exist in the results array, add it as a layer
				// by setting the key to an empty array
				if (!isset($result_ref[$key])) {
					$result_ref[$key] = [];
				}

				// Move the reference deeper...
				$result_ref = &$result_ref[$key];
			}

			// Now that we have our dimensions set, assign value of this dimension to the
			// target value that we stored earlier
			$result_ref = $target_val;
		}
	}

	// ...and voila, return the results
	return $result;
}