Dotclear

source: plugins/themeEditor/class.themeEditor.php @ 3874:ab8368569446

Revision 3874:ab8368569446, 11.8 KB checked in by franck <carnet.franck.paul@…>, 7 years ago (diff)

short notation for array (array() → [])

Line 
1<?php
2/**
3 * @brief themeEditor, a plugin for Dotclear 2
4 *
5 * @package Dotclear
6 * @subpackage Plugins
7 *
8 * @copyright Olivier Meunier & Association Dotclear
9 * @copyright GPL-2.0-only
10 */
11
12if (!defined('DC_RC_PATH')) {return;}
13
14class dcThemeEditor
15{
16    protected $core;
17
18    protected $user_theme;
19    protected $parent_theme;
20    protected $tplset_theme;
21
22    protected $parent_name;
23    protected $tplset_name;
24
25    public $tpl = [];
26    public $css = [];
27    public $js  = [];
28    public $po  = [];
29
30    public function __construct($core)
31    {
32        $this->core          = &$core;
33        $this->default_theme = path::real($this->core->blog->themes_path . '/default');
34        $this->user_theme    = path::real($this->core->blog->themes_path . '/' . $this->core->blog->settings->system->theme);
35        $this->tplset_theme  = DC_ROOT . '/inc/public/default-templates/' . DC_DEFAULT_TPLSET;
36        $this->tplset_name   = DC_DEFAULT_TPLSET;
37        if (null !== $this->core->themes) {
38            $parent_theme = $this->core->themes->moduleInfo($this->core->blog->settings->system->theme, 'parent');
39            if ($parent_theme) {
40                $this->parent_theme = path::real($this->core->blog->themes_path . '/' . $parent_theme);
41                $this->parent_name  = $parent_theme;
42            }
43            $tplset = $this->core->themes->moduleInfo($this->core->blog->settings->system->theme, 'tplset');
44            if ($tplset) {
45                $this->tplset_theme = DC_ROOT . '/inc/public/default-templates/' . $tplset;
46                $this->tplset_name  = $tplset;
47            }
48        }
49        $this->findTemplates();
50        $this->findStyles();
51        $this->findScripts();
52        $this->findLocales();
53    }
54
55    public function filesList($type, $item = '%1$s', $split = true)
56    {
57        $files = $this->getFilesFromType($type);
58
59        if (empty($files)) {
60            return '<p>' . __('No file') . '</p>';
61        }
62
63        $list = '';
64        if ($split) {
65            $list_theme  = ''; // Files from current theme
66            $list_parent = ''; // Files from parent of current theme
67            $list_tpl    = ''; // Files from template set used by current theme
68            foreach ($files as $k => $v) {
69                if (strpos($v, $this->user_theme) === 0) {
70                    $li = sprintf('<li class="default-file">%s</li>', $item);
71                    $list_theme .= sprintf($li, $k, html::escapeHTML($k));
72                } elseif ($this->parent_theme && strpos($v, $this->parent_theme) === 0) {
73                    $li = sprintf('<li class="parent-file">%s</li>', $item);
74                    $list_parent .= sprintf($li, $k, html::escapeHTML($k));
75                } else {
76                    $li = sprintf('<li>%s</li>', $item);
77                    $list_tpl .= sprintf($li, $k, html::escapeHTML($k));
78                }
79            }
80            $list .= ($list_theme != '' ? sprintf('<li class="group-file">' . __('From theme:') . '<ul>%s</ul></li>', $list_theme) : '');
81            $list .= ($list_parent != '' ? sprintf('<li class="group-file">' . __('From parent:') . ' %s<ul>%s</ul></li>',
82                $this->parent_name, $list_parent) : '');
83            $list .= ($list_tpl != '' ? sprintf('<li class="group-file">' . __('From template set:') . ' %s<ul>%s</ul></li>',
84                $this->tplset_name, $list_tpl) : '');
85        } else {
86            foreach ($files as $k => $v) {
87                if (strpos($v, $this->user_theme) === 0) {
88                    $li = sprintf('<li class="default-file">%s</li>', $item);
89                } elseif ($this->parent_theme && strpos($v, $this->parent_theme) === 0) {
90                    $li = sprintf('<li class="parent-file">%s</li>', $item);
91                } else {
92                    $li = sprintf('<li>%s</li>', $item);
93                }
94                $list .= sprintf($li, $k, html::escapeHTML($k));
95            }
96        }
97
98        return sprintf('<ul>%s</ul>', $list);
99    }
100
101    public function getFileContent($type, $f)
102    {
103        $files = $this->getFilesFromType($type);
104
105        if (!isset($files[$f])) {
106            throw new Exception(__('File does not exist.'));
107        }
108
109        $F = $files[$f];
110        if (!is_readable($F)) {
111            throw new Exception(sprintf(__('File %s is not readable'), $f));
112        }
113
114        return [
115            'c'    => file_get_contents($F),
116            'w'    => $this->getDestinationFile($type, $f) !== false,
117            'type' => $type,
118            'f'    => $f
119        ];
120    }
121
122    public function writeFile($type, $f, $content)
123    {
124        $files = $this->getFilesFromType($type);
125
126        if (!isset($files[$f])) {
127            throw new Exception(__('File does not exist.'));
128        }
129
130        try
131        {
132            $dest = $this->getDestinationFile($type, $f);
133
134            if ($dest == false) {
135                throw new Exception();
136            }
137
138            if ($type == 'tpl' && !is_dir(dirname($dest))) {
139                files::makeDir(dirname($dest));
140            }
141
142            if ($type == 'po' && !is_dir(dirname($dest))) {
143                files::makeDir(dirname($dest));
144            }
145
146            $fp = @fopen($dest, 'wb');
147            if (!$fp) {
148                throw new Exception('tocatch');
149            }
150
151            $content = preg_replace('/(\r?\n)/m', "\n", $content);
152            $content = preg_replace('/\r/m', "\n", $content);
153
154            fwrite($fp, $content);
155            fclose($fp);
156
157            # Updating inner files list
158            $this->updateFileInList($type, $f, $dest);
159        } catch (Exception $e) {
160            throw new Exception(sprintf(__('Unable to write file %s. Please check your theme files and folders permissions.'), $f));
161        }
162    }
163
164    public function deletableFile($type, $f)
165    {
166        if ($type != 'tpl') {
167            // Only tpl files may be deleted
168            return false;
169        }
170
171        $files = $this->getFilesFromType($type);
172        if (isset($files[$f])) {
173            $dest = $this->getDestinationFile($type, $f);
174            if ($dest) {
175                if (file_exists($dest) && is_writable($dest)) {
176                    // Is there a model (parent theme or template set) ?
177                    if (isset($this->tpl_model[$f])) {
178                        return true;
179                    }
180                }
181            }
182        }
183        return false;
184    }
185
186    public function deleteFile($type, $f)
187    {
188        if ($type != 'tpl') {
189            // Only tpl files may be deleted
190            return;
191        }
192
193        $files = $this->getFilesFromType($type);
194        if (!isset($files[$f])) {
195            throw new Exception(__('File does not exist.'));
196        }
197
198        try
199        {
200            $dest = $this->getDestinationFile($type, $f);
201            if ($dest) {
202                // File exists and may be deleted
203                unlink($dest);
204
205                // Updating template files list
206                $this->findTemplates();
207            }
208        } catch (Exception $e) {
209            throw new Exception(sprintf(__('Unable to delete file %s. Please check your theme files and folders permissions.'), $f));
210        }
211    }
212
213    protected function getDestinationFile($type, $f)
214    {
215        if ($type == 'tpl') {
216            $dest = $this->user_theme . '/tpl/' . $f;
217        } elseif ($type == 'po') {
218            $dest = $this->user_theme . '/locales/' . $f;
219        } else {
220            $dest = $this->user_theme . '/' . $f;
221        }
222
223        if (file_exists($dest) && is_writable($dest)) {
224            return $dest;
225        }
226
227        if ($type == 'tpl' && !is_dir(dirname($dest))) {
228            if (is_writable($this->user_theme)) {
229                return $dest;
230            }
231        }
232
233        if ($type == 'po' && !is_dir(dirname($dest))) {
234            if (is_writable($this->user_theme)) {
235                return $dest;
236            }
237        }
238
239        if (is_writable(dirname($dest))) {
240            return $dest;
241        }
242
243        return false;
244    }
245
246    protected function getFilesFromType($type)
247    {
248        switch ($type) {
249            case 'tpl':
250                return $this->tpl;
251            case 'css':
252                return $this->css;
253            case 'js':
254                return $this->js;
255            case 'po':
256                return $this->po;
257            default:
258                return [];
259        }
260    }
261
262    protected function updateFileInList($type, $f, $file)
263    {
264        switch ($type) {
265            case 'tpl':
266                $list = &$this->tpl;
267                break;
268            case 'css':
269                $list = &$this->css;
270                break;
271            case 'js':
272                $list = &$this->js;
273                break;
274            case 'po':
275                $list = &$this->po;
276                break;
277            default:
278                return;
279        }
280
281        $list[$f] = $file;
282    }
283
284    protected function findTemplates()
285    {
286        $this->tpl = array_merge(
287            $this->getFilesInDir($this->tplset_theme),
288            $this->getFilesInDir($this->parent_theme . '/tpl')
289        );
290        $this->tpl_model = $this->tpl;
291
292        $this->tpl = array_merge($this->tpl, $this->getFilesInDir($this->user_theme . '/tpl'));
293
294        # Then we look in 'default-templates' plugins directory
295        $plugins = $this->core->plugins->getModules();
296        foreach ($plugins as $p) {
297            // Looking in default-templates directory
298            $this->tpl       = array_merge($this->getFilesInDir($p['root'] . '/default-templates'), $this->tpl);
299            $this->tpl_model = array_merge($this->getFilesInDir($p['root'] . '/default-templates'), $this->tpl_model);
300            // Looking in default-templates/tplset directory
301            $this->tpl       = array_merge($this->getFilesInDir($p['root'] . '/default-templates/' . $this->tplset_name), $this->tpl);
302            $this->tpl_model = array_merge($this->getFilesInDir($p['root'] . '/default-templates/' . $this->tplset_name), $this->tpl_model);
303        }
304
305        uksort($this->tpl, [$this, 'sortFilesHelper']);
306    }
307
308    protected function findStyles()
309    {
310        $this->css = $this->getFilesInDir($this->user_theme, 'css');
311        $this->css = array_merge($this->css, $this->getFilesInDir($this->user_theme . '/style', 'css', 'style/'));
312        $this->css = array_merge($this->css, $this->getFilesInDir($this->user_theme . '/css', 'css', 'css/'));
313    }
314
315    protected function findScripts()
316    {
317        $this->js = $this->getFilesInDir($this->user_theme, 'js');
318        $this->js = array_merge($this->js, $this->getFilesInDir($this->user_theme . '/js', 'js', 'js/'));
319    }
320
321    protected function findLocales()
322    {
323        $langs = l10n::getISOcodes(1, 1);
324        foreach ($langs as $k => $v) {
325            if ($this->parent_theme) {
326                $this->po = array_merge($this->po, $this->getFilesInDir($this->parent_theme . '/locales/' . $v, 'po', $v . '/'));
327            }
328            $this->po = array_merge($this->po, $this->getFilesInDir($this->user_theme . '/locales/' . $v, 'po', $v . '/'));
329        }
330    }
331
332    protected function getFilesInDir($dir, $ext = null, $prefix = '', $model = null)
333    {
334        $dir = path::real($dir);
335        if (!$dir || !is_dir($dir) || !is_readable($dir)) {
336            return [];
337        }
338
339        $d   = dir($dir);
340        $res = [];
341        while (($f = $d->read()) !== false) {
342            if (is_file($dir . '/' . $f) && !preg_match('/^\./', $f) && (!$ext || preg_match('/\.' . preg_quote($ext) . '$/i', $f))) {
343                if (!$model || preg_match('/^' . preg_quote($model) . '$/i', $f)) {
344                    $res[$prefix . $f] = $dir . '/' . $f;
345                }
346            }
347        }
348
349        return $res;
350    }
351
352    protected function sortFilesHelper($a, $b)
353    {
354        if ($a == $b) {
355            return 0;
356        }
357
358        $ext_a = files::getExtension($a);
359        $ext_b = files::getExtension($b);
360
361        return strcmp($ext_a . '.' . $a, $ext_b . '.' . $b);
362    }
363}
Note: See TracBrowser for help on using the repository browser.

Sites map