Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
90.57% covered (success)
90.57%
48 / 53
81.82% covered (warning)
81.82%
9 / 11
CRAP
0.00% covered (danger)
0.00%
0 / 1
Slot
90.57% covered (success)
90.57%
48 / 53
81.82% covered (warning)
81.82%
9 / 11
23.44
0.00% covered (danger)
0.00%
0 / 1
 __invoke
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 __toString
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isset
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
12
 build
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
4
 get
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 set
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 prepend
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 append
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 start
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 end
90.00% covered (success)
90.00%
9 / 10
0.00% covered (danger)
0.00%
0 / 1
4.02
 clear
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3/**
4 * Slot view helper
5 *
6 * PHP version 8
7 *
8 * Copyright (C) Villanova University 2019.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2,
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22 *
23 * @category VuFind
24 * @package  View_Helpers
25 * @author   Chris Hallberg <challber@villanova.edu>
26 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
27 * @link     https://vufind.org/wiki/development Wiki
28 */
29
30namespace VuFindTheme\View\Helper;
31
32/**
33 * Slot view helper
34 *
35 * @category VuFind
36 * @package  View_Helpers
37 * @author   Chris Hallberg <challber@villanova.edu>
38 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
39 * @link     https://vufind.org/wiki/development Wiki
40 */
41class Slot extends \Laminas\View\Helper\AbstractHelper
42{
43    /**
44     * End saving methods
45     *
46     * @const string
47     */
48    public const SET   = 'SET';
49    public const PREPEND = 'PREPEND';
50    public const APPEND = 'APPEND';
51
52    /**
53     * Storage for strings to be concatenated to the front of a block
54     *
55     * @var array of arrays
56     */
57    protected $blockPrepends = [];
58
59    /**
60     * Storage for strings saved to slots
61     *
62     * @var array
63     */
64    protected $blocks = [];
65
66    /**
67     * Storage for strings to be concatenated to the end of a block
68     *
69     * @var array of arrays
70     */
71    protected $blockAppends = [];
72
73    /**
74     * Call stack to handle nested slots
75     *
76     * @var array
77     */
78    protected $stack = [];
79
80    /**
81     * Get the Slot instance. Create if instance doesn't exist.
82     *
83     * @param string $name  Name of target block for action
84     * @param mixed  $value Optional shortcut parameter to set a value
85     *
86     * @return Slot|string|mixed
87     */
88    public function __invoke($name, $value = null)
89    {
90        $this->stack[] = $name;
91        if ($value != null) {
92            return $this->set($value);
93        }
94        return $this;
95    }
96
97    /**
98     * Shortcut to get if no methods are called on invoke.
99     *
100     * @return string|mixed
101     */
102    public function __toString()
103    {
104        return $this->get();
105    }
106
107    /**
108     * Checks for content to provide isset functionality.
109     *
110     * @return boolean
111     */
112    public function isset()
113    {
114        $name = array_pop($this->stack);
115        return isset($this->blockPrepends[$name]) ||
116            isset($this->blocks[$name]) ||
117            isset($this->blockAppends[$name]);
118    }
119
120    /**
121     * Helper function to return blocks with prepends and appends.
122     * Prepends, blocks, and appends are separated byspacestopreventthisfromhappening
123     *
124     * Non-string data can be stored in a slot but prepend and append
125     * will cause it to be concatenated into a string.
126     *
127     * @param string $name Name of target block for action
128     *
129     * @return string|mixed
130     */
131    protected function build($name)
132    {
133        $pre = $this->blockPrepends[$name] ?? [];
134        $post = $this->blockAppends[$name] ?? [];
135        if (!empty($pre) || !empty($post)) {
136            $block = $this->blocks[$name] ?? '';
137            $ret = implode(' ', $pre) . ' ' . $block . ' ' . implode(' ', $post);
138            return trim($ret);
139        }
140        if (!isset($this->blocks[$name])) {
141            return null;
142        }
143        return $this->blocks[$name];
144    }
145
146    /**
147     * Get current value of slot. Returns null if unset.
148     *
149     * @param mixed $default Value to return if no value is set
150     *
151     * @return string|null
152     */
153    public function get($default = null)
154    {
155        $name = array_pop($this->stack);
156        $ret = $this->build($name);
157        return $ret ?? $default;
158    }
159
160    /**
161     * Set current value of slot but only if unset.
162     *
163     * @param mixed $value Value to override if unset
164     *
165     * @return string|null
166     */
167    public function set($value)
168    {
169        $name = array_pop($this->stack);
170        if (!isset($this->blocks[$name])) {
171            $this->blocks[$name] = $value;
172        }
173        return $this->build($name);
174    }
175
176    /**
177     * Add string to list of block prepends.
178     *
179     * @param string $value Value to override if unset
180     *
181     * @return string
182     */
183    public function prepend($value)
184    {
185        $name = array_pop($this->stack);
186        if (!isset($this->blockPrepends[$name])) {
187            $this->blockPrepends[$name] = [$value];
188        } else {
189            array_unshift($this->blockPrepends[$name], $value);
190        }
191        return $this->build($name);
192    }
193
194    /**
195     * Add string to list of block appends.
196     *
197     * @param string $value Value to override if unset
198     *
199     * @return string
200     */
201    public function append($value)
202    {
203        $name = array_pop($this->stack);
204        if (!isset($this->blockAppends[$name])) {
205            $this->blockAppends[$name] = [$value];
206        } else {
207            array_push($this->blockAppends[$name], $value);
208        }
209        return $this->build($name);
210    }
211
212    /**
213     * Starts a buffer capture to override the value of a block.
214     *
215     * @return void
216     */
217    public function start()
218    {
219        array_pop($this->stack);
220        ob_start();
221    }
222
223    /**
224     * End a buffer capture to override the value of a block. Returns slot value.
225     *
226     * @param string $method SET/PREPEND/APPEND for where this buffer should be saved
227     *
228     * @return string|mixed
229     */
230    public function end($method = self::SET)
231    {
232        $method = strtoupper($method);
233        if ($method == self::SET) {
234            $ret = $this->set(ob_get_contents());
235        } elseif ($method == self::PREPEND) {
236            $ret = $this->prepend(ob_get_contents());
237        } elseif ($method == self::APPEND) {
238            $ret = $this->append(ob_get_contents());
239        } else {
240            throw new \Exception("Undefined Slot method: $method");
241        }
242        ob_end_clean();
243        return $ret;
244    }
245
246    /**
247     * Unset any values stored in a slot.
248     *
249     * @return void
250     */
251    public function clear()
252    {
253        $name = array_pop($this->stack);
254        $ret = $this->build($name);
255        unset($this->blockPrepends[$name]);
256        unset($this->blocks[$name]);
257        unset($this->blockAppends[$name]);
258        return $ret;
259    }
260}