Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 36
0.00% covered (danger)
0.00%
0 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
HeadLink
0.00% covered (danger)
0.00%
0 / 36
0.00% covered (danger)
0.00%
0 / 9
380
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 getFileType
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 itemToString
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
20
 forcePrependStylesheet
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
20
 isExcludedFromConcat
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
12
 getResourceFilePath
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setResourceFilePath
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getType
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 getMinifier
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3/**
4 * Head link view helper (extended for VuFind's theme system)
5 *
6 * PHP version 8
7 *
8 * Copyright (C) Villanova University 2010.
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   Demian Katz <demian.katz@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
32use stdClass;
33use VuFindTheme\ThemeInfo;
34
35/**
36 * Head link view helper (extended for VuFind's theme system)
37 *
38 * @category VuFind
39 * @package  View_Helpers
40 * @author   Demian Katz <demian.katz@villanova.edu>
41 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
42 * @link     https://vufind.org/wiki/development Wiki
43 *
44 * @method getWhitespace(string|int $indent)
45 * @method getIndent()
46 * @method getSeparator()
47 */
48class HeadLink extends \Laminas\View\Helper\HeadLink implements \Laminas\Log\LoggerAwareInterface
49{
50    use ConcatTrait;
51    use RelativePathTrait;
52    use \VuFind\Log\LoggerAwareTrait;
53
54    /**
55     * Theme information service
56     *
57     * @var ThemeInfo
58     */
59    protected $themeInfo;
60
61    /**
62     * CSP nonce
63     *
64     * @var string
65     */
66    protected $cspNonce;
67
68    /**
69     * Maximum import size (for inlining of e.g. images) in kilobytes
70     *
71     * @var int|null
72     */
73    protected $maxImportSize;
74
75    /**
76     * Constructor
77     *
78     * @param ThemeInfo   $themeInfo     Theme information service
79     * @param string|bool $plconfig      Config for current application environment
80     * @param string      $nonce         Nonce from nonce generator
81     * @param int         $maxImportSize Maximum imported (inlined) file size
82     */
83    public function __construct(
84        ThemeInfo $themeInfo,
85        $plconfig = false,
86        $nonce = '',
87        $maxImportSize = null
88    ) {
89        parent::__construct();
90        $this->themeInfo = $themeInfo;
91        $this->usePipeline = $this->enabledInConfig($plconfig);
92        $this->cspNonce = $nonce;
93        $this->maxImportSize = $maxImportSize;
94        $this->itemKeys[] = 'nonce';
95    }
96
97    /**
98     * Folder name and file extension for trait
99     *
100     * @return string
101     */
102    protected function getFileType()
103    {
104        return 'css';
105    }
106
107    /**
108     * Create HTML link element from data item
109     *
110     * @param stdClass $item data item
111     *
112     * @return string
113     */
114    public function itemToString(stdClass $item)
115    {
116        // Normalize href to account for themes (if appropriate), then call the parent class:
117        if ($this->isRelativePath($item->href)) {
118            $relPath = 'css/' . $item->href;
119            $details = $this->themeInfo
120                ->findContainingTheme($relPath, ThemeInfo::RETURN_ALL_DETAILS);
121            if (!empty($details)) {
122                $urlHelper = $this->getView()->plugin('url');
123                $url = $urlHelper('home') . "themes/{$details['theme']}/" . $relPath;
124                $url .= strstr($url, '?') ? '&_=' : '?_=';
125                $url .= filemtime($details['path']);
126                $item->href = $url;
127            }
128        }
129        $this->addNonce($item);
130        return parent::itemToString($item);
131    }
132
133    /**
134     * Forcibly prepend a stylesheet removing it from any existing position
135     *
136     * @param string $href                  Stylesheet href
137     * @param string $media                 Media
138     * @param string $conditionalStylesheet Any conditions
139     * @param array  $extras                Array of extra attributes
140     *
141     * @return void
142     */
143    public function forcePrependStylesheet(
144        $href,
145        $media = 'screen',
146        $conditionalStylesheet = '',
147        $extras = []
148    ) {
149        // Look for existing entry and remove it if found. Comparison method
150        // copied from isDuplicate().
151        foreach ($this->getContainer() as $offset => $item) {
152            if (($item->rel == 'stylesheet') && ($item->href == $href)) {
153                $this->offsetUnset($offset);
154                break;
155            }
156        }
157        parent::prependStylesheet($href, $media, $conditionalStylesheet, $extras);
158    }
159
160    /**
161     * Returns true if file should not be included in the compressed concat file
162     * Required by ConcatTrait
163     *
164     * @param stdClass $item Link element object
165     *
166     * @return bool
167     */
168    protected function isExcludedFromConcat($item)
169    {
170        return !isset($item->rel) || $item->rel != 'stylesheet'
171            || strpos($item->href, '://');
172    }
173
174    /**
175     * Get the file path from the link object
176     * Required by ConcatTrait
177     *
178     * @param stdClass $item Link element object
179     *
180     * @return string
181     */
182    protected function getResourceFilePath($item)
183    {
184        return $item->href;
185    }
186
187    /**
188     * Set the file path of the link object
189     * Required by ConcatTrait
190     *
191     * @param stdClass $item Link element object
192     * @param string   $path New path string
193     *
194     * @return stdClass
195     */
196    protected function setResourceFilePath($item, $path)
197    {
198        $item->href = $path;
199        return $item;
200    }
201
202    /**
203     * Get the file type
204     *
205     * @param stdClass $item Link element object
206     *
207     * @return string
208     */
209    public function getType($item)
210    {
211        $type = $item->media ?? 'all';
212        if (isset($item->conditionalStylesheet)) {
213            $type .= '_' . $item->conditionalStylesheet;
214        }
215        return $type;
216    }
217
218    /**
219     * Get the minifier that can handle these file types
220     * Required by ConcatTrait
221     *
222     * @return \MatthiasMullie\Minify\JS
223     */
224    protected function getMinifier()
225    {
226        $minifier = new \VuFindTheme\Minify\CSS();
227        if (null !== $this->maxImportSize) {
228            $minifier->setMaxImportSize($this->maxImportSize);
229        }
230        return $minifier;
231    }
232}