Files
kupshop/class/smarty_plugins/block.asset_compile.php
2025-08-02 16:30:27 +02:00

172 lines
6.4 KiB
PHP

<?php
global $cfg;
// define('SACY_TRANSFORMER_SASS', 1);
define('SACY_DEBUG_TOGGLE', 'SMARTY_DEBUG');
define('SACY_QUERY_STRINGS', 'force-handle');
define('SACY_WRITE_HEADERS', false);
define('SACY_TRANSFORMER_FONTICONS', '/usr/local/bin/fontcustom');
define('ASSET_COMPILE_OUTPUT_DIR', $cfg['Path']['data'].'tmp/cache/');
define('ASSET_COMPILE_URL_ROOT', '/'.$cfg['Path']['data'].'tmp/cache/');
$_SERVER['DOCUMENT_ROOT'] = './';
if (!defined('____SACY_BUNDLED')) {
include_once $cfg['Path']['shared_class'].'sacy/sacy.php';
include_once $cfg['Path']['shared_class'].'sacy/phpsass.php';
include_once $cfg['Path']['shared_class'].'sacy/fragment-cache.php';
}
if (!(defined('ASSET_COMPILE_OUTPUT_DIR') && defined('ASSET_COMPILE_URL_ROOT'))) {
throw new sacy\Exception('Failed to initialize because path configuration is not set (ASSET_COMPILE_OUTPUT_DIR and ASSET_COMPILE_URL_ROOT)');
}
function smarty_block_asset_compile($params, $content, &$template, &$repeat)
{
if (!$repeat) {
// don't shoot me, but all tried using the dom-parser and removing elements
// ended up with problems due to the annoying DOM API and braindead stuff
// like no getDocumentElement() or getElementByID() not working even though
// loadHTML clearly knows that the content is in fact HTML.
//
// So, let's go back to good old regexps :-)
$cfg = new sacy\Config($params);
if ($cfg->getDebugMode() == 1) {
return $content;
}
// Cache whole compile output
$cache_key = 'sacy-cache-'.md5($content);
if ($cfg->getDebugMode() == 0) {
$patched_content = getCache($cache_key);
if ($patched_content) {
return $patched_content;
}
}
$tag_pattern = '#\s*<\s*T(?:\s+(.*))?\s*(?:/>|>(.*)</T>)\s*#Uims';
$tags = [];
$aindex = 0;
// first assembling all work. The idea is that, if sorted by descending
// location offset, we can selectively remove tags.
//
// We'll need that to conditionally handle tags (like jTemplate's
// <script type="text/html" that should remain)
foreach (['link', 'style', 'script'] as $tag) {
$p = str_replace('T', preg_quote($tag), $tag_pattern);
if (preg_match_all($p, $content, $ms, PREG_OFFSET_CAPTURE)) {
foreach ($ms[1] as $i => $m) {
$tags[] = [
'tag' => $tag,
'attrdata' => $m[0],
'index' => $ms[0][$i][1],
'tagdata' => $ms[0][$i][0],
'content' => $ms[2][$i][0] ?? null,
'page_order' => $aindex++,
];
}
}
}
// now sort task list by descending location offset
usort($tags, function ($a, $b) {
if ($a['index'] == $b['index']) {
return 0;
}
return ($a['index'] < $b['index']) ? 1 : -1;
});
$ex = new sacy\WorkUnitExtractor($cfg);
$work_units = $ex->getAcceptedWorkUnits($tags);
$renderer = new sacy\CacheRenderer($cfg, $_SERVER['SCRIPT_FILENAME']);
$patched_content = $content;
$render = [];
$category = function ($work_unit) {
return implode('', [$work_unit['group'], $work_unit['tag'], (bool) $work_unit['file']]);
};
$curr_cat = $work_units ? $category($work_units[0]) : null;
$entry = null;
foreach ($work_units as $i => $entry) {
$cg = $category($entry);
// the moment the category changes, render all we have so far
// this makes it IMPERATIVE to keep links of the same category
// together.
if ($curr_cat != $cg || ($cfg->getDebugMode() == 3 && $i > 0 && $renderer->allowMergedTransformOnly($work_units[$i - 1]['tag']) && count($render))) {
$render_order = array_reverse($render);
$res = $renderer->renderWorkUnits($work_units[$i - 1]['tag'], $work_units[$i - 1]['group'], $render_order);
if ($res === false) {
// rendering failed.
// because we don't know which one, we just enter emergency mode
// and return the initial content unharmed:
return $content;
}
// add rendered stuff to patched content
$m = null;
foreach ($render as $r) {
if ($m == null) {
$m = $r['position'];
}
if ($r['position'] < $m) {
$m = $r['position'];
}
// remove tag
$patched_content = substr_replace($patched_content, '', $r['position'], $r['length']);
}
// splice in replacement
$patched_content = substr_replace($patched_content, $res, $m, 0);
$curr_cat = $cg;
$render = [$entry];
} else {
$render[] = $entry;
}
}
$render_order = array_reverse($render);
$res = '';
if ($work_units) {
$res = $renderer->renderWorkUnits($entry['tag'], $entry['group'], $render_order);
if ($res === false) {
// see last comment
return $content;
}
}
$m = 0;
foreach ($render as $r) {
if ($m == null) {
$m = $r['position'];
}
if ($r['position'] < $m) {
$m = $r['position'];
}
// remove tag
$patched_content = substr_replace($patched_content, '', $r['position'], $r['length']);
}
$patched_content = substr_replace($patched_content, $res, $m, 0);
if ($block_ref = $cfg->get('block_ref')) {
$sacy = $template->smarty->getTemplateVars('sacy') ?: [];
$rendered_assets = $sacy['rendered_assets'] ?: [];
$rendered_assets[$block_ref] = array_merge(
$rendered_assets[$block_ref] ?: [],
$renderer->getRenderedAssets()
);
$sacy['rendered_assets'] = $rendered_assets;
$template->smarty->assign('sacy', $sacy);
}
// Save content to cache
setCache($cache_key, $patched_content);
return $patched_content;
}
}