MDL-44357 theme: Allow core to compile LESS in PHP
[moodle.git] / lib / classes / lessc.php
CommitLineData
d433cf37
FM
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 * Moodle implementation of LESS.
19 *
20 * @package core
21 * @copyright 2014 Frédéric Massart
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
25defined('MOODLE_INTERNAL') || die();
26require_once($CFG->libdir . '/lessphp/Autoloader.php');
27Less_Autoloader::register();
28
29/**
30 * Moodle LESS compiler class.
31 *
32 * @package core
33 * @copyright 2014 Frédéric Massart
34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
35 */
36class core_lessc extends Less_Parser {
37
38 /**
39 * Add a rule to import a file.
40 *
41 * This is useful when you want to import the content of a LESS files but
42 * you are not sure if it contains @imports or not. This method will
43 * import the file using @import with a relative path from your
44 * main file to compile. Less does not support absolute paths.
45 *
46 * @param string $filepath The path to the LESS file to import.
47 * @param string $relativeto The path from which the relative path should be built.
48 * Typically this would be the path to a file passed
49 * to {@link self::parseFile()}.
50 * @return void
51 */
52 public function import_file($filepath, $relativeto) {
53 global $CFG;
54
55 if (!is_readable($filepath) || !is_readable($relativeto)) {
56 throw new coding_exception('Could not read the files');
57 }
58
59 $filepath = realpath($filepath);
60 $relativeto = realpath($relativeto);
61
62 if (strtolower(substr($filepath, -5)) != '.less') {
63 throw new coding_exception('Imports only work with LESS files.');
64 } else if (strpos(realpath($filepath), $CFG->dirroot) !== 0 ||
65 strpos(realpath($relativeto), $CFG->dirroot) !== 0) {
66 throw new coding_exception('Files must be in CFG->dirroot.');
67 }
68
69 // Simplify the file path the start of dirroot.
70 $filepath = trim(substr($filepath, strlen($CFG->dirroot)), '/');
71 $relativeto = trim(substr($relativeto, strlen($CFG->dirroot)), '/');
72
73 // Split the file path and remove the file name.
74 $dirs = explode('/', $relativeto);
75 array_pop($dirs);
76
77 // Generate the relative path.
78 $relativepath = str_repeat('../', count($dirs)) . $filepath;
79
80 $this->parse('@import "' . $relativepath . '";');
81 }
82
83 /**
84 * Parse the content of a file.
85 *
86 * The purpose of this method is to provide a way to import the
87 * content of a file without messing with the import directories
88 * as {@link self::parseFile()} would do. But of course you should
89 * have manually set your import directories previously.
90 *
91 * @see self::SetImportDirs()
92 * @param string $filepath The path to the file.
93 * @return void
94 */
95 public function parse_file_content($filepath) {
96 $this->parse(file_get_contents($filepath));
97 }
98
99}