Seditio Source
Root |
./othercms/dotclear-2.22/plugins/themeEditor/class.themeEditor.php
<?php
/**
 * @brief themeEditor, a plugin for Dotclear 2
 *
 * @package Dotclear
 * @subpackage Plugins
 *
 * @copyright Olivier Meunier & Association Dotclear
 * @copyright GPL-2.0-only
 */
if (!defined('DC_RC_PATH')) {
    return;
}

class
dcThemeEditor
{
    protected
$core;

    protected
$user_theme;
    protected
$parent_theme;
    protected
$tplset_theme;

    protected
$parent_name;
    protected
$tplset_name;

    protected
$tpl_model;

    public
$tpl = [];
    public
$css = [];
    public
$js  = [];
    public
$po  = [];
    public
$php = [];

    public function
__construct($core)
    {
       
$this->core         = &$core;
       
$this->user_theme   = path::real($this->core->blog->themes_path . '/' . $this->core->blog->settings->system->theme);
       
$this->tplset_theme = DC_ROOT . '/inc/public/default-templates/' . DC_DEFAULT_TPLSET;
       
$this->tplset_name  = DC_DEFAULT_TPLSET;
        if (
null !== $this->core->themes) {
           
$parent_theme = $this->core->themes->moduleInfo($this->core->blog->settings->system->theme, 'parent');
            if (
$parent_theme) {
               
$this->parent_theme = path::real($this->core->blog->themes_path . '/' . $parent_theme);
               
$this->parent_name  = $parent_theme;
            }
           
$tplset = $this->core->themes->moduleInfo($this->core->blog->settings->system->theme, 'tplset');
            if (
$tplset) {
               
$this->tplset_theme = DC_ROOT . '/inc/public/default-templates/' . $tplset;
               
$this->tplset_name  = $tplset;
            }
        }
       
$this->findTemplates();
       
$this->findStyles();
       
$this->findScripts();
       
$this->findLocales();
       
$this->findCodes();
    }

    public function
filesList($type, $item = '%1$s', $split = true)
    {
       
$files = $this->getFilesFromType($type);

        if (empty(
$files)) {
            return
'<p>' . __('No file') . '</p>';
        }

       
$list = '';
        if (
$split) {
           
$list_theme  = ''; // Files from current theme
           
$list_parent = ''; // Files from parent of current theme
           
$list_tpl    = ''; // Files from template set used by current theme
           
foreach ($files as $k => $v) {
                if (
strpos($v, $this->user_theme) === 0) {
                   
$li = sprintf('<li class="default-file">%s</li>', $item);
                   
$list_theme .= sprintf($li, $k, html::escapeHTML($k));
                } elseif (
$this->parent_theme && strpos($v, $this->parent_theme) === 0) {
                   
$li = sprintf('<li class="parent-file">%s</li>', $item);
                   
$list_parent .= sprintf($li, $k, html::escapeHTML($k));
                } else {
                   
$li = sprintf('<li>%s</li>', $item);
                   
$list_tpl .= sprintf($li, $k, html::escapeHTML($k));
                }
            }
           
$list .= ($list_theme != '' ? sprintf('<li class="group-file">' . __('From theme:') . '<ul>%s</ul></li>', $list_theme) : '');
           
$list .= ($list_parent != '' ? sprintf(
               
'<li class="group-file">' . __('From parent:') . ' %s<ul>%s</ul></li>',
               
$this->parent_name,
               
$list_parent
           
) : '');
           
$list .= ($list_tpl != '' ? sprintf(
               
'<li class="group-file">' . __('From template set:') . ' %s<ul>%s</ul></li>',
               
$this->tplset_name,
               
$list_tpl
           
) : '');
        } else {
            foreach (
$files as $k => $v) {
                if (
strpos($v, $this->user_theme) === 0) {
                   
$li = sprintf('<li class="default-file">%s</li>', $item);
                } elseif (
$this->parent_theme && strpos($v, $this->parent_theme) === 0) {
                   
$li = sprintf('<li class="parent-file">%s</li>', $item);
                } else {
                   
$li = sprintf('<li>%s</li>', $item);
                }
               
$list .= sprintf($li, $k, html::escapeHTML($k));
            }
        }

        return
sprintf('<ul>%s</ul>', $list);
    }

    public function
getFileContent($type, $f)
    {
       
$files = $this->getFilesFromType($type);

        if (!isset(
$files[$f])) {
            throw new
Exception(__('File does not exist.'));
        }

       
$F = $files[$f];
        if (!
is_readable($F)) {
            throw new
Exception(sprintf(__('File %s is not readable'), $f));
        }

        return [
           
'c'    => file_get_contents($F),
           
'w'    => $this->getDestinationFile($type, $f) !== false,
           
'type' => $type,
           
'f'    => $f,
        ];
    }

    public function
writeFile($type, $f, $content)
    {
       
$files = $this->getFilesFromType($type);

        if (!isset(
$files[$f])) {
            throw new
Exception(__('File does not exist.'));
        }

        try {
           
$dest = $this->getDestinationFile($type, $f);

            if (
$dest == false) {
                throw new
Exception();
            }

            if (
$type == 'tpl' && !is_dir(dirname($dest))) {
               
files::makeDir(dirname($dest));
            }

            if (
$type == 'po' && !is_dir(dirname($dest))) {
               
files::makeDir(dirname($dest));
            }

           
$fp = @fopen($dest, 'wb');
            if (!
$fp) {
                throw new
Exception('tocatch');
            }

           
$content = preg_replace('/(\r?\n)/m', "\n", $content);
           
$content = preg_replace('/\r/m', "\n", $content);

           
fwrite($fp, $content);
           
fclose($fp);

           
# Updating inner files list
           
$this->updateFileInList($type, $f, $dest);
        } catch (
Exception $e) {
            throw new
Exception(sprintf(__('Unable to write file %s. Please check your theme files and folders permissions.'), $f));
        }
    }

    public function
deletableFile($type, $f)
    {
        if (
$type != 'tpl') {
           
// Only tpl files may be deleted
           
return false;
        }

       
$files = $this->getFilesFromType($type);
        if (isset(
$files[$f])) {
           
$dest = $this->getDestinationFile($type, $f);
            if (
$dest) {
                if (
file_exists($dest) && is_writable($dest)) {
                   
// Is there a model (parent theme or template set) ?
                   
if (isset($this->tpl_model[$f])) {
                        return
true;
                    }
                }
            }
        }

        return
false;
    }

    public function
deleteFile($type, $f)
    {
        if (
$type != 'tpl') {
           
// Only tpl files may be deleted
           
return;
        }

       
$files = $this->getFilesFromType($type);
        if (!isset(
$files[$f])) {
            throw new
Exception(__('File does not exist.'));
        }

        try {
           
$dest = $this->getDestinationFile($type, $f);
            if (
$dest) {
               
// File exists and may be deleted
               
unlink($dest);

               
// Updating template files list
               
$this->findTemplates();
            }
        } catch (
Exception $e) {
            throw new
Exception(sprintf(__('Unable to delete file %s. Please check your theme files and folders permissions.'), $f));
        }
    }

    protected function
getDestinationFile($type, $f)
    {
        if (
$type == 'tpl') {
           
$dest = $this->user_theme . '/tpl/' . $f;
        } elseif (
$type == 'po') {
           
$dest = $this->user_theme . '/locales/' . $f;
        } else {
           
$dest = $this->user_theme . '/' . $f;
        }

        if (
file_exists($dest) && is_writable($dest)) {
            return
$dest;
        }

        if (
$type == 'tpl' && !is_dir(dirname($dest))) {
            if (
is_writable($this->user_theme)) {
                return
$dest;
            }
        }

        if (
$type == 'po' && !is_dir(dirname($dest))) {
            if (
is_writable($this->user_theme)) {
                return
$dest;
            }
        }

        if (
is_writable(dirname($dest))) {
            return
$dest;
        }

        return
false;
    }

    protected function
getFilesFromType($type)
    {
        switch (
$type) {
            case
'tpl':
                return
$this->tpl;
            case
'css':
                return
$this->css;
            case
'js':
                return
$this->js;
            case
'po':
                return
$this->po;
            case
'php':
                return
$this->php;
            default:
                return [];
        }
    }

    protected function
updateFileInList($type, $f, $file)
    {
        switch (
$type) {
            case
'tpl':
               
$list = &$this->tpl;

                break;
            case
'css':
               
$list = &$this->css;

                break;
            case
'js':
               
$list = &$this->js;

                break;
            case
'po':
               
$list = &$this->po;

                break;
            case
'php':
               
$list = &$this->php;

                break;
            default:
                return;
        }

       
$list[$f] = $file;
    }

    protected function
findTemplates()
    {
       
$this->tpl = array_merge(
           
$this->getFilesInDir($this->tplset_theme),
           
$this->getFilesInDir($this->parent_theme . '/tpl')
        );
       
$this->tpl_model = $this->tpl;

       
$this->tpl = array_merge($this->tpl, $this->getFilesInDir($this->user_theme . '/tpl'));

       
# Then we look in 'default-templates' plugins directory
       
$plugins = $this->core->plugins->getModules();
        foreach (
$plugins as $p) {
           
// Looking in default-templates directory
           
$this->tpl       = array_merge($this->getFilesInDir($p['root'] . '/default-templates'), $this->tpl);
           
$this->tpl_model = array_merge($this->getFilesInDir($p['root'] . '/default-templates'), $this->tpl_model);
           
// Looking in default-templates/tplset directory
           
$this->tpl       = array_merge($this->getFilesInDir($p['root'] . '/default-templates/' . $this->tplset_name), $this->tpl);
           
$this->tpl_model = array_merge($this->getFilesInDir($p['root'] . '/default-templates/' . $this->tplset_name), $this->tpl_model);
        }

       
uksort($this->tpl, [$this, 'sortFilesHelper']);
    }

    protected function
findStyles()
    {
       
$this->css = $this->getFilesInDir($this->user_theme, 'css');
       
$this->css = array_merge($this->css, $this->getFilesInDir($this->user_theme . '/style', 'css', 'style/'));
       
$this->css = array_merge($this->css, $this->getFilesInDir($this->user_theme . '/css', 'css', 'css/'));
    }

    protected function
findScripts()
    {
       
$this->js = $this->getFilesInDir($this->user_theme, 'js');
       
$this->js = array_merge($this->js, $this->getFilesInDir($this->user_theme . '/js', 'js', 'js/'));
    }

    protected function
findLocales()
    {
       
$langs = l10n::getISOcodes(true, true);
        foreach (
$langs as $k => $v) {
            if (
$this->parent_theme) {
               
$this->po = array_merge($this->po, $this->getFilesInDir($this->parent_theme . '/locales/' . $v, 'po', $v . '/'));
            }
           
$this->po = array_merge($this->po, $this->getFilesInDir($this->user_theme . '/locales/' . $v, 'po', $v . '/'));
        }
    }

    protected function
findCodes()
    {
       
$this->php = $this->getFilesInDir($this->user_theme, 'php');
    }

    protected function
getFilesInDir($dir, $ext = null, $prefix = '', $model = null)
    {
       
$dir = path::real($dir);
        if (!
$dir || !is_dir($dir) || !is_readable($dir)) {
            return [];
        }

       
$d   = dir($dir);
       
$res = [];
        while ((
$f = $d->read()) !== false) {
            if (
is_file($dir . '/' . $f) && !preg_match('/^\./', $f) && (!$ext || preg_match('/\.' . preg_quote($ext) . '$/i', $f))) {
                if (!
$model || preg_match('/^' . preg_quote($model) . '$/i', $f)) {
                   
$res[$prefix . $f] = $dir . '/' . $f;
                }
            }
        }

        return
$res;
    }

    protected function
sortFilesHelper($a, $b)
    {
        if (
$a == $b) {
            return
0;
        }

       
$ext_a = files::getExtension($a);
       
$ext_b = files::getExtension($b);

        return
strcmp($ext_a . '.' . $a, $ext_b . '.' . $b);
    }
}