0; $i--) { if (preg_match($closing, $scripts[$i - 1]) && preg_match($opening, $scripts[$i])) { $scripts[$i - 1] = preg_replace($closing, '', $scripts[$i - 1]); $scripts[$i] = preg_replace($opening, '', $scripts[$i]); } } return $scripts; } /** * This is a primitive comment stripper. It doesn't catch all comments * and falls short of minification, but it doesn't munge Angular injections * and is fast enough to run synchronously (without caching). * * At time of writing, running this against the Angular modules, this impl * of stripComments currently adds 10-20ms and cuts ~7%. * * Please be extremely cautious about extending this. If you want better * minification, you should probably remove this implementation, * import a proper JSMin implementation, and cache its output. * * @param string $script * @return string */ public static function stripComments($script) { return preg_replace(":^\\s*//[^\n]+$:m", "", $script); } /** * Decodes a js object (not necessarily strict json but valid js) into an array or primitive type * * ex. {a: 'Apple', 'b': "Banana", c: [1, 2, 3]} * * @param string $js * @return mixed */ public static function decode($js) { if (!class_exists('Services_JSON')) { require_once 'packages/OpenFlashChart/php-ofc-library/JSON.php'; } $codec = new Services_JSON(); $result = $codec->decode($js); // Converts stdClass to array return json_decode(json_encode($result), TRUE); } /** * Gets the properties of a javascript object WITHOUT decoding them. * * Useful when the object might contain js functions, expressions, etc. which cannot be decoded. * Returns an array with keys as property names and values as raw strings of js. * * Ex: {foo: getFoo(arg), bar: function() {return "bar"}} * Returns [ * 'foo' => 'getFoo(arg)', * 'bar' => 'function() {return "bar"}', * ] * * @param $js * @return array * @throws \Exception */ public static function getObjectProps($js) { $js = trim($js); if (!is_string($js) || !($js[0] === '{')) { throw new Exception("Invalid js object string passed to CRM_Utils_JS::getObjectProps"); } $chars = str_split(substr($js, 1)); $prev = NULL; $key = NULL; $quote = NULL; $item = ''; $length = strlen($js) - 2; $quotes = ['"', "'"]; $enclosures = [ '{' => 0, '(' => 0, '[' => 0, ]; $closers = [ '}' => '{', ')' => '(', ']' => '[', ]; $result = []; foreach ($chars as $index => $char) { // Open quotes - we'll ignore everything inside if (in_array($char, $quotes) && $prev != '\\' && !$quote) { $quote = $char; } // Close quotes elseif (in_array($char, $quotes) && $prev != '\\' && $char === $quote) { $quote = NULL; } if (!$quote) { // Skip opening whitespace between properties if ($char === ' ' && !strlen($item)) { $prev = $char; continue; } // Delineates property key if ($char == ':' && !array_filter($enclosures)) { $key = $item; $item = ''; $prev = $char; continue; } // Delineates property value if (($char == ',' || ($char == '}' && $index == $length)) && !array_filter($enclosures) && isset($key)) { $result[trim(trim($key), '"\'')] = $item; $item = ''; $prev = $char; continue; } // Open brackets - we'll ignore delineators inside if (isset($enclosures[$char])) { $enclosures[$char]++; } // Close brackets if (isset($closers[$char]) && $enclosures[$closers[$char]]) { $enclosures[$closers[$char]]--; } } $item .= $char; $prev = $char; } return $result; } }