diff --git a/module/VuFindTheme/src/VuFindTheme/View/Helper/AssetPipeline.php b/module/VuFindTheme/src/VuFindTheme/View/Helper/AssetPipeline.php index 60f8d930898..72cb02298ec 100644 --- a/module/VuFindTheme/src/VuFindTheme/View/Helper/AssetPipeline.php +++ b/module/VuFindTheme/src/VuFindTheme/View/Helper/AssetPipeline.php @@ -40,6 +40,13 @@ */ class AssetPipeline extends \Laminas\View\Helper\AbstractHelper { + /** + * Array of accumulated scripts, indexed by position (header/footer). + * + * @var array + */ + protected $scripts = ['header' => [], 'footer' => []]; + /** * Array of accumulated styles. * @@ -148,12 +155,7 @@ public function appendScript( bool $allowArbitraryAttrs = false, string $position = 'header' ) { - $helperName = $position === 'header' ? 'headScript' : 'footScript'; - $scriptHelper = $this->getView()->plugin($helperName); - if ($allowArbitraryAttrs) { - $scriptHelper->setAllowArbitraryAttributes(true); - } - $scriptHelper->appendScript($script, $type, $attrs); + $this->scripts[$position][] = compact('script', 'type', 'attrs', 'allowArbitraryAttrs'); } /** @@ -172,8 +174,7 @@ public function appendScriptFile( array $attrs = [], string $position = 'header' ): void { - $helper = $position === 'header' ? 'headScript' : 'footScript'; - $this->getView()->plugin($helper)->appendFile($src, $type, $attrs); + $this->scripts[$position][] = compact('src', 'type', 'attrs'); } /** @@ -192,8 +193,13 @@ public function forcePrependScriptFile( array $attrs = [], string $position = 'header' ): void { - $helper = $position === 'header' ? 'headScript' : 'footScript'; - $this->getView()->plugin($helper)->forcePrependFile($src, $type, $attrs); + $newScripts = [compact('src', 'type', 'attrs')]; + foreach ($this->scripts[$position] as $script) { + if ($script['src'] ?? null !== $newScripts[0]['src']) { + $newScripts[] = $script; + } + } + $this->scripts[$position] = $newScripts; } /** @@ -214,20 +220,40 @@ public function prependScript( bool $allowArbitraryAttrs = false, string $position = 'header' ) { + array_unshift($this->scripts[$position], compact('script', 'type', 'attrs', 'allowArbitraryAttrs')); + } + + /** + * Return the HTML to output script assets in the requested position. + * + * @param mixed $position Position of assets (header or footer) + * + * @return string + */ + protected function outputScriptAssets($position): string + { $helperName = $position === 'header' ? 'headScript' : 'footScript'; $scriptHelper = $this->getView()->plugin($helperName); - if ($allowArbitraryAttrs) { - $scriptHelper->setAllowArbitraryAttributes(true); + foreach ($this->scripts[$position] as $script) { + if ($script['allowArbitraryAttrs'] ?? false) { + $scriptHelper->setAllowArbitraryAttributes(true); + } + // Every $script will have either a script attribute (inline JS) or a src attribute (file): + if (isset($script['script'])) { + $scriptHelper->appendScript($script['script'], $script['type'], $script['attrs']); + } else { + $scriptHelper->appendFile($script['src'], $script['type'], $script['attrs']); + } } - $scriptHelper->prependScript($script, $type, $attrs); + return ($scriptHelper)(); } /** - * Output the collected assets for the header. + * Return the HTML to output style assets. * * @return string */ - public function outputHeaderAssets(): string + protected function outputStyleAssets(): string { $headLink = $this->getView()->plugin('headLink'); foreach ($this->stylesheets as $sheet) { @@ -244,9 +270,17 @@ public function outputHeaderAssets(): string $headStyle->appendStyle($style['css'], $style['attributes']); } - return ($headLink)() . "\n" - . ($headStyle)() . "\n" - . ($this->getView()->plugin('headScript'))(); + return ($headLink)() . "\n" . ($headStyle)(); + } + + /** + * Output the collected assets for the header. + * + * @return string + */ + public function outputHeaderAssets(): string + { + return $this->outputStyleAssets() . "\n" . $this->outputScriptAssets('header'); } /** @@ -256,6 +290,6 @@ public function outputHeaderAssets(): string */ public function outputFooterAssets(): string { - return ($this->getView()->plugin('footScript'))(); + return $this->outputScriptAssets('footer'); } } diff --git a/module/VuFindTheme/src/VuFindTheme/View/Helper/HeadScript.php b/module/VuFindTheme/src/VuFindTheme/View/Helper/HeadScript.php index ab0a14a5c93..7b140d9d890 100644 --- a/module/VuFindTheme/src/VuFindTheme/View/Helper/HeadScript.php +++ b/module/VuFindTheme/src/VuFindTheme/View/Helper/HeadScript.php @@ -31,8 +31,6 @@ use VuFindTheme\ThemeInfo; -use function array_key_exists; - /** * Head script view helper (extended for VuFind's theme system) * @@ -125,35 +123,6 @@ public function itemToString($item, $indent, $escapeStart, $escapeEnd) return parent::itemToString($item, $indent, $escapeStart, $escapeEnd); } - /** - * Forcibly prepend a file removing it from any existing position - * - * @param string $src Script src - * @param string $type Script type - * @param array $attrs Array of script attributes - * - * @return void - */ - public function forcePrependFile( - $src = null, - $type = 'text/javascript', - array $attrs = [] - ) { - // Look for existing entry and remove it if found. Comparison method - // copied from isDuplicate(). - foreach ($this->getContainer() as $offset => $item) { - if ( - ($item->source === null) - && array_key_exists('src', $item->attributes) - && ($src === $item->attributes['src']) - ) { - $this->offsetUnset($offset); - break; - } - } - parent::prependFile($src, $type, $attrs); - } - /** * Returns true if file should not be included in the compressed concat file * Required by ConcatTrait