Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
67 / 67
100.00% covered (success)
100.00%
4 / 4
CRAP
100.00% covered (success)
100.00%
1 / 1
PageLocator
100.00% covered (success)
100.00%
67 / 67
100.00% covered (success)
100.00%
4 / 4
10
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 generateTemplateFromPattern
100.00% covered (success)
100.00%
17 / 17
100.00% covered (success)
100.00%
1 / 1
2
 getTemplateOptionsFromPattern
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
1 / 1
2
 determineTemplateAndRenderer
100.00% covered (success)
100.00%
29 / 29
100.00% covered (success)
100.00%
1 / 1
5
1<?php
2
3/**
4 * Class PageLocator
5 *
6 * PHP version 8
7 *
8 * Copyright (C) Moravian Library 2020.
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  Content
25 * @author   Josef Moravec <moravec@mzk.cz>
26 * @license  https://opensource.org/licenses/gpl-2.0.php GNU General Public License
27 * @link     https://vufind.org/wiki/development Wiki
28 */
29
30namespace VuFind\Content;
31
32/**
33 * Class PageLocator
34 *
35 * @category VuFind
36 * @package  Content
37 * @author   Josef Moravec <moravec@mzk.cz>
38 * @license  https://opensource.org/licenses/gpl-2.0.php GNU General Public License
39 * @link     https://vufind.org/wiki/development Wiki
40 */
41class PageLocator
42{
43    /**
44     * Types/formats of content
45     *
46     * @var array $types
47     */
48    protected $types = [
49        'phtml',
50        'md',
51    ];
52
53    /**
54     * Theme info service
55     *
56     * @var \VuFindTheme\ThemeInfo
57     */
58    protected $themeInfo;
59
60    /**
61     * Current language
62     *
63     * @var string
64     */
65    protected $language;
66
67    /**
68     * Default language
69     *
70     * @var string
71     */
72    protected $defaultLanguage;
73
74    /**
75     * Page constructor.
76     *
77     * @param \VuFindTheme\ThemeInfo $themeInfo       Theme information service
78     * @param string                 $language        Current language
79     * @param string                 $defaultLanguage Main configuration
80     */
81    public function __construct($themeInfo, $language, $defaultLanguage)
82    {
83        $this->themeInfo = $themeInfo;
84        $this->language = $language;
85        $this->defaultLanguage  = $defaultLanguage;
86    }
87
88    /**
89     * Generate a template from a file search pattern. Examples:
90     * - %pathPrefix%/%pageName%{_%language%} => content/help_en
91     * - %pathPrefix%/%language%/%pageName% => HelpTranslations/en/search
92     *
93     * @param string $pathPrefix Subdirectory where the template should be located
94     * @param string $pageName   Page name
95     * @param string $pattern    Filesystem pattern
96     * @param string $language   Language
97     *
98     * @return string
99     */
100    protected function generateTemplateFromPattern(
101        string $pathPrefix,
102        string $pageName,
103        string $pattern,
104        string $language = ''
105    ): string {
106        $standardReplacements = [
107            '%pathPrefix%' => $pathPrefix,
108            '%pageName%' => $pageName,
109            '%language%' => $language,
110            '//' => '/',
111        ];
112        $languagePatternExtended = '"\\{(.*)%language%(.*)\\}"';
113        $languagePatternExtendedReplacement = $language ? "\\1$language\\2" : '';
114        return str_replace(
115            array_keys($standardReplacements),
116            array_values($standardReplacements),
117            preg_replace(
118                $languagePatternExtended,
119                $languagePatternExtendedReplacement,
120                $pattern
121            )
122        );
123    }
124
125    /**
126     * Try to find a template using
127     * 1) Current language
128     * 2) Default language
129     * 3) No language
130     *
131     * @param string $pathPrefix Subdirectory where the template should be located
132     * @param string $pageName   Template name
133     * @param string $pattern    Filesystem pattern
134     *
135     * @return \Generator Array generator with template options
136     *                    (key equals matchType)
137     */
138    protected function getTemplateOptionsFromPattern(
139        string $pathPrefix,
140        string $pageName,
141        string $pattern
142    ): \Generator {
143        yield 'language' => $this->generateTemplateFromPattern(
144            $pathPrefix,
145            $pageName,
146            $pattern,
147            $this->language
148        );
149        if ($this->language != $this->defaultLanguage) {
150            yield 'defaultLanguage' => $this->generateTemplateFromPattern(
151                $pathPrefix,
152                $pageName,
153                $pattern,
154                $this->defaultLanguage
155            );
156        }
157        yield 'pageName' => $this->generateTemplateFromPattern(
158            $pathPrefix,
159            $pageName,
160            $pattern
161        );
162    }
163
164    /**
165     * Try to find template information about desired page
166     *
167     * @param string $pathPrefix Subdirectory where the template should be located
168     * @param string $pageName   Template name
169     * @param string $pattern    Optional filesystem pattern
170     *
171     * @return array|null Null if template is not found or array with keys renderer
172     * (type of template), path (full path of template), relativePath (relative
173     * path within the templates directory), page (page name), theme,
174     * matchType (see getTemplateOptionsFromPattern)
175     */
176    public function determineTemplateAndRenderer(
177        $pathPrefix,
178        $pageName,
179        $pattern = null
180    ) {
181        if ($pattern === null) {
182            $pattern = '%pathPrefix%/%pageName%{_%language%}';
183        }
184
185        $templates = $this->getTemplateOptionsFromPattern(
186            $pathPrefix,
187            $pageName,
188            $pattern
189        );
190
191        foreach ($templates as $matchType => $template) {
192            foreach ($this->types as $type) {
193                $filename = "$template.$type";
194                $pathDetails = $this->themeInfo->findContainingTheme(
195                    $filename,
196                    $this->themeInfo::RETURN_ALL_DETAILS
197                );
198                if (null != $pathDetails) {
199                    $relativeTemplatePath = preg_replace(
200                        '"^templates/"',
201                        '',
202                        $pathDetails['relativePath']
203                    );
204                    return [
205                        'renderer' => $type,
206                        'path' => $pathDetails['path'],
207                        'relativePath' => $relativeTemplatePath,
208                        'page' => basename($template),
209                        'theme' => $pathDetails['theme'],
210                        'matchType' => $matchType,
211                    ];
212                }
213            }
214        }
215
216        return null;
217    }
218}