<?php

/**
 * Check if the script is executed from the console or via web server.
 *
 * @return bool True if the script is executed from the console.
 */
function isCLI() {
	return in_array(php_sapi_name(), [ 'cli' ]);
}

/**
 * Check if the supplied variable can be interpreted as an empty value.
 * Extended so that include strings: '&nbsp;', 'false', 'off', 'no', 'n', '0' or '', case
 * insensitive.
 *
 * @param mixed $var The variable to check.
 *
 * @return bool True for empty variable, false otherwise.
 */
function isEmpty($var = null) {

	// Default empty
	if (empty($var)) {
		return true;
	}

	// Special
	if (is_string($var)) {
		if (in_array(trim(strtolower($var)), [ '&nbsp;', 'false', 'off', 'no', 'n', '0', '' ])) {
			return true;
		}
	}

	return false;
}

/**
 * Check if the supplied string is an email.
 *
 * @param string $email The email to test for validity.
 *
 * @return bool True if the argument is valid email address, false otherwise.
 */
function validEmail($email) {
	return (bool) preg_match(RFC_2822, $email);
}

/**
 * Same as reset, without errors :)
 *
 * @param array $array The array to extract the first element.
 *
 * @return mixed The first element of the array.
 */
function res($array) {
	return reset($array);
}

/**
 * Get the last item from a joined string.
 * Equivalent to end(explode()).
 *
 * @param string $delimiter The delimiter used to separate the string to elements.
 * @param string $string    The input string.
 *
 * @return string The last element in the string.
 */
function last($delimiter, $string = null) {

	$explode = explode($delimiter, $string);
	return end($explode);
}

/**
 * Get the last item from a string joined by dot ".".
 *
 * @param string $string The input string.
 *
 * @return string The last element in the string.
 */
function lastFromDot($string = null) {
	return last('.', $string);
}

/**
 * Recursively translate all items in array.
 *
 * @param array $array The array to translate.
 *
 * @return array The translated array.
 */
function __a($array) {
	foreach ($array as $i => $item) {
		$array[$i] = is_array($item)
			? __a($array)
			: __($item);
	}
	return $array;
}

# ~ Recursive glob - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
/**
 * @param string $path    The path of the base directory
 * @param string $pattern The pattern. No tilde expansion or parameter substitution is done.
 * @param int    $flags   [optional] <p>
 *                        Valid flags:
 *                        GLOB_MARK - Adds a slash to each directory returned
 *                        GLOB_NOSORT - Return files as they appear in the directory (no sorting).
 *                        When this flag is not used, the pathnames are sorted alphabetically
 *                        GLOB_NOCHECK - Return the search pattern if no files matching it were
 *                        found GLOB_NOESCAPE - Backslashes do not quote metacharacters GLOB_BRACE
 *                        - Expands {a,b,c} to match 'a', 'b', or 'c' GLOB_ONLYDIR - Return only
 *                        directory entries which match the pattern GLOB_ERR - Stop on read errors
 *                        (like unreadable directories), by default errors are ignored.
 *                        </p>
 *
 * @return array An array containing the matched files/directories, an empty array if no file
 *               matched or false on error.
 */
function rglob($path = '', $pattern = '*', $flags = 0) {
	$paths = glob($path . '*', GLOB_MARK | GLOB_ONLYDIR | GLOB_NOSORT | GLOB_BRACE);
	$files = glob($path . $pattern, $flags);
	foreach ((array) $paths as $path) {
		$files = array_merge($files, rglob($path, $pattern, $flags));
	}
	return $files;
}

/**
 * Sort a keys in array, by supplying another array with values representing the requested order.
 *
 * @param array $array The original array that should be sorted.
 * @param array $sort  The array containing the values in which the keyso for the original array
 *                     should be sorted.
 *
 * @return array The sorted array. Any keys not found in the $sort array will be appended to the
 *               end, in the original order.
 */
function manualSort($array, $sort) {
	$result = [];

	foreach ($sort as $key) {
		if (key_exists($key, $array)) {
			$result[$key] = $array[$key];
			unset($array[$key]);
		}
	}

	return $result + $array;
}

/**
 * Set default values for function arguments that are set to to null.
 *
 * @param mixed $var     The data to update with default value, if null.
 * @param mixed $default The default value to set.
 * @param null  $type    The type to force, accepts 'array' and 'int'.
 *
 * @return mixed The resulting value.
 */
function setDefault(&$var, $default = 0, $type = null) {
	if ($var === null) {
		$var = $default;
	}

	switch ($type) {
		case 'array':
			return $var = (array) $var;
		case 'int':
			return $var = (int) $var;
		default:
			return $var;
	}
}

# ~ Initializes the key of the array to some predefined value  - - - - - - - - #
/**
 * Initializes the key of the array to some predefined value, if not already set.
 *
 * @param array  $array The original array/
 * @param string $key   The key to check.
 * @param mixed  $value The default value to set.
 *
 * @return array The resulting array.
 */
function initKey(&$array, $key, $value = 0) {
	if (!isset($array[$key])) {
		$array[$key] = $value;
	}

	return $array;
}

/**
 * Exits the application and print the complete SQL dump.
 */
function kill() {
	Timer::end(true);
	require(VECTORCMS_ROOT . 'View/Elements/dev/sql_dump.ctp');
	exit;
}

/**
 * Appends the value to the string.
 *
 * @param string|string[] $object The object to append to.
 * @param string          $key    The key in $object on which to append the value.
 * @param string          $value  The value to append.
 *
 * @return null|string
 */
function append(&$object, $key, $value = null) {

	// To array
	if ($key !== null) {
		if (empty($object[$key])) {
			$object[$key] = $value;
		} else {
			$object[$key] .= ' ' . $value;
		}

		// To string
	} else {
		if (empty($object)) {
			$object = $value;
		} else {
			$object .= ' ' . $value;
		}
	}

	return $object;
}

/**
 * Convert HTML to plain text.
 *
 * @param string $html The original HTML.
 *
 * @return string The textual representation of the supplied HTML.
 */
function html2text($html) {
	$html = preg_replace('~\r~', '', $html);
	$html = preg_replace('~\s\s+~', ' ', $html);

	$html = preg_replace('~\<script.*\>.*\</script\>~ Usi', '', $html);
	$html = preg_replace('~</(p|h\d)>~', "$0\n\n", $html);
	$html = preg_replace('~\<br\s*/?\>?~i', "$0\n", $html);
	$html = preg_replace('~\<li\s*/?\>?~i', "$0\n - ", $html);

	$html = strip_tags($html);
	$html = preg_replace("~( +)?(\n)*\n *~", "$2\n", $html);

	return trim($html);
}

/**
 * Convert plain text to HTML.
 *
 * @param string $text The original plain text.
 *
 * @return string The HTML representation of the supplied text.
 */
function text2html($text) {
	App::uses('Sanitize', 'Utility');
	$text = Sanitize::html($text);
	$text = nl2br($text);

	return trim($text);
}

/**
 * Convert plain text to HTML
 *
 * @param string $hex The original color, in format RRGGBB (with or without leading #).
 *
 * @return array The array representing colors, with keys 'R', 'G' and 'B'.
 */
function hexToRGB($hex) {

	# Remove prefix
	$hex = trim($hex, '# ');

	# Return the array
	return [
		'R' => hexdec(substr($hex, 0, 2)),
		'G' => hexdec(substr($hex, 2, 2)),
		'B' => hexdec(substr($hex, 4, 2))
	];
}

/**
 * Create a CSS style rgba color definition.
 *
 * @param int[] $color The color to show, in format of [ 'R' => 0-255, 'G' => 0-255, 'B' => 0-255 ].
 * @param float $alpha The alpha channel to use, as a value from 0 to 1.
 *
 * @return string The resulting CSS rgba value.
 */
function cssRGBA($color, $alpha = 1.0) {
	return "rgba({$color['R']}, {$color['G']}, {$color['B']}, {$alpha});";
}

/**
 * Returns the list of all elements found in public folder.
 *
 * @param string $folder    The path to the folder to search into.
 * @param string $extension The extension of the files to find.
 * @param bool   $time      Set to true to include the modified time in the result.
 *
 * @return array The array containing the time of the latest modification and the list of files.
 */
function listPublicFiles($folder, $extension, $time = true) {

	// Get list of all files
	$found = glob(WWW_ROOT . "{$folder}/*.{$extension}");

	// Pack them into array
	$files = [];
	$maxTime = 0;
	if ($found) {
		foreach ((array) $found as $file) {

			// Throw exception if filename is not property formatted
			if (!preg_match("~/(\d+)-([\.a-z0-9_-]+[a-z0-9])\.{$extension}$~ i", $file, $match)) {
				throw new CakeException(__("Filename `{$file}` not propery formed"));
			}

			// Set filename
			$fileModifiedTime = filemtime($file);
			$time = $time ? '?' . $fileModifiedTime : '';
			$maxTime = $maxTime > $fileModifiedTime ? $maxTime : $fileModifiedTime;
			$files[$match[1]] = "{$folder}/{$match[1]}-{$match[2]}.{$extension}{$time}";
		}
	}

	return [
		'max_mtime' => $maxTime,
		'files'     => $files
	];
}

/**
 * Simplest possible curl wrapper.
 *
 * @param string $url     THe target URL.
 * @param array  $post    The optional post to send.
 * @param array  $options The list of additional options for the curl.
 *
 * @return mixed The result from the curl.
 */
function curl($url, $post = [], $options = []) {
	$ch = curl_init();
	curl_setopt($ch, CURLOPT_URL, $url);
	curl_setopt($ch, CURLOPT_COOKIEJAR, ROOT . 'tmp/cookie.txt');
	curl_setopt($ch, CURLOPT_COOKIEFILE, ROOT . 'tmp/cookie.txt');
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

	// Post
	if ($post) {
		curl_setopt($ch, CURLOPT_POST, 1);
		curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
	}

	// Set additional options
	foreach ($options as $option => $value) {
		curl_setopt($ch, $option, $value);
	}

	// Execute and close
	$result = curl_exec($ch);
	curl_close($ch);
	return $result;
}

/**
 * Remove numerical keys from an array.
 *
 * @param array $array The array to simplify.
 *
 * @return array The array without the numerical keys.
 */
function removeIntKeys($array) {
	foreach ($array as $i => $item) {
		if (is_numeric($i)) {
			unset($array[$i]);
		}
	}

	return $array;
}

/**
 * Format the number so it has exactly decimal places.
 *
 * @param float  $num       The number to format.
 * @param int    $places    The number of decimal places to show.
 * @param string $separator The separator to use for decimal space.
 *
 * @return string Numerical value with exactly requested decimal places.
 */
function dec($num, $places = 2, $separator = '.') {
	return str_replace([ ',', '.' ], [ $separator, $separator ], sprintf('%.' . $places . 'f', 1.0 * str_replace(',', '.', $num)));
}

/**
 * Get the locale from the column name.
 *
 * @param string $column The column name that might end in __{{locale}}.
 *
 * @return string|null The found locale or null if no locale in the column name.
 */
function getLocale($column) {
	if (preg_match("~__([a-z]{2,3})$~", $column, $match)) {
		return $match[1];
	}

	return null;
}

/**
 * Remove the locale from the end of the column name.
 *
 * @param string $column The column name that might end in __{{locale}}.
 *
 * @return string The column name without the locale..
 */
function removeLocale($column) {
	return preg_replace("~__([a-z]{2,3})$~", '', $column);
}

# ~ Get the source from the input  - - - - - - - - - - - - - - - - - - - - - - #
function parseSource($input, $translate = true) {

	# Grab the variables
	if (preg_match('~[a-z0-9]+(?:\.[a-z0-9_]+)+~ i', $input['content'], $var)) {
		$path = explode('.', $var[0]);
		$source = array_shift($path);

		$source = Inflector::variable($source);
		foreach ($path as $next) {
			$source .= "['{$next}']";
		}

		return $translate ? "__('" . str_replace($var, "' . \${$source} . '", $input['content']) . "')" : "\${$source}";

		# No variables
	} else {
		$source = $input['content'];
	}

	return $translate ? "__('{$source}')" : $source;
}

/**
 * Merges arrays of integers into a comma separated string.
 *
 * @return string The merged sets of integers.
 */
function mergeSets() {
	$ret = [];
	$sets = func_get_args();
	foreach ($sets as $set) {
		$set = preg_replace('~[^,0-9]~', '', $set);
		$ret = array_merge($ret, explode(',', $set));
	}

	return preg_replace('~[^,0-9]~', '', implode(',', array_filter(array_unique($ret))));
}

/**
 * Returns a value from multidimensional array by supplied path.
 *
 * @param array $array The array to traverse.
 * @param array $path  The path into the array.
 *
 * @return mixed The resulting value.
 */
function fromPath($array, $path = []) {
	if (is_string($path)) {
		$path = explode('.', $path);
	}

	# Iterate over path
	$key = array_shift($path);
	if ($key !== null && $key !== '' && is_array($array)) {
		return isset($array[$key])
			? fromPath($array[$key], $path)
			: null;
	}

	return $array;
}

/**
 * Returns flat array from tagged tree structure.
 *
 * @param        $tree
 * @param string $marker
 * @param null   $field
 * @param array  $path
 *
 * @return array The flattened path.
 */
function activePath($tree, $marker = 'selected', $field = null, $path = []) {
	setDefault($field, $marker);

	foreach ($tree as $node) {
		if (fromPath($node, $marker)) {
			$path[] = fromPath($node, $field);
			$path = activePath($node['children'], $marker, $field, $path);
			break;
		}
	}

	return $path;
}

/**
 * Dummy function for parsing template variables.
 *
 * @return null Always null.
 */
function getUserVariable($name, $type) {
	return null;
}

/**
 * Generate a random string.
 *
 * @param int    $length Length of the generated string.
 * @param string $chars  The string containing all of the available characters.
 *
 * @return string The generated string.
 */
function getRandomString($length = 10, $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') {
	$str = '';

	$size = strlen($chars);
	for ($i = 0; $i < $length; $i++) {
		$str .= $chars[mt_rand(0, $size - 1)];
	}

	return $str;
}

/**
 * Remove the files and directories from the path.
 *
 * @param string $path      The path to the directory to clean up.
 * @param bool   $removeAll True to delete the targeter path as well, false to just leave it
 *                          empty..
 */
function cleanDir($path, $removeAll = false) {
	if (is_dir($path)) {
		$objects = scandir($path);
		foreach ($objects as $object) {
			if ($object != "." && $object != '..') {
				if (filetype($path . '/' . $object) == 'dir') {
					cleanDir($path . '/' . $object);
				} else if ($object != '.empty') {
					unlink($path . '/' . $object);
				}
			}
		}

		// Remove the directory as well.
		if ($removeAll) {
			rmdir($path);
		}
	}
}

/**
 * Multi-byte safe HTML encode.
 *
 * @param string $html The string being converted.
 *
 * @return string The encoded data.
 */
function html($html) {
	return trim(htmlspecialchars($html, ENT_QUOTES, 'UTF-8', true));
}

/**
 * Calculate the distance between two GPS locations.
 *
 * @param string $location1 First location, in GPS_LOCATION valid format.
 * @param string $location2 Second location, in GPS_LOCATION valid format.
 *
 * @return int The distance in meters between two locations or null on error.
 */
function gpsDistance($location1, $location2) {
	if (!preg_match(GPS_LOCATION, $location1) || !preg_match(GPS_LOCATION, $location2))
		return null;

	list($lat1, $lon1) = explode(',', str_replace(' ', '', $location1));
	list($lat2, $lon2) = explode(',', str_replace(' ', '', $location2));
	$lat1 *= M_PI / 180;
	$lon1 *= M_PI / 180;
	$lat2 *= M_PI / 180;
	$lon2 *= M_PI / 180;

	return round(acos(sin($lat1) * sin($lat2) + cos($lat1) * cos($lat2) * cos($lon2 - $lon1)) * 6371000);
}

/**
 * Format bytes, using KB, MB, GB, TB, PB and EB.
 *
 * @param int    $size      The size in bytes.
 * @param int    $precision The number of decimal places to show.
 * @param string $separator The separator to use for decimal space.
 *
 * @return string
 */
function formatBytes($size, $precision = 2, $separator = ' . ') {
	if ($size !== null) {

		// Get the suffix
		$base = log($size) / log(1024);
		$index = min(6, floor($base));
		$suffixes = [ '', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB' ];

		// Show the value
		return dec(pow(1024, $base - $index), $precision, $separator) . $suffixes[$index . ''];
	}

	return '0';
}

/**
 * Get HTML code for the font awesome icon.
 *
 * @param string $icon    The name of the icon, without the fa- prefix.
 * @param mixed  $options Send the key-value pair for additional HTML attributes, true for setting
 *                        the fa-fw class.
 *                        All values numeric indices will be treated as additional classes.
 *
 * @return string The HTML i tag with font awesome icon.
 */
function icon($icon, $options = true) {
	$attributes = [];

	// Default options
	if ($options === true) {
		$icon = 'fw fa-' . $icon;
		$options = [];
	}

	// Get the class
	$attributes['class'] = [ 'fa', 'fa-' . $icon ];
	foreach ((array) $options as $key => $value)
		if (!empty($value)) {

			# Additional class
			if (is_numeric($key)) {
				$attributes['class'][] = $value;
				continue;
			}

			# Additional options
			switch ($key) {

				default:
					$attributes[$key] = $value;
			}
		}
	$attributes['class'] = implode(' ', $attributes['class']);

	// Get other HTML attributes
	$attr = [];
	foreach ($attributes as $key => $value) {
		$attr[] = $key . ' = "' . htmlentities($value) . '"';
	}

	return '<i' . implode(' ', $attr) . '></i>';
}

/**
 * Get statistics for youtube video, using YT API v3
 *
 * @param string $ytId     Id of youtube video.
 * @param string $ytApiKey The API key for youtube API v3.
 * @param string $scApiKey The optional API key for SharedCount API.
 *
 * @return array|null Statistics info about video, or null if not found.
 */
function getYoutubeVideoInfo($ytId, $ytApiKey, $scApiKey = null) {

	// Try cache
	$cached = Cache::read($ytId, 'yt_cache');
	if (!empty($cached)) {
		return $cached;
	}

	//	// Not for production !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	//	$stats = array(
	//		'name' => 'asdfasdf',
	//		'description' => 'asdfsadfasd',
	//		'views' => 654,
	//		'likes' => 321,
	//		'duration' => PT4M21S,
	//		'yt_published' => '1989 - 11 - 01',
	//		'shares' => 21
	//	);
	//
	//	Cache::write($ytId, $stats, 'yt_cache');
	//	return $stats;
	//	// Not for production !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

	// Get response from youtube API
	$result = curl("https://www.googleapis.com/youtube/v3/videos?part=snippet%2Cstatistics%2Cstatus%2CcontentDetails&id=" . $ytId . "&maxResults=1&key=" . $ytApiKey);
	$result = json_decode($result, true);

	// If there are no videos found, invalidate field
	if (empty($result['items'])) {
		return null;
	}

	// Pack response
	$videoData = $result['items'][0];
	$response = [
		'name'         => $videoData['snippet']['title'],
		'description'  => $videoData['snippet']['description'],
		'views'        => $videoData['statistics']['viewCount'],
		'likes'        => $videoData['statistics']['likeCount'],
		'duration'     => $videoData['contentDetails']['duration'],
		'yt_published' => date('Y - m - d', strtotime($videoData['snippet']['publishedAt']))
	];

	// If there is SC api key, get share count for url
	if ($scApiKey) {

		// Get share count
		$sharedCount = curl("http://free.sharedcount.com/?url=" . rawurlencode('http://youtu.be/' . $ytId) . "&apikey=" . $scApiKey);
		$sharedCount = json_decode($sharedCount, true);

		// If there is error, return false
		if (isset($sharedCount['Error'])) {
			return null;
		}

		// Sum all social networks
		$totalCount = 0;
		foreach ($sharedCount as $type => $value) {
			if (is_array($value)) {
				if (!empty($value['total_count'])) {
					$totalCount += $value['total_count'];
				}
			} else {
				$totalCount += $value;
			}
		}

		// Pack in response
		$response['shares'] = $totalCount;
	}

	// Return response
	Cache::write($ytId, $response, 'yt_cache');
	return $response;
}

/**
 * Compress JS content
 *
 * @param string $buffer The original JS.
 *
 * @return string The compressed JS.
 */
function compressJs($buffer) {
	require_once(VECTORCMS_ROOT . 'Vendor/JShrink/Minifier.php');
	return \JShrink\Minifier::minify($buffer, [ 'flaggedComments' => false ]);
}

/**
 * Compress CSS content
 *
 * @param string $buffer The original CSS.
 *
 * @return string The compressed CSS.
 */
function compressCss($buffer) {

	// Remove comments
	$buffer = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $buffer);

	// Clear everything else
	require_once(VECTORCMS_ROOT . 'Vendor/CSSMin/cssmin.php');
	$compressor = new CSSmin();
	return $compressor->run($buffer);
}

/**
 * Get the refresh token for the Google API.
 *
 * @return string The refresh token.
 */
function getRefreshToken() {

	// Create array of data to be posted
	$post = [
		'code'          => '4/v9YPIk5Bop6D3mHcO0vDxssSLu5pbrMzraxqbTfiXDA.UrQ5EE47k14foiIBeO6P2m-4VA1nkgI',
		'client_id'     => GA_CLIENT_ID,
		'client_secret' => GA_CLIENT_SECRET,
		'redirect_uri'  => '/',
		'grant_type'    => 'authorization_code'
	];

	return curl('https://accounts.google.com/o/oauth2/token', $post);
}

/**
 * Get the access token for the Google analytics.
 *
 * @return string The response from the Google.
 */
function getAccessToken() {

	// Create array of data to be posted
	$post = [
		'client_id'     => GA_CLIENT_ID,
		'client_secret' => GA_CLIENT_SECRET,
		'refresh_token' => Configure::read('Website.google_api_refresh_token'),
		'grant_type'    => 'refresh_token'
	];

	return curl('https://accounts.google.com/o/oauth2/token', $post);
}

/**
 * Clear named and query params from url
 *
 * @param CakeRequest $request The original request.
 *
 * @return string The cleaned URL.
 */
function cleanUrl(CakeRequest $request) {

	// Remove named params
	$url = $request->here;
	foreach ($request->params['named'] as $paramName => $paramValue) {
		$url = str_replace('/' . $paramName . ':' . $paramValue, '', $url);
	}

	// Remove query params
	$url = strtok($url, '?');

	return $url;
}

/**
 * Get date and time in format suitable for storing in the datetime columns in database.
 *
 * @param mixed $timestamp The timestamp to use, string to covert to time or null fo this moment.
 *
 * @return string The formatted time using date('Y-m-d H:i:s');
 */
function datetime($timestamp = null) {

	// Handle the string values
	if (is_string($timestamp)) {
		$timestamp = strtotime($timestamp);
	}

	return date('Y-m-d H:i:s', $timestamp);
}

/**
 * Convert a string to a human-friendly version.
 *
 * @param string    $string The raw input string.
 * @param bool|null $case   True to apply ucfirst, false to use lowercase or null to leave as it is.
 *
 * @return string The humanized string.
 */
function humanize($string, $case = false) {
	$string = preg_replace('~(.)[\s_-]?([A-Z])~', '$1 $2', $string);
	switch ($case) {
		case true:
			return ucfirst(strtolower($string));
		case false:
			return strtolower($string);
		default:
			return $string;
	}
}

/**
 * Convenience method for dying and debugging at the same time.
 *
 * @param string $data Optional data to be printed out.
 */
function diebug($data = 'some_value_that_will_never_be_passed_213,masd921masd') {

	// Get the calling line
	$debug = debug_backtrace();
	$message = "{$debug[0]['file']}: {$debug[0]['line']}";

	// Remove document root, if possible
	if (defined('ROOT')) {
		$message = substr($message, strlen(ROOT) + 1);
	}

	// Get memory info
	$memory = memory_get_peak_usage();
	if (function_exists('formatBytes')) {
		$memory = formatBytes($memory);
	}

	// Echo
	echo "Dead on {$message} ({$memory} memory peak)";
	if ($data !== 'some_value_that_will_never_be_passed_213,masd921masd') {
		echo "\n";
		print_r($data);
	}
	die(-1);
}
