public static function createFile(&$body, $src_files, $excluded_files, $replace_tags, $conds, $comments, $indexes) { $arr = plgSystemJBetolo::param('files'); $abs_excl_minify = plgSystemJBetolo::param('minify_exclude'); if ($abs_excl_minify) { $abs_excl_minify = explode(',', $abs_excl_minify); } $abs_excl_gzip = plgSystemJBetolo::param('gzip_exclude'); if ($abs_excl_gzip) { $abs_excl_gzip = explode(',', $abs_excl_gzip); } $excl_js_imports = $excl_css_imports = ''; $css_imports = $js_imports = array(); $js_placement = plgSystemJBetolo::param('js_placement'); $age = plgSystemJBetolo::param('cache_age'); $app = JFactory::getApplication()->getName(); $tmpl = JFactory::getApplication()->getTemplate(); $paramHasChanged = false; $external_custom_orders = array(); /** * app[administrator|site],type[css|js],attr[css=media,js=''] */ foreach ($src_files as $type => $_src_files) { if (empty($_src_files)) { continue; } $skipFiles = array_merge($conds[$type], $comments[$type]); $merge = plgSystemJBetolo::param($type . '_merge'); $is_gz = JBETOLO_IS_GZ && plgSystemJBetolo::param($type . '_gzip') && jbetoloHelper::clientEncoding(); $is_minify = JBETOLO_IS_MINIFY && plgSystemJBetolo::param($type . '_minify'); $excl_files = $excluded_files[$type]; if ($merge) { $mergeMode = plgSystemJBetolo::param($type . '_merge_mode', 'mono'); $are_files_changed = $new_files_found = false; if (count($arr) == 0 || !isset($arr[$app]) || !isset($arr[$app][$tmpl]) || !isset($arr[$app][$tmpl][$type]) || !is_array($arr[$app][$tmpl][$type])) { $arr[$app][$tmpl][$type] = array(); } if ($mergeMode == 'mono') { if (count($arr[$app][$tmpl][$type])) { foreach ($arr[$app][$tmpl][$type] as $attr => $rec) { $merged = array(); $merged_file = JBETOLO_CACHE_DIR . $rec['merged']; $found_files = array(); $delete_merged_file = false; foreach ($_src_files as $s => $src_file) { if ($type == 'js' || isset($indexes['css'][$s]['attr']) && $attr == $indexes['css'][$s]['attr']) { if (!in_array($src_file, $rec['srcs'])) { $found_files[] = $src_file; $delete_merged_file = true; } } } if (!empty($found_files)) { $merged = array_merge($merged, $found_files); } $merged_file_exists = JFile::exists($merged_file); if (empty($found_files) && $merged_file_exists) { $are_files_changed = self::areFilesChanged($rec['parts']); if ($are_files_changed) { $delete_merged_file = true; } } if ($delete_merged_file && $merged_file_exists) { JFile::delete($merged_file); } $merged_file_exists = JFile::exists($merged_file); if (!$merged_file_exists) { $merged = array_merge($merged, $rec['srcs']); } if (!empty($merged)) { $merged = array_unique($merged); $merged = jbetoloFileHelper::customOrder($merged, $type); if ($type == 'js') { jbetoloJS::setJqueryFile($merged, jbetoloHelper::getArrayValues($excl_files, 'src')); $res = jbetoloJS::build($merged); } else { $res = jbetoloCSS::build($merged, array_fill(0, count($merged), $attr)); } $arr[$app][$tmpl][$type][$attr] = $res[$attr]; $paramHasChanged = true; } } } else { $_src_files = array_unique($_src_files); if ($type == 'js') { jbetoloJS::setJqueryFile($_src_files, jbetoloHelper::getArrayValues($excl_files, 'src')); } $arr[$app][$tmpl][$type] = $type == 'css' ? jbetoloCSS::build($_src_files, '', true, $indexes['css']) : jbetoloJS::build($_src_files); $paramHasChanged = true; } $imports = $arr[$app][$tmpl][$type]; } else { if ($mergeMode == 'url') { $files_key = jbetoloHelper::currentURL(); } else { if ($mergeMode == 'resource') { $_src_files = array_unique($_src_files); $files_key = $_src_files; sort($files_key); $files_key = implode('', $files_key); } } if (isset($arr[$app][$tmpl][$type][$files_key])) { $rec = $arr[$app][$tmpl][$type][$files_key]; $add_key = key($rec); $rec = $rec[$add_key]; if (self::areFilesChanged($rec['parts'])) { if (JFile::exists(JBETOLO_CACHE_DIR . $rec['merged'])) { JFile::delete(JBETOLO_CACHE_DIR . $rec['merged']); } $paramHasChanged = true; } } else { $paramHasChanged = true; } if ($paramHasChanged) { $arr[$app][$tmpl][$type][$files_key] = $type == 'css' ? jbetoloCSS::build($_src_files, '', true, $indexes['css']) : jbetoloJS::build($_src_files); } $imports = $arr[$app][$tmpl][$type][$files_key]; } $external_custom_orders[$type] = jbetoloHelper::replaceTags($body, $replace_tags[$type], "", $indexes[$type], plgSystemJBetolo::param($type . '_external_custom_order_before'), plgSystemJBetolo::param($type . '_external_custom_order_after')); /** * @@todo: if cdn enabled just provide the file and no dynamic url */ foreach ($imports as $attr => $rec) { $url = jbetoloFileHelper::getServingURL($rec['merged'], $type, $is_gz, $age); if ($type == 'js') { $js_imports[] = "\n" . '<script type="text/javascript" src="' . $url . '"></script>'; } else { $attrs = jbetoloHelper::returnAttributes($attr); $css_imports[] = "\n" . '<link rel="stylesheet" type="text/css" href="' . $url . '" ' . $attrs . ' />'; } } } $gzip_excluded = plgSystemJBetolo::param($type . '_gzip_excluded'); $minify_excluded = plgSystemJBetolo::param($type . '_minify_excluded'); if (($is_gz && $gzip_excluded || $is_minify && $minify_excluded) && count($excl_files)) { $jqueryNoConflict = plgSystemJBetolo::param('js_jquery_no_conflict'); foreach ($excl_files as $excl_file) { $src = $excl_file['src']; if (jbetoloFileHelper::fileInArray($src, $skipFiles)) { continue; } $_minify = $is_minify && !jbetoloFileHelper::isFileExcluded($src, $abs_excl_minify); $_gz = $is_gz && !jbetoloFileHelper::isFileExcluded($src, $abs_excl_gzip); if (($_minify || $_gz) && !$excl_file['dynamic']) { $src = str_replace(JBETOLO_URI_BASE, '', $src); $attr = $type == 'css' ? jbetoloHelper::extractAttributes($excl_file['tag']) : 'main'; $file = $type == 'css' ? jbetoloCSS::build($src, array($attr)) : jbetoloJS::build($src); $file = $file[$attr]['merged']; $src = jbetoloFileHelper::getServingURL($file, $type, $is_gz, $age); if ($type == 'js') { $excl_js_imports .= "\n" . '<script type="text/javascript" src="' . $src . '"></script>'; } else { if ($type == 'css') { $attrs = jbetoloHelper::returnAttributes($attr); $excl_css_imports .= "\n" . '<link rel="stylesheet" type="text/css" href="' . $src . '" ' . $attrs . ' />'; } } $body = str_ireplace($excl_file['tag'], '', $body); } } } } jbetoloFileHelper::placeTags($body, $excl_css_imports, 'css'); jbetoloFileHelper::placeTags($body, $js_imports, 'js', $js_placement, isset($external_custom_orders['js']) ? $external_custom_orders['js']['before'] : array(), isset($external_custom_orders['js']['after']) ? $external_custom_orders['js']['after'] : array(), true); jbetoloFileHelper::placeTags($body, $excl_js_imports, 'js', $js_placement, null, null, true); jbetoloFileHelper::placeTags($body, $css_imports, 'css'); if ($paramHasChanged) { plgSystemJBetolo::param('files', $arr, 'set'); } }
private function parseBody($body, $type) { $merge = self::param($type . '_merge'); $gzip = JBETOLO_IS_GZ && self::param($type . '_gzip'); $gzip_excluded = $gzip && self::param($type . '_gzip_excluded'); $minify = JBETOLO_IS_MINIFY && self::param($type . '_minify'); $minify_excluded = $minify && self::param($type . '_minify_excluded'); if (!$merge && !$gzip_excluded && !$minify_excluded) { return; } $head_only = (bool) self::param($type . '_scan_headonly', true); if ($head_only) { list($body, ) = explode('</head>', $body); list(, $body) = explode('<head>', $body); } // absolutely included resources are appended to body $included = plgSystemJBetolo::param($type . '_include', ''); $included = trim($included); if ($included) { $included = @explode(',', $included); foreach ($included as $i => $include) { $include = jbetoloFileHelper::normalizeCall($include); if ($type == 'js') { $included[$i] = "<script type=\"text/javascript\" src=\"" . $include . "\"></script>\n"; } else { if ($type == 'css') { $included[$i] = "<link rel=\"stylesheet\" href=\"" . $include . "\" type=\"text/css\" media=\"screen\" />\n"; } } } $included = implode('', $included); $body = str_ireplace('</title>', '</title>' . $included, $body); } $excluded = $comments = $conds = $excludedSrcs = array(); // find and consider IE conditionals as excluded from merging preg_match_all(self::$conditionalTagScript[$type], $body, $condTags); $condTags = $condTags[0]; self::$conditionalTags = implode('', $condTags); preg_match_all(self::$conditionalSrcScript[$type], self::$conditionalTags, $matches); foreach ($matches[0] as $c => $conditional) { $conds[] = jbetoloFileHelper::normalizeCall($matches[1][$c]); $excludedSrcs[] = $conds[$c]; } // find and exclude commented resources from merging preg_match_all(self::$commentedTagScript[$type], $body, $matches); if (!empty($matches[0]) && !empty($condTags)) { foreach ($matches[0] as $m => $match) { if (in_array($match, $condTags)) { unset($matches[0][$m]); } } } $matches = implode('', $matches[0]); preg_match_all(self::$conditionalSrcScript[$type], $matches, $matches); foreach ($matches[0] as $c => $conditional) { $comments[] = jbetoloFileHelper::normalizeCall($matches[1][$c]); $excludedSrcs[] = $comments[$c]; } // collect resources to be excluded from merging if ($merge) { $excluded = self::param($type . '_merge_exclude'); if (isset($excluded) && $excluded) { $excluded = @explode(',', $excluded); } else { $excluded = array(); } $excluded = array_merge($excluded, self::$predefinedExclude[$type], $excludedSrcs); // Gzip operates at file level, therefore if a file is indicated to be non-gzipped // and gzipping of merged file is enabled then we need to exclude it // (the analogus doesn't apply for minify as merged file can contain a mix of // minified and non-minified code) $abs_excl = self::param('gzip_exclude'); if ($abs_excl && $gzip) { $abs_excl = explode(',', $abs_excl); $excluded = array_merge($excluded, $abs_excl); } } // find all resources preg_match_all(self::$tagRegex[$type], $body, $matches); $tags = $matches[0]; preg_match_all(self::$srcRegex[$type], implode('', $tags), $matches); if (count($matches[0]) != count($tags)) { // Due to incorrect syntax some tags has not found corresponding source entry and will be discarded $n = count($matches[1]); $d = 0; foreach ($tags as $s => $src) { $si = $s - $d; if ($si < $n) { if (strpos($tags[$s], $matches[1][$si]) === false) { unset($tags[$s]); $d++; } } else { unset($tags[$s]); } } $tags = array_filter($tags); $tags = array_values($tags); } $excludedSrcs = $_excludedSrcs = $srcs = $indexes = $srcsIndexes = array(); // prepare required input for the merging by processing each found resource // 1. separate the excluded ones by considering the choosen merging method // 2. if css identify and assign correct media type // 3. if resource is not locally available no further processing $deleteSrcs = self::param('delete'); if ($deleteSrcs) { $deleteSrcs = explode(',', $deleteSrcs); } foreach ($matches[1] as $s => $src) { $indexes[] = array('src' => $src, 'tag' => $tags[$s], 'srci' => ''); $src = jbetoloFileHelper::normalizeCall($src, false, false, true, $type); if ($src) { $asDynamic = jbetoloFileHelper::isSkippedAsDynamic($src); if ($merge) { $shouldIgnore = jbetoloFileHelper::isFileExcluded($src, $excluded); } else { $shouldIgnore = true; } if ($type == 'css') { $attr = jbetoloHelper::extractAttributes($tags[$s]); $indexes[$s]['attr'] = $attr; } if (!$shouldIgnore && !$asDynamic) { $srcs[] = $src; $indexes[$s]['srci'] = count($srcs) - 1; $srcsIndexes[$src] = $indexes[$s]; } else { $isDeleted = false; // is deleted if ($deleteSrcs) { foreach ($deleteSrcs as $d) { if ($d == $matches[1][$s]) { $isDeleted = true; break; } } } if (!$isDeleted) { $excludedSrcs[$src] = array('src' => $src, 'tag' => $tags[$s], 'dynamic' => $asDynamic); $_excludedSrcs[] = $src; $tags[$s] = JBETOLO_EMPTYTAG; } } } else { // external url or resource not found physically on the server $isDeleted = false; // is deleted if ($deleteSrcs) { foreach ($deleteSrcs as $d) { if ($d == $matches[1][$s]) { $isDeleted = true; break; } } } // is left untouched if (!$isDeleted) { $tags[$s] = JBETOLO_EMPTYTAG; } } } // resources to be deleted are removed from found ones if ($deleteSrcs) { foreach ($deleteSrcs as $d) { $_d = jbetoloFileHelper::normalizeCall($d); if ($_d !== false) { $d = $_d; } $f = jbetoloFileHelper::fileInArray($d, $srcs); if ($f) { unset($srcsIndexes[$srcs[$f[0]]]); unset($srcs[$f[0]]); } } } if ($type == 'js') { if (self::param('js_jquery_migrate_plugin', 0)) { $srcs[] = JBETOLO_PATH . 'jbetolo/assets/jquery/' . JBETOLO_JQUERY_MIGRATE_PLUGIN; $srcsIndexes[JBETOLO_PATH . 'jbetolo/assets/jquery/' . JBETOLO_JQUERY_MIGRATE_PLUGIN] = array('src' => JBETOLO_PATH . 'jbetolo/assets/jquery/' . JBETOLO_JQUERY_MIGRATE_PLUGIN, 'tag' => '', 'srci' => ''); } if (self::param('add_local_jquery', 0)) { $srcs[] = JBETOLO_PATH . 'jbetolo/assets/jquery/' . JBETOLO_JQUERY; $srcsIndexes[JBETOLO_PATH . 'jbetolo/assets/jquery/' . JBETOLO_JQUERY] = array('src' => JBETOLO_PATH . 'jbetolo/assets/jquery/' . JBETOLO_JQUERY, 'tag' => '', 'srci' => ''); self::param('js_jquery', JBETOLO_JQUERY, 'set'); if (self::param('add_local_jquery_ui', 0)) { $srcs[] = JBETOLO_PATH . 'jbetolo/assets/jquery-ui/js/' . JBETOLO_JQUERY_UI; $srcsIndexes[JBETOLO_PATH . 'jbetolo/assets/jquery-ui/js/' . JBETOLO_JQUERY_UI] = array('src' => JBETOLO_PATH . 'jbetolo/assets/jquery-ui/js/' . JBETOLO_JQUERY_UI, 'tag' => '', 'srci' => ''); } } jbetoloJS::setJqueryFile($srcs, $_excludedSrcs); } else { if ($type == 'css') { if (self::param('add_local_jquery_ui_css', 0)) { $srcs[] = JBETOLO_PATH . 'jbetolo/assets/jquery-ui/css/' . JBETOLO_JQUERY_UI_CSS; $srcsIndexes[JBETOLO_PATH . 'jbetolo/assets/jquery-ui/css/' . JBETOLO_JQUERY_UI_CSS] = array('src' => JBETOLO_PATH . 'jbetolo/assets/jquery-ui/css/' . JBETOLO_JQUERY_UI_CSS, 'tag' => '', 'srci' => ''); } } } // apply merging ordering $orderedSrcs = jbetoloFileHelper::customOrder($srcsIndexes, $type, $srcs); $orderedSrcs = jbetoloHelper::getArrayValues($orderedSrcs, 'src'); $orderedExcludedSrcs = jbetoloFileHelper::customOrder($excludedSrcs, $type, $_excludedSrcs); return array($orderedSrcs, $orderedExcludedSrcs, $tags, $conds, $comments, $indexes); }