1<?php
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
17/**
18 * List the valid locations to search for a template with a given name.
19 *
20 * @package    core
21 * @category   output
22 * @copyright  2015 Damyon Wiese
23 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 */
25
26namespace core\output;
27
28use coding_exception;
29use moodle_exception;
30use core_component;
31use theme_config;
32
33/**
34 * Get information about valid locations for mustache templates.
35 *
36 * @copyright  2015 Damyon Wiese
37 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
38 * @since      2.9
39 */
40class mustache_template_finder {
41
42    /**
43     * Helper function for getting a list of valid template directories for a specific component.
44     *
45     * @param string $component The component to search
46     * @param string $themename The current theme name
47     * @return string[] List of valid directories for templates for this compoonent. Directories are not checked for existence.
48     */
49    public static function get_template_directories_for_component($component, $themename = '') {
50        global $CFG, $PAGE;
51
52        // Default the param.
53        if ($themename == '') {
54            $themename = $PAGE->theme->name;
55        }
56
57        // Clean params for safety.
58        $component = clean_param($component, PARAM_COMPONENT);
59        $themename = clean_param($themename, PARAM_COMPONENT);
60
61        // Validate the component.
62        $dirs = array();
63        $compdirectory = core_component::get_component_directory($component);
64        if (!$compdirectory) {
65            throw new coding_exception("Component was not valid: " . s($component));
66        }
67
68        // Find the parent themes.
69        $parents = array();
70        if ($themename === $PAGE->theme->name) {
71            $parents = $PAGE->theme->parents;
72        } else {
73            $themeconfig = theme_config::load($themename);
74            $parents = $themeconfig->parents;
75        }
76
77        // First check the theme.
78        $dirs[] = $CFG->dirroot . '/theme/' . $themename . '/templates/' . $component . '/';
79        if (isset($CFG->themedir)) {
80            $dirs[] = $CFG->themedir . '/' . $themename . '/templates/' . $component . '/';
81        }
82        // Now check the parent themes.
83        // Search each of the parent themes second.
84        foreach ($parents as $parent) {
85            $dirs[] = $CFG->dirroot . '/theme/' . $parent . '/templates/' . $component . '/';
86            if (isset($CFG->themedir)) {
87                $dirs[] = $CFG->themedir . '/' . $parent . '/templates/' . $component . '/';
88            }
89        }
90
91        $dirs[] = $compdirectory . '/templates/';
92
93        return $dirs;
94    }
95
96    /**
97     * Helper function for getting a filename for a template from the template name.
98     *
99     * @param string $name - This is the componentname/templatename combined.
100     * @param string $themename - This is the current theme name.
101     * @return string
102     */
103    public static function get_template_filepath($name, $themename = '') {
104        global $CFG, $PAGE;
105
106        if (strpos($name, '/') === false) {
107            throw new coding_exception('Templates names must be specified as "componentname/templatename"' .
108                                       ' (' . s($name) . ' requested) ');
109        }
110
111        list($component, $templatename) = explode('/', $name, 2);
112        $component = clean_param($component, PARAM_COMPONENT);
113
114        $dirs = self::get_template_directories_for_component($component, $themename);
115
116        foreach ($dirs as $dir) {
117            $candidate = $dir . $templatename . '.mustache';
118            if (file_exists($candidate)) {
119                return $candidate;
120            }
121        }
122
123        throw new moodle_exception('filenotfound', 'error', '', null, $name);
124    }
125}
126