| 
<?php
 /**
 * Transform qtags in html.
 * Will look for all qtag_TAG functions, in all modules, and apply them to the code
 * to convert tags.
 *
 * TODO: convert to OO approach.
 *
 * @param Environment $env
 *   The Environment.
 *
 * @param string $html
 *   The html to analyze.
 *
 * @param string $options
 *   Options for qtags.
 *
 * @return array
 *   All the qtags in the html.
 *
 */
 function checkCodeTags(&$env, $html, $options = array(), $regex_options = 'U') {
 $replacing = array();
 // Find all qtags using regular expressions (both { and [ bracket types are valid).
 $regexs = array();
 
 $qtag_delimiters = isset($options['qtag_delimiters']) ? $options['qtag_delimiters'] : array('[]', '{}');
 foreach ($qtag_delimiters as $qtag_delimiter) {
 $qtag_del_open = substr($qtag_delimiter, 0, 1);
 $qtag_del_close = substr($qtag_delimiter, 1, 1);
 
 $regexs['/\\' . $qtag_del_open . '(.*)\\' . $qtag_del_close . '/' . $regex_options] = array($qtag_del_open, $qtag_del_close, '|');
 }
 
 foreach ($regexs as $regex => $delimiters) {
 preg_match_all($regex, $html, $matches);
 foreach ($matches[1] as $tag_value) {
 $tag_full = $delimiters[0] . $tag_value . $delimiters[1];
 $replaces = checkCodeTags($env, $tag_value, $options);
 foreach ($replaces as $tag => $val) {
 if (is_array($val)) {
 $val = implode(GLOBAL_SEPARATOR, $val);
 }
 $tag_value = str_replace($tag, $val, $tag_value);
 }
 $tag = explode(':', $tag_value);
 
 // If there is more than one : we have to just consider the first chunk
 // and unify the rest.
 
 $tag_destination = isset($tag[1]) ? $tag[1] : NULL;
 for ($i = 2; $i < count($tag); $i++) {
 $tag_destination .= ':' . $tag[$i];
 }
 
 // Load the attributes of the qtag.
 $attributes = explode($delimiters[2], $tag[0]);
 $tag_name = $attributes[0];
 $attr_arr = array();
 unset($attributes[0]);
 // Assign attributes as specified in the tag.
 foreach ($attributes as $attr_item) {
 $split = explode('=', $attr_item);
 
 // If there is more than one = we have to just consider the first chunk
 // and unify the rest.
 
 $attribute_name = $split[0];
 $attribute_value = isset($split[1]) ? $split[1] : NULL;
 for ($i = 2; $i < count($split); $i++) {
 $attribute_value .= '=' . $split[$i];
 }
 
 if (isset($attribute_value)) {
 $attr_arr[$attribute_name] = $attribute_value;
 }
 else {
 $attr_arr[$attribute_name] = TRUE;
 }
 }
 
 // When the showtag attribute is used, don't render the tab but just display it.
 if (!empty($attr_arr['showtag'])) {
 $replacing[$tag_full] =  string_normalize(str_replace('|showtag', '', $tag_full));
 }
 // When the showtag attribute is used, don't render the tab but just display it.
 elseif (!empty($attr_arr['runlast']) && empty($options['runlast'])) {
 
 continue;
 }
 else {
 
 // Check if the requested qtag is defined by any function.
 if ($tag_name == strtoupper($tag_name) && function_exists('qtag_' . $tag_name)) {
 $func = 'qtag_' . $tag_name;
 if (function_exists($func)) {
 $qtag[$tag_full] = '';
 $attr_arr['tag_full'] = $tag_full;
 $qtag_access = TRUE;
 
 $vars = array(
 'attributes' => $attr_arr,
 'target' => $tag_destination,
 'qtag' => &$qtag[$tag_full],
 'access' => &$qtag_access,
 );
 
 $env->hook('qtag_preload', $vars);
 
 // Check that access is OK for the qtag.
 if (!$qtag_access) {
 $replacing[$tag_full] = '';
 }
 else {
 
 // Run the qtag.
 $tag_html = $func($env, !empty($tag_destination) ? $tag_destination : NULL, $attr_arr);
 
 $qtag[$tag_full] = $tag_html;
 
 // Let other modules hook into the rendered qtag.
 $env->hook('qtag', $vars);
 
 $tag_content = $qtag[$tag_full];
 
 // Add eventual suffix and prefix.
 if (!empty($attr_arr['suffix']) && !empty($tag_content)) {
 $tag_content .= $attr_arr['suffix'];
 }
 if (!empty($attr_arr['prefix']) && !empty($tag_content)) {
 $tag_content = $attr_arr['prefix'] . $tag_content;
 }
 
 // Prevent replacement where no_qtags attribute present. Used for input forms etc.
 if (isset($attr_arr['no_qtags'])) {
 $tag_content = string_normalize($tag_content);
 }
 
 $replacing[$tag_full] = $tag_content;
 }
 }
 }
 }
 }
 }
 
 return $replacing;
 }
 
 /**
 * @param $env
 * @param $html
 * @return mixed
 */
 function transformCodeTags(&$env, $html, $options = array()) {
 
 // After rendering all tags in a page, the result could be containing other tags.
 
 // For this reason, keep looping until all tags are rendered.
 while (TRUE) {
 
 $replaces = (checkCodeTags($env, $html, $options));
 
 if (empty($replaces)) {
 break;
 }
 foreach ($replaces as $k => $replace) {
 if (is_array($replace)) {
 $replace = implode(GLOBAL_SEPARATOR, $replace);
 }
 $html = str_replace($k, $replace, $html);
 }
 
 }
 return $html;
 }
 
 
 /**
 * Remove all qtags elements from the string (all [elements] within brackets).
 * @param $string
 * @return string
 */
 function stripQTags($string) {
 return preg_replace('/\[.*?\]/', '', $string);
 }
 
 |