From 381ba8f039cca1fd3c3c840b093e1f9b5aa078a3 Mon Sep 17 00:00:00 2001 From: Chris Hallberg <crhallberg@gmail.com> Date: Fri, 13 Mar 2020 14:38:56 -0400 Subject: [PATCH] Slot View Helper (#1454) * Slot helper prototype. - Slot/block system for easier customization. - Designed to set block values then include parent template (helper coming). - start/end for buffer capture. - set for string setting. - clear for value clearing. * Add get method to Slot. * Add Slot method documentation. * Improve Slot documentation. * Change syntax to slot('name')->action(). Fix instancing. * Improve documentation. * Add examples to slot PR. * Update documentation. * checkstyles * Fix error with slot->get. * Remove trim so any value type can be saved. * Add prepend/append methods to slots. * Move Slots helper to VuFindTheme. * Add unit tests for Slot helper. * Clear Slot prepends and appends. * Space and trim block output. * checkstyle typo * Improve documentation of non-string slot values. * Add method constants. * Add __invoke(name, val) and __toString shortcuts. * Clarify prepend/append concatination. * Slot clear returns old contents. * Update test to match new clear functionality. * Remove example * get() can now return a default. * Make non-string tests more robust. * Remove hardcoded string. * Documentation for get default. * Apply slots to root templates. * Add isset. * Apply slots to bootstrap templates. * Documentation fix. * Checkstyles. * Bugfix: prevent overriding of ''. * Laminas migration. * More specific slot name for home page hero. * Remove 'footer' full footer slot (footer). * Add tests to cover '' cases. * Add a few default tests. Co-authored-by: Demian Katz <demian.katz@villanova.edu> --- module/VuFindTheme/Module.php | 3 + .../src/VuFindTheme/View/Helper/Slot.php | 259 ++++++++++++++ .../src/VuFindTest/View/Helper/SlotTest.php | 330 ++++++++++++++++++ .../Recommend/CollectionSideFacets.phtml | 2 +- .../templates/Recommend/SideFacets.phtml | 2 +- .../Recommend/SideFacetsDeferred.phtml | 2 +- .../templates/combined/results-list.phtml | 6 +- .../templates/combined/results.phtml | 15 +- themes/bootstrap3/templates/eds/search.phtml | 2 +- themes/bootstrap3/templates/footer.phtml | 44 ++- .../bootstrap3/templates/records/home.phtml | 4 +- .../templates/search/controls/showing.phtml | 28 +- themes/bootstrap3/templates/search/home.phtml | 8 +- .../templates/search/newitemresults.phtml | 6 +- .../templates/search/reservesresults.phtml | 8 +- .../bootstrap3/templates/search/results.phtml | 27 +- .../AbstractBase/export-endnote.phtml | 2 +- .../AbstractBase/export-endnoteweb.phtml | 2 +- .../AbstractBase/export-refworks.phtml | 2 +- .../RecordDriver/Primo/export-endnote.phtml | 2 +- .../RecordDriver/Primo/export-refworks.phtml | 2 +- .../RecordDriver/Summon/export-endnote.phtml | 2 +- .../RecordDriver/Summon/export-refworks.phtml | 2 +- 23 files changed, 672 insertions(+), 88 deletions(-) create mode 100644 module/VuFindTheme/src/VuFindTheme/View/Helper/Slot.php create mode 100644 module/VuFindTheme/tests/unit-tests/src/VuFindTest/View/Helper/SlotTest.php diff --git a/module/VuFindTheme/Module.php b/module/VuFindTheme/Module.php index fd549f2dc81..2c1ead9cc65 100644 --- a/module/VuFindTheme/Module.php +++ b/module/VuFindTheme/Module.php @@ -100,6 +100,8 @@ class Module View\Helper\ParentTemplateFactory::class, View\Helper\InlineScript::class => View\Helper\PipelineInjectorFactory::class, + View\Helper\Slot::class => + View\Helper\PipelineInjectorFactory::class, View\Helper\TemplatePath::class => View\Helper\TemplatePathFactory::class, ], @@ -112,6 +114,7 @@ class Module \Laminas\View\Helper\InlineScript::class => View\Helper\InlineScript::class, 'parentTemplate' => View\Helper\ParentTemplate::class, + 'slot' => View\Helper\Slot::class, 'templatePath' => View\Helper\TemplatePath::class, ], ]; diff --git a/module/VuFindTheme/src/VuFindTheme/View/Helper/Slot.php b/module/VuFindTheme/src/VuFindTheme/View/Helper/Slot.php new file mode 100644 index 00000000000..294e29a0c28 --- /dev/null +++ b/module/VuFindTheme/src/VuFindTheme/View/Helper/Slot.php @@ -0,0 +1,259 @@ +<?php +/** + * Slot view helper + * + * PHP version 7 + * + * Copyright (C) Villanova University 2019. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package View_Helpers + * @author Chris Hallberg <challber@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +namespace VuFindTheme\View\Helper; + +/** + * Slot view helper + * + * @category VuFind + * @package View_Helpers + * @author Chris Hallberg <challber@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +class Slot extends \Laminas\View\Helper\AbstractHelper +{ + /** + * End saving methods + * + * @const string + */ + const SET = 'SET'; + const PREPEND = 'PREPEND'; + const APPEND = 'APPEND'; + + /** + * Storage for strings to be concatinated to the front of a block + * + * @var array of arrays + */ + protected $blockPrepends = []; + + /** + * Storage for strings saved to slots + * + * @var array + */ + protected $blocks = []; + + /** + * Storage for strings to be concatinated to the end of a block + * + * @var array of arrays + */ + protected $blockAppends = []; + + /** + * Call stack to handle nested slots + * + * @var array + */ + protected $stack = []; + + /** + * Get the Slot instance. Create if instance doesn't exist. + * + * @param string $name Name of target block for action + * @param any $value Optional shortcut parameter to set a value + * + * @return Slot|string|any + */ + public function __invoke($name, $value = null) + { + $this->stack[] = $name; + if ($value != null) { + return $this->set($value); + } + return $this; + } + + /** + * Shortcut to get if no methods are called on invoke. + * + * @return string|any + */ + public function __toString() + { + return $this->get(); + } + + /** + * Checks for content to provide isset functionality. + * + * @return boolean + */ + public function isset() + { + $name = array_pop($this->stack); + return isset($this->blockPrepends[$name]) || + isset($this->blocks[$name]) || + isset($this->blockAppends[$name]); + } + + /** + * Helper function to return blocks with prepends and appends. + * Prepends, blocks, and appends are separated byspacestopreventthisfromhappening + * + * Non-string data can be stored in a slot but prepend and append + * will cause it to be concatinated into a string. + * + * @param string $name Name of target block for action + * + * @return string|any + */ + protected function build($name) + { + $pre = $this->blockPrepends[$name] ?? []; + $post = $this->blockAppends[$name] ?? []; + if (!empty($pre) || !empty($post)) { + $block = $this->blocks[$name] ?? ''; + $ret = implode(' ', $pre) . ' ' . $block . ' ' . implode(' ', $post); + return trim($ret); + } + if (!isset($this->blocks[$name])) { + return null; + } + return $this->blocks[$name]; + } + + /** + * Get current value of slot. Returns null if unset. + * + * @param any $default Value to return if no value is set + * + * @return string|null + */ + public function get($default = null) + { + $name = array_pop($this->stack); + $ret = $this->build($name); + return $ret === null ? $default : $ret; + } + + /** + * Set current value of slot but only if unset. + * + * @param any $value Value to override if unset + * + * @return string|null + */ + public function set($value) + { + $name = array_pop($this->stack); + if (!isset($this->blocks[$name])) { + $this->blocks[$name] = $value; + } + return $this->build($name); + } + + /** + * Add string to list of block prepends. + * + * @param string $value Value to override if unset + * + * @return string + */ + public function prepend($value) + { + $name = array_pop($this->stack); + if (!isset($this->blockPrepends[$name])) { + $this->blockPrepends[$name] = [$value]; + } else { + array_unshift($this->blockPrepends[$name], $value); + } + return $this->build($name); + } + + /** + * Add string to list of block appends. + * + * @param string $value Value to override if unset + * + * @return string + */ + public function append($value) + { + $name = array_pop($this->stack); + if (!isset($this->blockAppends[$name])) { + $this->blockAppends[$name] = [$value]; + } else { + array_push($this->blockAppends[$name], $value); + } + return $this->build($name); + } + + /** + * Starts a buffer capture to override the value of a block. + * + * @return void + */ + public function start() + { + array_pop($this->stack); + ob_start(); + } + + /** + * End a buffer capture to override the value of a block. Returns slot value. + * + * @param string $method SET/PREPEND/APPEND for where this buffer should be saved + * + * @return string|any + */ + public function end($method = self::SET) + { + $method = strtoupper($method); + $ret = null; + if ($method == self::SET) { + $ret = $this->set(ob_get_contents()); + } elseif ($method == self::PREPEND) { + $ret = $this->prepend(ob_get_contents()); + } elseif ($method == self::APPEND) { + $ret = $this->append(ob_get_contents()); + } else { + throw new \Exception("Undefined Slot method: $method"); + } + ob_end_clean(); + return $ret; + } + + /** + * Unset any values stored in a slot. + * + * @return void + */ + public function clear() + { + $name = array_pop($this->stack); + $ret = $this->build($name); + unset($this->blockPrepends[$name]); + unset($this->blocks[$name]); + unset($this->blockAppends[$name]); + return $ret; + } +} diff --git a/module/VuFindTheme/tests/unit-tests/src/VuFindTest/View/Helper/SlotTest.php b/module/VuFindTheme/tests/unit-tests/src/VuFindTest/View/Helper/SlotTest.php new file mode 100644 index 00000000000..8d92883a3e4 --- /dev/null +++ b/module/VuFindTheme/tests/unit-tests/src/VuFindTest/View/Helper/SlotTest.php @@ -0,0 +1,330 @@ +<?php +/** + * HeadThemeResources view helper Test Class + * + * PHP version 7 + * + * Copyright (C) Villanova University 2010. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category VuFind + * @package Tests + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:testing:unit_tests Wiki + */ +namespace VuFindTest\View\Helper; + +use VuFindTheme\ResourceContainer; +use VuFindTheme\View\Helper\Slot; + +/** + * HeadThemeResources view helper Test Class + * + * @category VuFind + * @package Tests + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development:testing:unit_tests Wiki + */ +class SlotTest extends \VuFindTest\Unit\TestCase +{ + /** + * Test the helper. + * + * @return void + */ + public function testInstance() + { + $helper = $this->getHelper(); + $ret = $helper->__invoke('test'); + $this->assertTrue($ret instanceof Slot); + } + + /** + * Test get value of slot. + * + * @return void + */ + public function testGet() + { + $helper = $this->getHelper(); + + // test empty default + $this->assertEquals(null, $helper->__invoke('test')->get()); + $this->assertEquals('default', $helper->__invoke('test')->get('default')); + + // test populated over default + $helper->__invoke('test')->set('ONE'); + $this->assertEquals('ONE', $helper->__invoke('test')->get()); + $this->assertEquals('ONE', $helper->__invoke('test')->get('default')); + } + + /** + * Test setting value of slot blocking later sets. + * + * @return void + */ + public function testSet() + { + $helper = $this->getHelper(); + + // test return + $ret = $helper->__invoke('test')->set('ONE'); + $this->assertEquals('ONE', $ret); + + // test get + $this->assertEquals('ONE', $helper->__invoke('test')->get()); + + // test no override + $ret = $helper->__invoke('test')->set('TWO'); + $this->assertEquals('ONE', $ret); + + // test number + $ret = $helper->__invoke('array')->set(100); + $this->assertEquals(100, $ret); + + // test empty string (not null) + $helper->__invoke('empty')->clear(); + $ret = $helper->__invoke('empty')->set(''); + $this->assertEquals('', $ret); + $this->assertEquals('', $helper->__invoke('empty')->get('default')); + + // test array + $helper->__invoke('array')->clear(); + $ret = $helper->__invoke('array')->set([1, 2, 3]); + $this->assertEquals([1, 2, 3], $ret); + + // test object + $helper->__invoke('array')->clear(); + $ret = $helper->__invoke('array')->set(new \SplStack()); + $this->assertEquals('SplStack', get_class($ret)); + + // test shortcuts + $ret = $helper->__invoke('short', 'SUCCESS'); + $this->assertEquals('SUCCESS', $ret); + $this->assertEquals('SUCCESS', $helper->__invoke('short')); + } + + /** + * Test capturing echo with start and end. + * + * @return void + */ + public function testCapture() + { + $helper = $this->getHelper(); + + // test capture + $helper->__invoke('test')->start(); + echo 'BUFFER'; + $ret = $helper->__invoke('test')->end(); + $this->assertEquals('BUFFER', $ret); + + // test no override + $helper->__invoke('test')->start(); + echo 'OVERRIDE'; + $ret = $helper->__invoke('test')->end(); + $this->assertEquals('BUFFER', $ret); + } + + /** + * Test clearing blocks and allowing for override. + * + * @return void + */ + public function testClear() + { + $helper = $this->getHelper(); + $set1 = $helper->__invoke('test')->set('ONE'); + $this->assertEquals('ONE', $set1); + + $ret = $helper->__invoke('test')->clear(); + + // test returns old content + $this->assertEquals('ONE', $ret); + + // test now null + $this->assertEquals(null, $helper->__invoke('test')->get()); + + // test set after clear + $set1 = $helper->__invoke('test')->set('TWO'); + $this->assertEquals('TWO', $set1); + } + + /** + * Test prepending more to blocks. + * + * @return void + */ + public function testPrepend() + { + $helper = $this->getHelper(); + + // test no block + $ret = $helper->__invoke('test')->prepend('PRE1'); + $this->assertEquals('PRE1', $ret); + // default only returns of all are unset + $this->assertEquals('PRE1', $helper->__invoke('test')->get('default')); + + // test with block + $ret = $helper->__invoke('test')->set('BLOCK'); + $this->assertEquals('PRE1 BLOCK', $ret); + + // test capture prepend + $helper->__invoke('test')->start(); + echo 'PRE2'; + $ret = $helper->__invoke('test')->end('PREPEND'); // end mode + $this->assertEquals('PRE2 PRE1 BLOCK', $ret); + + // test get + $this->assertEquals('PRE2 PRE1 BLOCK', $helper->__invoke('test')->get()); + + // test clear + $helper->__invoke('test')->clear(); + $this->assertEquals(null, $helper->__invoke('test')->get()); + + // test empty strings + $ret = $helper->__invoke('test')->set(''); + $ret = $helper->__invoke('test')->prepend('PRE1'); + $this->assertEquals('PRE1', $ret); + $helper->__invoke('test')->clear(); + $ret = $helper->__invoke('test')->set('BASE'); + $ret = $helper->__invoke('test')->prepend(''); + $this->assertEquals('BASE', $ret); + } + + /** + * Test appending more to blocks. + * + * @return void + */ + public function testAppend() + { + $helper = $this->getHelper(); + + // test no block + $ret = $helper->__invoke('test')->append('POST1'); + $this->assertEquals('POST1', $ret); + // default only returns of all are unset + $this->assertEquals('POST1', $helper->__invoke('test')->get('default')); + + // test with block + $ret = $helper->__invoke('test')->set('BLOCK'); + $this->assertEquals('BLOCK POST1', $ret); + + // test capture append + $helper->__invoke('test')->start(); + echo 'POST2'; + $ret = $helper->__invoke('test')->end('APPEND'); // end mode + $this->assertEquals('BLOCK POST1 POST2', $ret); + + // test get + $this->assertEquals('BLOCK POST1 POST2', $helper->__invoke('test')->get()); + + // test clear + $helper->__invoke('test')->clear(); + $this->assertEquals(null, $helper->__invoke('test')->get()); + + // test empty strings + $ret = $helper->__invoke('test')->set(''); + $ret = $helper->__invoke('test')->append('POST'); + $this->assertEquals('POST', $ret); + $helper->__invoke('test')->clear(); + $ret = $helper->__invoke('test')->set('BASE'); + $ret = $helper->__invoke('test')->append(''); + $this->assertEquals('BASE', $ret); + } + + /** + * Test nested slots. + * + * @return void + */ + public function testNesting() + { + $helper = $this->getHelper(); + + $helper->__invoke('parent')->start(); + echo '<parent>'; + + $helper->__invoke('child')->start(); + echo 'CHILD'; + echo $child = $helper->__invoke('child')->end(); + $this->assertEquals('CHILD', $child); + + echo '</parent>'; + $ret = $helper->__invoke('parent')->end(); + $this->assertEquals('<parent>CHILD</parent>', $ret); + } + + /** + * Test nested slots showing that children don't appear in parent without echo. + * + * @return void + */ + public function testNestingWithoutEcho() + { + $helper = $this->getHelper(); + + $helper->__invoke('parent')->start(); + echo '<parent>'; + + $helper->__invoke('child')->start(); + echo 'CHILD'; + $child = $helper->__invoke('child')->end(); // no echo + $this->assertEquals('CHILD', $child); + + echo '</parent>'; + $ret = $helper->__invoke('parent')->end(); + $this->assertEquals('<parent></parent>', $ret); + } + + /** + * Build Slot helper with mock view + * + * @return \VuFindTheme\View\Helper\Slot + */ + protected function getHelper() + { + $helper = new Slot($this->getResourceContainer()); + $helper->setView($this->getMockView()); + return $helper; + } + + /** + * Get a populated resource container for testing. + * + * @return ResourceContainer + */ + protected function getResourceContainer() + { + $rc = new ResourceContainer(); + $rc->setEncoding('utf-8'); + $rc->setGenerator('fake-generator'); + return $rc; + } + + /** + * Get a fake view object. + * + * @return \Laminas\View\Renderer\PhpRenderer + */ + protected function getMockView() + { + $view = $this->createMock(\Laminas\View\Renderer\PhpRenderer::class); + return $view; + } +} diff --git a/themes/bootstrap3/templates/Recommend/CollectionSideFacets.phtml b/themes/bootstrap3/templates/Recommend/CollectionSideFacets.phtml index 41bcc4f0abc..d33647d61d8 100644 --- a/themes/bootstrap3/templates/Recommend/CollectionSideFacets.phtml +++ b/themes/bootstrap3/templates/Recommend/CollectionSideFacets.phtml @@ -1,5 +1,5 @@ <?php - $this->overrideSideFacetCaption = 'Filter Collection'; + $this->slot('side-facet-caption')->set('Filter Collection'); $this->baseUriExtra = $this->recommend->getResults()->getParams()->getCollectionId(); ?> <?=$this->render('Recommend/SideFacets.phtml')?> diff --git a/themes/bootstrap3/templates/Recommend/SideFacets.phtml b/themes/bootstrap3/templates/Recommend/SideFacets.phtml index 7817bff86e9..d89fce8f6e6 100644 --- a/themes/bootstrap3/templates/Recommend/SideFacets.phtml +++ b/themes/bootstrap3/templates/Recommend/SideFacets.phtml @@ -28,7 +28,7 @@ ?> <button class="close-offcanvas btn btn-link" data-toggle="offcanvas"><?=$this->transEsc('navigate_back') ?></button> <?php if ($results->getResultTotal() > 0): ?> - <h2><?=$this->transEsc(isset($this->overrideSideFacetCaption) ? $this->overrideSideFacetCaption : 'Narrow Search')?></h2> + <h4><?=$this->transEsc($this->slot('side-facet-caption')->get('Narrow Search')) ?></h4> <?php endif; ?> <?php $checkboxFilters = $this->recommend->getCheckboxFacetSet(); ?> <?php $checkboxesShown = false; ?> diff --git a/themes/bootstrap3/templates/Recommend/SideFacetsDeferred.phtml b/themes/bootstrap3/templates/Recommend/SideFacetsDeferred.phtml index 3d7e3f310de..69be1ea1239 100644 --- a/themes/bootstrap3/templates/Recommend/SideFacetsDeferred.phtml +++ b/themes/bootstrap3/templates/Recommend/SideFacetsDeferred.phtml @@ -29,7 +29,7 @@ } ?> <?php if ($results->getResultTotal() > 0): ?> - <h2><?=$this->transEsc(isset($this->overrideSideFacetCaption) ? $this->overrideSideFacetCaption : 'Narrow Search')?></h2> + <h4><?=$this->transEsc($this->slot('side-facet-caption')->get('Narrow Search')) ?></h4> <div class="side-facets-container-ajax" data-search-class-id="<?=$this->escapeHtmlAttr($this->searchClassId) ?>" data-location="<?=$this->escapeHtmlAttr($this->location) ?>" data-config-index="<?=$this->escapeHtmlAttr($this->configIndex) ?>"> <?php endif; ?> <?php $checkboxFilters = $this->recommend->getCheckboxFacetSet(); ?> diff --git a/themes/bootstrap3/templates/combined/results-list.phtml b/themes/bootstrap3/templates/combined/results-list.phtml index f53707e5a2e..99a0a95058d 100644 --- a/themes/bootstrap3/templates/combined/results-list.phtml +++ b/themes/bootstrap3/templates/combined/results-list.phtml @@ -37,11 +37,7 @@ <?php if ($recordTotal < 1): ?> <p class="alert alert-danger"> - <?php if (isset($view->overrideEmptyMessage)): ?> - <?=$view->overrideEmptyMessage?> - <?php else: ?> - <?=$this->translate('nohit_lookfor_html', ['%%lookfor%%' => $this->escapeHtml($lookfor)]) ?> - <?php endif; ?> + <?=$this->slot('empty-message')->get($this->translate('nohit_lookfor_html', ['%%lookfor%%' => $this->escapeHtml($lookfor)])); ?> </p> <?php if (isset($view->parseError)): ?> <p class="alert alert-danger"><?=$this->transEsc('nohit_parse_error')?></p> diff --git a/themes/bootstrap3/templates/combined/results.phtml b/themes/bootstrap3/templates/combined/results.phtml index 9bdc276a54f..23b2a079812 100644 --- a/themes/bootstrap3/templates/combined/results.phtml +++ b/themes/bootstrap3/templates/combined/results.phtml @@ -1,11 +1,9 @@ <?php // Set up page title: $lookfor = $this->params->getDisplayQuery(); - if (isset($this->overrideTitle)) { - $this->headTitle($this->overrideTitle); - } else { - $this->headTitle($this->translate('Search Results') . (empty($lookfor) ? '' : " - {$lookfor}")); - } + $headTitle = $this->slot('head-title') + ->get($this->translate('Search Results') . (empty($lookfor) ? '' : " - {$lookfor}")); + $this->headTitle($headTitle); // Set up search box: $this->layout()->searchbox = $this->context($this)->renderInContext( @@ -27,12 +25,7 @@ $combinedResults = $this->results; // Set up breadcrumbs: - if (isset($this->overrideTitle)) { - $this->layout()->breadcrumbs = '<li class="active">' . $this->escapeHtml($this->overrideTitle) . '</li>'; - } else { - $this->layout()->breadcrumbs = '<li class="active">' . $this->transEsc('Search') . ': ' . - $this->escapeHtml($lookfor) . '</li>'; - } + $this->layout()->breadcrumbs = '<li class="active">' . $this->escapeHtml($headTitle) . '</li>'; // Enable cart if appropriate: $this->showCartControls = $this->supportsCart && $this->cart()->isActive(); diff --git a/themes/bootstrap3/templates/eds/search.phtml b/themes/bootstrap3/templates/eds/search.phtml index 772edf01d51..d405df2d979 100644 --- a/themes/bootstrap3/templates/eds/search.phtml +++ b/themes/bootstrap3/templates/eds/search.phtml @@ -1,6 +1,6 @@ <?php // Load standard settings from the default search results screen: - $this->overrideSideFacetCaption = 'Refine Results'; + $this->slot('side-facet-caption')->set('Refine Results'); $this->paginationOptions = ['disableFirst' => true, 'disableLast' => true]; echo $this->render('search/results.phtml'); ?> diff --git a/themes/bootstrap3/templates/footer.phtml b/themes/bootstrap3/templates/footer.phtml index 2604172f5de..4a5d3c89682 100644 --- a/themes/bootstrap3/templates/footer.phtml +++ b/themes/bootstrap3/templates/footer.phtml @@ -1,29 +1,35 @@ <footer class="hidden-print"> <div class="footer-container"> <div class="footer-column"> - <h2><?=$this->transEsc('Search Options')?></h2> - <ul> - <li><a href="<?=$this->url('search-history')?>"><?=$this->transEsc('Search History')?></a></li> - <li><a href="<?=$this->url('search-advanced')?>"><?=$this->transEsc('Advanced Search')?></a></li> - </ul> + <?php $this->slot('footer-left')->start(); ?> + <p><strong><?=$this->transEsc('Search Options')?></strong></p> + <ul> + <li><a href="<?=$this->url('search-history')?>"><?=$this->transEsc('Search History')?></a></li> + <li><a href="<?=$this->url('search-advanced')?>"><?=$this->transEsc('Advanced Search')?></a></li> + </ul> + <?=$this->slot('footer-left')->end(); ?> </div> <div class="footer-column"> - <h2><?=$this->transEsc('Find More')?></h2> - <ul> - <li><a href="<?=$this->url('browse-home')?>"><?=$this->transEsc('Browse the Catalog')?></a></li> - <li><a href="<?=$this->url('alphabrowse-home')?>"><?=$this->transEsc('Browse Alphabetically')?></a></li> - <li><a href="<?=$this->url('channels-home')?>"><?=$this->transEsc('channel_explore')?></a></li> - <li><a href="<?=$this->url('search-reserves')?>"><?=$this->transEsc('Course Reserves')?></a></li> - <li><a href="<?=$this->url('search-newitem')?>"><?=$this->transEsc('New Items')?></a></li> - </ul> + <?php $this->slot('footer-center')->start(); ?> + <p><strong><?=$this->transEsc('Find More')?></strong></p> + <ul> + <li><a href="<?=$this->url('browse-home')?>"><?=$this->transEsc('Browse the Catalog')?></a></li> + <li><a href="<?=$this->url('alphabrowse-home')?>"><?=$this->transEsc('Browse Alphabetically')?></a></li> + <li><a href="<?=$this->url('channels-home')?>"><?=$this->transEsc('channel_explore')?></a></li> + <li><a href="<?=$this->url('search-reserves')?>"><?=$this->transEsc('Course Reserves')?></a></li> + <li><a href="<?=$this->url('search-newitem')?>"><?=$this->transEsc('New Items')?></a></li> + </ul> + <?=$this->slot('footer-center')->end(); ?> </div> <div class="footer-column"> - <h2><?=$this->transEsc('Need Help?')?></h2> - <ul> - <li><a href="<?=$this->url('help-home')?>?topic=search&_=<?=time() ?>" data-lightbox class="help-link"><?=$this->transEsc('Search Tips')?></a></li> - <li><a href="<?=$this->url('content-page', ['page' => 'asklibrary']) ?>"><?=$this->transEsc('Ask a Librarian')?></a></li> - <li><a href="<?=$this->url('content-page', ['page' => 'faq']) ?>"><?=$this->transEsc('FAQs')?></a></li> - </ul> + <?php $this->slot('footer-right')->start(); ?> + <p><strong><?=$this->transEsc('Need Help?')?></strong></p> + <ul> + <li><a href="<?=$this->url('help-home')?>?topic=search&_=<?=time() ?>" data-lightbox class="help-link"><?=$this->transEsc('Search Tips')?></a></li> + <li><a href="<?=$this->url('content-page', ['page' => 'asklibrary']) ?>"><?=$this->transEsc('Ask a Librarian')?></a></li> + <li><a href="<?=$this->url('content-page', ['page' => 'faq']) ?>"><?=$this->transEsc('FAQs')?></a></li> + </ul> + <?=$this->slot('footer-right')->end(); ?> </div> </div> <div class="poweredby"> diff --git a/themes/bootstrap3/templates/records/home.phtml b/themes/bootstrap3/templates/records/home.phtml index e8e558779b4..0136ff42352 100644 --- a/themes/bootstrap3/templates/records/home.phtml +++ b/themes/bootstrap3/templates/records/home.phtml @@ -1,6 +1,6 @@ <?php - $this->overrideTitle = $this->translate('View Records'); - $this->overrideSearchHeading = ''; + $this->slot('head-title')->set($this->translate('View Records')); + $this->slot('search-heading')->set(''); // Load standard settings from the default search results screen: echo $this->render('search/results.phtml'); diff --git a/themes/bootstrap3/templates/search/controls/showing.phtml b/themes/bootstrap3/templates/search/controls/showing.phtml index b0ae18b0c94..b2598bb229b 100644 --- a/themes/bootstrap3/templates/search/controls/showing.phtml +++ b/themes/bootstrap3/templates/search/controls/showing.phtml @@ -5,21 +5,21 @@ '%%total%%' => $this->localizedNumber($this->recordTotal), '%%lookfor%%' => $this->escapeHtml($this->lookfor) ]; + + $showingResults = $this->translate( + isset($this->skipTotalCount) ? 'showing_results_html' : 'showing_results_of_html', + $transParams + ); ?> -<?php if (!isset($this->skipTotalCount)): ?> - <?php $showingResults = $this->translate('showing_results_of_html', $transParams); ?> -<?php else: ?> - <?php $showingResults = $this->translate('showing_results_html', $transParams); ?> -<?php endif; ?> -<?php if (isset($this->overrideSearchHeading)): ?> - <?php $showingResults .= ' ' . $this->overrideSearchHeading; ?> -<?php elseif ($this->params->getSearchType() == 'basic'): ?> - <?php if (!isset($this->skipTotalCount)): ?> - <?php $showingResults = $this->translate('showing_results_of_for_html', $transParams); ?> - <?php else: ?> - <?php $showingResults = $this->translate('showing_results_for_html', $transParams); ?> - <?php endif; ?> -<?php endif; ?> +<?php if ($this->slot('search-heading')->isset()): ?> + <?php $showingResults .= ' ' . $this->slot('search-heading')->get(); ?> +<?php elseif ($this->params->getSearchType() == 'basic'): + $showingResults = $this->translate( + isset($this->skipTotalCount) ? 'showing_results_for_html' : 'showing_results_of_for_html', + $transParams + ); +endif; ?> + <?php $this->layout()->srmessage = $showingResults; ?> <?php if ($qtime = $this->results->getQuerySpeed()): ?> <?=$showingResults; ?><span class="search-query-time">, <?=$this->transEsc('query time')?>: <?=$this->localizedNumber($qtime, 2) . $this->transEsc('seconds_abbrev')?></span> diff --git a/themes/bootstrap3/templates/search/home.phtml b/themes/bootstrap3/templates/search/home.phtml index ee530a73b3e..b9b0c453f4f 100644 --- a/themes/bootstrap3/templates/search/home.phtml +++ b/themes/bootstrap3/templates/search/home.phtml @@ -14,8 +14,10 @@ ?> <div class="searchHomeContent"> - <?=$this->context($this)->renderInContext("search/searchbox.phtml", ['ignoreHiddenFilterMemory' => true])?> - <?=$this->inlineScript(\Laminas\View\Helper\HeadScript::SCRIPT, '$("#searchForm_lookfor").focus();', 'SET'); ?> + <?php $this->slot('search-home-hero')->start() ?> + <?=$this->context($this)->renderInContext("search/searchbox.phtml", ['ignoreHiddenFilterMemory' => true])?> + <?=$this->inlineScript(\Laminas\View\Helper\HeadScript::SCRIPT, '$("#searchForm_lookfor").focus();', 'SET'); ?> + <?=$this->slot('search-home')->end() ?> </div> -<?=implode('', array_map([$this, 'contentBlock'], $blocks ?? []))?> \ No newline at end of file +<?=implode('', array_map([$this, 'contentBlock'], $blocks ?? []))?> diff --git a/themes/bootstrap3/templates/search/newitemresults.phtml b/themes/bootstrap3/templates/search/newitemresults.phtml index 8eb629497fd..4a61b2ad29d 100644 --- a/themes/bootstrap3/templates/search/newitemresults.phtml +++ b/themes/bootstrap3/templates/search/newitemresults.phtml @@ -1,7 +1,7 @@ <?php // Set some overrides, then call the standard search results action: - $this->overrideTitle = $this->translate('New Items'); - $this->overrideSearchHeading = $this->transEsc('New Items'); - $this->overrideEmptyMessage = $this->transEsc('No new item information is currently available.'); + $this->slot('head-title')->set($this->translate('New Items')); + $this->slot('search-heading')->set($this->transEsc('New Items')); + $this->slot('empty-message')->set($this->transEsc('No new item information is currently available.')); echo $this->render('search/results.phtml'); ?> diff --git a/themes/bootstrap3/templates/search/reservesresults.phtml b/themes/bootstrap3/templates/search/reservesresults.phtml index d007c4f582e..cdcf2affa73 100644 --- a/themes/bootstrap3/templates/search/reservesresults.phtml +++ b/themes/bootstrap3/templates/search/reservesresults.phtml @@ -1,7 +1,7 @@ <?php // Set some overrides, then call the standard search results action: - $this->overrideTitle = $this->translate('Reserves Search Results'); - $this->overrideSearchHeading = $this->transEsc('Reserves'); + $this->slot('head-title')->set($this->translate('Reserves Search Results')); + $this->slot('search-heading')->set($this->transEsc('Reserves')); $headingParts = []; if (isset($this->instructor)) { $headingParts[] = $this->transEsc('Instructor') . ': <strong>' . $this->escapeHtml($this->instructor) . '</strong>'; @@ -10,8 +10,8 @@ $headingParts[] = $this->transEsc('Course') . ': <strong>' . $this->escapeHtml($this->course) . '</strong>'; } if (!empty($headingParts)) { - $this->overrideSearchHeading .= ' (' . implode(', ', $headingParts) . ')'; + $this->slot('search-heading')->append(' (' . implode(', ', $headingParts) . ')'); } - $this->overrideEmptyMessage = $this->transEsc('course_reserves_empty_list'); + $this->slot('empty-message')->set($this->transEsc('course_reserves_empty_list')); echo $this->render('search/results.phtml'); ?> diff --git a/themes/bootstrap3/templates/search/results.phtml b/themes/bootstrap3/templates/search/results.phtml index bec5c3c6dbe..dbf10432e07 100644 --- a/themes/bootstrap3/templates/search/results.phtml +++ b/themes/bootstrap3/templates/search/results.phtml @@ -1,11 +1,9 @@ <?php // Set up page title: $lookfor = $this->results->getUrlQuery()->isQuerySuppressed() ? '' : $this->params->getDisplayQuery(); - if (isset($this->overrideTitle)) { - $this->headTitle($this->overrideTitle); - } else { - $this->headTitle($this->translate('Search Results') . (empty($lookfor) ? '' : " - {$lookfor}")); - } + $headTitle = $this->slot('head-title') + ->get($this->translate('Search Results') . (empty($lookfor) ? '' : " - {$lookfor}")); + $this->headTitle($headTitle); // Set up search box: $this->layout()->searchbox = $this->context($this)->renderInContext( @@ -26,11 +24,7 @@ ); // Set up breadcrumbs: - if (isset($this->overrideTitle)) { - $this->layout()->breadcrumbs .= '<li class="active">' . $this->escapeHtml($this->overrideTitle) . '</li>'; - } else { - $this->layout()->breadcrumbs .= '<li class="active">' . $this->transEsc('Search') . ': ' . $this->escapeHtml($lookfor) . '</li>'; - } + $this->layout()->breadcrumbs .= '<li class="active">' . $this->escapeHtml($headTitle) . '</li>'; // Enable cart if appropriate: $this->showBulkOptions = $this->params->getOptions()->supportsCart() && $this->showBulkOptions; @@ -83,12 +77,13 @@ <?php if ($recordTotal < 1): ?> <p> - <?php if (isset($this->overrideEmptyMessage)): ?> - <?=$this->overrideEmptyMessage?> - <?php else: ?> - <?php $this->layout()->srmessage = $this->translate('nohit_lookfor_html', ['%%lookfor%%' => $this->escapeHtml($lookfor)]); ?> - <?=$this->layout()->srmessage ?> - <?php endif; ?> + <?php + $emptyMessage = $this->slot('empty-message')->get( + $this->translate('nohit_lookfor_html', ['%%lookfor%%' => $this->escapeHtml($lookfor)]) + ); + $this->layout()->srmessage = $emptyMessage; + echo $emptyMessage; + ?> </p> <?php if (isset($this->parseError)): ?> <p class="alert alert-danger"><?=$this->transEsc('nohit_parse_error')?></p> diff --git a/themes/root/templates/RecordDriver/AbstractBase/export-endnote.phtml b/themes/root/templates/RecordDriver/AbstractBase/export-endnote.phtml index 614f668d251..fcbd238271d 100644 --- a/themes/root/templates/RecordDriver/AbstractBase/export-endnote.phtml +++ b/themes/root/templates/RecordDriver/AbstractBase/export-endnote.phtml @@ -1,6 +1,6 @@ <?php // A driver-specific template may pass in format overrides; check for these before going to the driver itself: -$formats = isset($this->overrideFormats) ? $this->overrideFormats : $this->driver->tryMethod('getFormats'); +$formats = $this->slot('endnote-formats')->get($this->driver->tryMethod('getFormats')); if (is_array($formats) && !empty($formats)) { foreach ($formats as $format) { echo "%0 $format\n"; diff --git a/themes/root/templates/RecordDriver/AbstractBase/export-endnoteweb.phtml b/themes/root/templates/RecordDriver/AbstractBase/export-endnoteweb.phtml index c3f86e304bf..0b9877d8d78 100644 --- a/themes/root/templates/RecordDriver/AbstractBase/export-endnoteweb.phtml +++ b/themes/root/templates/RecordDriver/AbstractBase/export-endnoteweb.phtml @@ -1,6 +1,6 @@ <?php // A driver-specific template may pass in format overrides; check for these before going to the driver itself: -$formats = isset($this->overrideFormats) ? $this->overrideFormats : $this->driver->tryMethod('getFormats'); +$formats = $this->slot('endnoteweb-formats')->get($this->driver->tryMethod('getFormats')); if (is_array($formats)) { foreach ($formats as $format) { switch (strtolower($format)) { diff --git a/themes/root/templates/RecordDriver/AbstractBase/export-refworks.phtml b/themes/root/templates/RecordDriver/AbstractBase/export-refworks.phtml index 83bdd8559c9..40c406eea4b 100644 --- a/themes/root/templates/RecordDriver/AbstractBase/export-refworks.phtml +++ b/themes/root/templates/RecordDriver/AbstractBase/export-refworks.phtml @@ -1,6 +1,6 @@ <?php // A driver-specific template may pass in format overrides; check for these before going to the driver itself: -$formats = isset($this->overrideFormats) ? $this->overrideFormats : $this->driver->tryMethod('getFormats'); +$formats = $this->slot('refworks-formats')->get($this->driver->tryMethod('getFormats')); if (is_array($formats) && !empty($formats)) { foreach ($formats as $format) { echo "RT $format\n"; diff --git a/themes/root/templates/RecordDriver/Primo/export-endnote.phtml b/themes/root/templates/RecordDriver/Primo/export-endnote.phtml index 6a69596db1f..927f9c7cdb9 100644 --- a/themes/root/templates/RecordDriver/Primo/export-endnote.phtml +++ b/themes/root/templates/RecordDriver/Primo/export-endnote.phtml @@ -61,6 +61,6 @@ case 'Website': break; } -$this->overrideFormats = [$endnoteFormat]; +$this->slot('endnote-formats')->set([$endnoteFormat]); // Use the default template, but override the formats: echo $this->render('RecordDriver/AbstractBase/export-endnote.phtml'); diff --git a/themes/root/templates/RecordDriver/Primo/export-refworks.phtml b/themes/root/templates/RecordDriver/Primo/export-refworks.phtml index c4904e8259b..0b31ae9cf27 100644 --- a/themes/root/templates/RecordDriver/Primo/export-refworks.phtml +++ b/themes/root/templates/RecordDriver/Primo/export-refworks.phtml @@ -57,6 +57,6 @@ case 'Website': break; } -$this->overrideFormats = [$refworksFormat]; +$this->slot('refworks-formats')->set([$refworksFormat]); // Use the default template, but override the formats: echo $this->render('RecordDriver/AbstractBase/export-refworks.phtml'); diff --git a/themes/root/templates/RecordDriver/Summon/export-endnote.phtml b/themes/root/templates/RecordDriver/Summon/export-endnote.phtml index e733fdfec86..8e46b18e62f 100644 --- a/themes/root/templates/RecordDriver/Summon/export-endnote.phtml +++ b/themes/root/templates/RecordDriver/Summon/export-endnote.phtml @@ -6,6 +6,6 @@ foreach ($formats as $i => $format) { } // Use the default template, but override the formats: -$this->overrideFormats = $formats; +$this->slot('endnote-formats')->set($formats); echo $this->render('RecordDriver/AbstractBase/export-endnote.phtml'); ?> diff --git a/themes/root/templates/RecordDriver/Summon/export-refworks.phtml b/themes/root/templates/RecordDriver/Summon/export-refworks.phtml index 008f016744e..ff9a0878c9a 100644 --- a/themes/root/templates/RecordDriver/Summon/export-refworks.phtml +++ b/themes/root/templates/RecordDriver/Summon/export-refworks.phtml @@ -6,6 +6,6 @@ foreach ($formats as $i => $format) { } // Use the default template, but override the formats: -$this->overrideFormats = $formats; +$this->slot('refworks-formats')->set($formats); echo $this->render('RecordDriver/AbstractBase/export-refworks.phtml'); ?> -- GitLab