|
<?php
|
|
|
|
namespace common\libraries;
|
|
|
|
/**
|
|
* Theme manager. Used to create, copy, update themes.
|
|
*
|
|
* To create a theme based on differences only:
|
|
*
|
|
* Create a "diff" theme containing only differences by calling create_empty_theme. Add differences to it - css, images, templates.
|
|
* Call make(base_theme, diff_theme, target_theme) where base theme is the base theme you want to copy, diff_theme is the theme that contains your differences and target_theme is the final them to use in Chamilo.
|
|
* Reaply make if base_theme or diff_them have changed.
|
|
*
|
|
* To update changes from a base theme to an exsiting theme.
|
|
*
|
|
* Call update(from_them, to_them)
|
|
*
|
|
* This will overwrite existing files based on the file change time stamp. Note that css files will not be merged! To do that create first a diff_theme containing differences and do a make.
|
|
*
|
|
* Note: at this point there is no differences between a diff theme and a normal theme.
|
|
* Creating diff theme is simply creating a theme that contains only differences from a base theme.
|
|
* As a result diff themes will be listed in the user interface and selected as the main theme. Which should not be done since they will not contain enough information.
|
|
*
|
|
* @copyright (c) 2011 University of Geneva
|
|
* @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
|
|
* @author laurent.opprecht@unige.ch
|
|
*/
|
|
class ThemeManager {
|
|
|
|
/**
|
|
* Return the list of resource types to copy from a theme to another. That is CSS, IMAGES and TEMPLATES.
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function get_resource_types() {
|
|
$result = array('css', 'images', 'templates');
|
|
return $result;
|
|
}
|
|
|
|
/*
|
|
* List of system themes. That is themes that are necessary for the system to work.
|
|
*/
|
|
public static function get_system_themes() {
|
|
$result = array('aqua');
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* List of existing themes.
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function get_themes() {
|
|
return Theme::get_themes();
|
|
}
|
|
|
|
/**
|
|
* Make $target_theme by copying $base_theme and adding the differences contained in $diff_theme.
|
|
* That is CSS files contained in $diff_theme are appended at the end. Taking precendence.
|
|
* Image and Template files contained in $diff_theme overwrite existing files.
|
|
*
|
|
* Note that files already present in $target_theme are deleted!
|
|
*
|
|
* @param string $base_theme
|
|
* @param string $diff_theme
|
|
* @param string $target_theme
|
|
*/
|
|
public static function make($base_theme, $diff_theme, $target_theme){
|
|
set_time_limit(60*5);
|
|
ThemeManager::delete($target_theme);
|
|
ThemeManager::update($base_theme, $target_theme);
|
|
ThemeManager::update($diff_theme, $target_theme, true, true);
|
|
}
|
|
|
|
/**
|
|
* Create an empty theme. That is the directory theme directory structure but with no file. Can be called several times.
|
|
*
|
|
* @param string $theme
|
|
* @param string $root
|
|
*/
|
|
public static function create_empty_theme($theme, $root = '') {
|
|
$root = $root ? $root : Path::get('SYS_PATH');
|
|
$files = Filesystem :: get_directory_content($root, Filesystem :: LIST_FILES_AND_DIRECTORIES, false);
|
|
foreach ($files as $file) {
|
|
$path = $root . '/' . $file;
|
|
if (StringUtilities::start_with($file, '.')) {
|
|
//do nothing those are sys files i.e. mercurial or apache, etc
|
|
} else if ($file == 'resources') {
|
|
$resource_types = self::get_resource_types();
|
|
foreach ($resource_types as $type) {
|
|
$resource_dir = $path . '/' . $type . '/' . $theme;
|
|
Filesystem::create_dir($resource_dir);
|
|
}
|
|
} else if (is_dir($path)) {
|
|
self::create_empty_theme($theme, $path);
|
|
} else {
|
|
//do nothing
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete a theme. Will not delete system themes.
|
|
* Wrapper function to hide the $root parameter.
|
|
*
|
|
* @param string $theme
|
|
* @param string $root
|
|
*/
|
|
public static function delete($theme) {
|
|
self::delete_exec($theme);
|
|
}
|
|
|
|
/**
|
|
* Copy files from FROM theme to TO theme. Create TO theme if it doesn't exist.
|
|
*
|
|
* @param string $from_theme The theme to copy resources from
|
|
* @param string $to_theme The theme to copy resources to
|
|
* @param bool $merge If true attemp to merge the FROM files with the TO files. That is for css append the css at the end of the css if it exists.
|
|
* @param string $force_overwrite If true overwrite existing files. By default overwite older files with new ones based on the "change" file timestamp.
|
|
* @param string $root root directory to update from. Leave blank to update everything.
|
|
*/
|
|
public static function update($from_theme, $to_theme, $merge = false, $force_overwrite = false, $root = '') {
|
|
$root = $root ? $root : Path::get('SYS_PATH');
|
|
$files = Filesystem :: get_directory_content($root, Filesystem :: LIST_FILES_AND_DIRECTORIES, false);
|
|
foreach ($files as $file) {
|
|
$path = $root . '/' . $file;
|
|
if ($comp = StringUtilities::start_with($file, '.')) {
|
|
//do nothing those are sys files i.e. mercurial or apache, etc
|
|
} else if ($file == 'resources') {
|
|
$resource_types = self::get_resource_types();
|
|
foreach ($resource_types as $type) {
|
|
$f = $path . '/' . $type . '/' . $from_theme;
|
|
$t = $path . '/' . $type . '/' . $to_theme;
|
|
self::copy_ressources($f, $t, $type, $merge, $force_overwrite);
|
|
}
|
|
} else if (is_dir($path)) {
|
|
self::update($from_theme, $to_theme, $merge, $force_overwrite, $path);
|
|
} else {
|
|
//do nothing
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete a theme. Will not delete system themes.
|
|
*
|
|
* @param string $theme
|
|
* @param string $root
|
|
*/
|
|
private static function delete_exec($theme, $root = '') {
|
|
|
|
//protection against possible attacks
|
|
$theme = str_replace('/', '', $theme);
|
|
$theme = str_replace('\\', '', $theme);
|
|
|
|
//protection, system themes which are necessary for the system to work should not be deletable
|
|
$system_themes = self::get_system_themes();
|
|
foreach ($system_themes as $system_theme) {
|
|
if (strtolower($system_theme) == $theme) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
$root = $root ? $root : Path::get('SYS_PATH');
|
|
|
|
$files = Filesystem :: get_directory_content($root, Filesystem :: LIST_FILES_AND_DIRECTORIES, false);
|
|
foreach ($files as $file) {
|
|
$path = $root . '/' . $file;
|
|
if (StringUtilities::start_with($file, '.')) {
|
|
//do nothing those are sys files i.e. mercurial or apache, etc
|
|
} else if ($file == 'resources') {
|
|
$resource_types = self::get_resource_types();
|
|
foreach ($resource_types as $type) {
|
|
$resource_dir = $path . '/' . $type . '/' . $theme;
|
|
Filesystem::remove($resource_dir);
|
|
}
|
|
} else if (is_dir($path)) {
|
|
self::delete_exec($theme, $path);
|
|
} else {
|
|
//do nothing
|
|
}
|
|
}
|
|
}
|
|
|
|
private static function copy_ressources($from, $to, $type, $merge, $force_overwrite) {
|
|
self::recurse_copy($from, $to, $type, $merge, $force_overwrite);
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
private static function recurse_copy($source, $destination, $type, $merge, $force_overwrite) {
|
|
if (!is_dir($source)) {
|
|
return self :: copy_resource($source, $destination, $type, $merge, $force_overwrite);
|
|
}
|
|
$result = true;
|
|
|
|
$content = Filesystem :: get_directory_content($source, Filesystem :: LIST_FILES_AND_DIRECTORIES, false);
|
|
foreach ($content as $file) {
|
|
$path_to_file = $source . '/' . $file;
|
|
$path_to_new_file = $destination . '/' . $file;
|
|
if (!is_dir($path_to_file)) {
|
|
$result &= self :: copy_resource($path_to_file, $path_to_new_file, $type, $merge, $force_overwrite);
|
|
} else {
|
|
Filesystem :: create_dir($path_to_new_file);
|
|
$result &= self :: recurse_copy($path_to_file, $path_to_new_file, $type, $merge, $force_overwrite);
|
|
}
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Copy file to destination if souce is newer OR we do a force overwrite. I.e. we don't ovewrite changes.
|
|
*/
|
|
private static function copy_resource($source, $destination, $type, $merge, $force_overwrite) {
|
|
$exists = file_exists($destination);
|
|
if ($exists && $merge && $type == 'css') {
|
|
$data = "\n" . file_get_contents($source);
|
|
return file_put_contents($destination, $data, FILE_APPEND);
|
|
} else if ($exists && !$force_overwrite) {
|
|
$d_time = filectime($destination);
|
|
$s_time = filectime($source);
|
|
if ($s_time < $d_time) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
$destination_dir = dirname($destination);
|
|
if (file_exists($source) && Filesystem :: create_dir($destination_dir)) {
|
|
copy($source, $destination);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
?>
|