Add virtual instance theme feature see BT#12490

- New function Template::getThemeDir() added to located the theme folder
- New setting in vchamilo ThemeFolder (DB change below)
- New field in vchamilo table: css_theme_folder (ALTER TABLE vchamilo ADD COLUMN css_theme_folder varchar(255);)
- Rewrite api_get_themes() using Finder class, adding vchamilo css theme folder
- Fix mirror function adding 'override' option
pull/2487/head
jmontoyaa 8 years ago
parent a018bc60f1
commit b43c3d3627
  1. 32
      main/admin/settings.lib.php
  2. 52
      main/inc/lib/api.lib.php
  3. 70
      main/inc/lib/template.lib.php
  4. 1
      plugin/vchamilo/install.php
  5. 4
      plugin/vchamilo/lang/english.php
  6. 6
      plugin/vchamilo/lib/Virtual.php
  7. 8
      plugin/vchamilo/views/editinstance_form.php
  8. 5
      src/Chamilo/CoreBundle/Component/Utils/ChamiloApi.php

@ -349,8 +349,9 @@ function handleStylesheets()
$selected = $currentStyle = Security::remove_XSS($_POST['style']);
}
$dir = api_get_path(SYS_PUBLIC_PATH).'css/themes/' . $selected . '/images/';
$url = api_get_path(WEB_CSS_PATH).'themes/' . $selected . '/images/';
$themeDir = Template::getThemeDir($selected);
$dir = api_get_path(SYS_PUBLIC_PATH).'css/' . $themeDir . '/images/';
$url = api_get_path(WEB_CSS_PATH).'/' . $themeDir . '/images/';
$logoFileName = 'header-logo.png';
$newLogoFileName = 'header-logo-custom' . api_get_current_access_url_id() . '.png';
$webPlatformLogoPath = ChamiloApi::getWebPlatformLogoPath($selected);
@ -498,8 +499,13 @@ function uploadStylesheet($values, $picture)
$style_name = api_preg_replace('/[^A-Za-z0-9]/', '', $values['name_stylesheet']);
$cssToUpload = CSS_UPLOAD_PATH;
// Create the folder if needed.
// Check if a virtual instance vchamilo is used
$virtualInstanceTheme = api_get_configuration_value('virtual_css_theme_folder');
if (!empty($virtualInstanceTheme)) {
$cssToUpload = $cssToUpload.$virtualInstanceTheme.'/';
}
// Create the folder if needed.
if (!is_dir($cssToUpload.$style_name.'/')) {
mkdir($cssToUpload.$style_name.'/', api_get_permissions_for_new_directories());
}
@ -591,7 +597,12 @@ function uploadStylesheet($values, $picture)
if ($result) {
$fs = new Filesystem();
$fs->mirror($cssToUpload, api_get_path(SYS_PATH).'web/css/themes/');
$fs->mirror(
CSS_UPLOAD_PATH,
api_get_path(SYS_PATH).'web/css/themes/',
null,
['override' => true]
);
}
return $result;
@ -692,13 +703,9 @@ function storeStylesheets()
*/
function isStyle($style)
{
$dir = CSS_UPLOAD_PATH;
$dirs = scandir($dir);
$style = str_replace(array('/', '\\'), array('', ''), $style); // Avoid slashes or backslashes.
if (in_array($style, $dirs) && is_dir($dir.$style)) {
return true;
}
return false;
$themeList = api_get_themes();
return in_array($style, array_keys($themeList));
}
/**
@ -1701,7 +1708,8 @@ function showSearchToolsStatusTable()
function generateCSSDownloadLink($style)
{
$arch = api_get_path(SYS_ARCHIVE_PATH).$style.'.zip';
$dir = api_get_path(SYS_CSS_PATH).'themes/'.$style;
$themeDir = Template::getThemeDir($style);
$dir = api_get_path(SYS_CSS_PATH).$themeDir;
$check = Security::check_abs_path(
$dir,
api_get_path(SYS_CSS_PATH).'themes'

@ -4260,7 +4260,8 @@ function api_get_language_from_type($lang_type)
* @param int $languageId
* @return array
*/
function api_get_language_info($languageId) {
function api_get_language_info($languageId)
{
$language = Database::getManager()
->find('ChamiloCoreBundle:Language', intval($languageId));
@ -4282,7 +4283,7 @@ function api_get_language_info($languageId) {
/**
* Returns the name of the visual (CSS) theme to be applied on the current page.
* The returned name depends on the platform, course or user -wide settings.
* @return string The visual theme's name, it is the name of a folder inside .../chamilo/main/css/
* @return string The visual theme's name, it is the name of a folder inside web/css/themes
*/
function api_get_visual_theme()
{
@ -4348,32 +4349,41 @@ function api_get_visual_theme()
/**
* Returns a list of CSS themes currently available in the CSS folder
* @param bool $getOnlyThemeFromVirtualInstance Used by the vchamilo plugin
* @return array List of themes directories from the css folder
* Note: Directory names (names of themes) in the file system should contain ASCII-characters only.
*/
function api_get_themes()
function api_get_themes($getOnlyThemeFromVirtualInstance = false)
{
$cssdir = api_get_path(SYS_CSS_PATH) . 'themes/';
$list = [];
if (is_dir($cssdir)) {
$themes = @scandir($cssdir);
// This configuration value is set by the vchamilo plugin
$virtualTheme = api_get_configuration_value('virtual_css_theme_folder');
$readCssFolder = function ($dir) use ($virtualTheme) {
$finder = new \Symfony\Component\Finder\Finder();
$themes = $finder->directories()->in($dir)->depth(0)->sortByName();
$list = [];
/** @var Symfony\Component\Finder\SplFileInfo $theme */
foreach ($themes as $theme) {
$folder = $theme->getFilename();
$name = ucwords(str_replace('_', ' ', $folder));
if ($folder == $virtualTheme) {
continue;
}
$list[$folder] = $name;
}
return $list;
};
if (is_array($themes)) {
if ($themes !== false) {
sort($themes);
$dir = api_get_path(SYS_CSS_PATH).'themes/';
$list = $readCssFolder($dir);
foreach ($themes as & $theme) {
if (substr($theme, 0, 1) == '.') {
continue;
} else {
if (is_dir($cssdir.$theme)) {
$name = ucwords(str_replace('_', ' ', $theme));
$list[$theme] = $name;
}
}
}
}
if (!empty($virtualTheme)) {
$newList = $readCssFolder($dir.'/'.$virtualTheme);
if ($getOnlyThemeFromVirtualInstance) {
return $newList;
}
$list = $list + $newList;
asort($list);
}
return $list;

@ -22,6 +22,7 @@ class Template
* @var string
*/
public $theme = '';
private $themeDir;
/**
* @var string
@ -480,21 +481,42 @@ class Template
$this->assign('_u', $user_info);
}
/**
* Get theme dir
* @param string $theme
* @return string
*/
public static function getThemeDir($theme)
{
$themeDir = 'themes/' . $theme.'/';
$virtualTheme = api_get_configuration_value('virtual_css_theme_folder');
if (!empty($virtualTheme)) {
$virtualThemeList = api_get_themes(true);
$isVirtualTheme = in_array($theme, array_keys($virtualThemeList));
if ($isVirtualTheme) {
$themeDir = 'themes/' . $virtualTheme.'/'.$theme.'/';
}
}
return $themeDir;
}
/**
* Set system parameters
*/
private function set_system_parameters()
{
global $_configuration;
$this->theme = api_get_visual_theme();
//Setting app paths/URLs
$this->themeDir = self::getThemeDir($this->theme);
// Setting app paths/URLs
$_p = array(
'web' => api_get_path(WEB_PATH),
'web_relative' => api_get_path(REL_PATH),
'web_course' => api_get_path(WEB_COURSE_PATH),
'web_main' => api_get_path(WEB_CODE_PATH),
'web_css' => api_get_path(WEB_CSS_PATH),
'web_css_theme' => api_get_path(WEB_CSS_PATH) . 'themes/' . $this->theme . '/',
'web_css_theme' => api_get_path(WEB_CSS_PATH) . $this->themeDir,
'web_ajax' => api_get_path(WEB_AJAX_PATH),
'web_img' => api_get_path(WEB_IMG_PATH),
'web_plugin' => api_get_path(WEB_PLUGIN_PATH),
@ -507,10 +529,10 @@ class Template
);
$this->assign('_p', $_p);
//Here we can add system parameters that can be use in any template
// Here we can add system parameters that can be use in any template
$_s = array(
'software_name' => $_configuration['software_name'],
'system_version' => $_configuration['system_version'],
'software_name' => api_get_configuration_value('software_name'),
'system_version' => api_get_configuration_value('system_version'),
'site_name' => api_get_setting('siteName'),
'institution' => api_get_setting('Institution'),
'date' => api_format_date('now', DATE_FORMAT_LONG),
@ -529,7 +551,6 @@ class Template
{
global $disable_js_and_css_files;
$css = array();
$this->theme = api_get_visual_theme();
if (!empty($this->preview_theme)) {
@ -559,11 +580,7 @@ class Template
if (api_is_global_chat_enabled()) {
$css[] = api_get_path(WEB_LIBRARY_PATH) . 'javascript/chat/css/chat.css';
}
//THEME CSS STYLE
// $css[] = api_get_cdn_path(api_get_path(WEB_CSS_PATH).'responsive.css');
$css_file_to_string = null;
$css_file_to_string = '';
foreach ($css as $file) {
$css_file_to_string .= api_get_css($file);
}
@ -579,8 +596,8 @@ class Template
public function setCSSEditor()
{
$cssEditor = api_get_cdn_path(api_get_path(WEB_CSS_PATH).'editor.css');
if (is_file(api_get_path(SYS_CSS_PATH).'themes/'.$this->theme.'/editor.css')) {
$cssEditor = api_get_path(WEB_CSS_PATH).'themes/'.$this->theme.'/editor.css';
if (is_file(api_get_path(SYS_CSS_PATH).$this->themeDir.'editor.css')) {
$cssEditor = api_get_path(WEB_CSS_PATH).$this->themeDir.'editor.css';
}
$this->assign('cssEditor', $cssEditor);
@ -595,23 +612,22 @@ class Template
{
global $disable_js_and_css_files;
// Base CSS
$css[] = api_get_cdn_path(api_get_path(WEB_CSS_PATH).'base.css');
if ($this->show_learnpath) {
$css[] = api_get_cdn_path(api_get_path(WEB_CSS_PATH).'scorm.css');
if (is_file(api_get_path(SYS_CSS_PATH).'themes/'.$this->theme.'/learnpath.css')) {
$css[] = api_get_path(WEB_CSS_PATH).'themes/'.$this->theme.'/learnpath.css';
if (is_file(api_get_path(SYS_CSS_PATH).$this->themeDir.'learnpath.css')) {
$css[] = api_get_path(WEB_CSS_PATH).$this->themeDir.'learnpath.css';
}
}
if (is_file(api_get_path(SYS_CSS_PATH).'themes/'.$this->theme.'/editor.css')) {
$css[] = api_get_path(WEB_CSS_PATH).'themes/'.$this->theme.'/editor.css';
}else{
if (is_file(api_get_path(SYS_CSS_PATH).$this->themeDir.'editor.css')) {
$css[] = api_get_path(WEB_CSS_PATH).$this->themeDir.'editor.css';
} else {
$css[] = api_get_cdn_path(api_get_path(WEB_CSS_PATH).'editor.css');
}
$css[] = api_get_cdn_path(api_get_path(WEB_CSS_PATH).'themes/'.$this->theme.'/default.css');
$css[] = api_get_cdn_path(api_get_path(WEB_CSS_PATH).$this->themeDir.'default.css');
$css_file_to_string = null;
foreach ($css as $file) {
@ -642,8 +658,10 @@ class Template
$style_print = '';
if (is_readable(api_get_path(SYS_CSS_PATH).$this->theme.'/print.css')) {
$style_print = api_get_css(api_get_cdn_path(api_get_path(WEB_CSS_PATH) . $this->theme . '/print.css'),
'print');
$style_print = api_get_css(
api_get_cdn_path(api_get_path(WEB_CSS_PATH).$this->theme.'/print.css'),
'print'
);
}
$this->assign('css_style_print', $style_print);
}
@ -801,7 +819,7 @@ class Template
}
$this->assign(
'online_button',
'online_button',
Display::return_icon('statusonline.png', null, [], ICON_SIZE_ATOM)
);
$this->assign(
@ -869,11 +887,11 @@ class Template
$favico = '<link rel="shortcut icon" href="' . api_get_path(WEB_PATH) . 'favicon.ico" type="image/x-icon" />';
//Added to verify if in the current Chamilo Theme exist a favicon
$favicoThemeUrl = api_get_path(SYS_CSS_PATH) . 'themes/' . $this->theme . '/images/';
$favicoThemeUrl = api_get_path(SYS_CSS_PATH) . $this->themeDir . 'images/';
//If exist pick the current chamilo theme favicon
if (is_file($favicoThemeUrl . 'favicon.ico')) {
$favico = '<link rel="shortcut icon" href="' . api_get_path(WEB_CSS_PATH). 'themes/' . $this->theme . '/images/favicon.ico" type="image/x-icon" />';
$favico = '<link rel="shortcut icon" href="' . api_get_path(WEB_CSS_PATH). $this->themeDir . 'images/favicon.ico" type="image/x-icon" />';
}
if (api_is_multiple_url_enabled()) {

@ -42,6 +42,7 @@ $sql = "
home_url varchar(255),
upload_url varchar(255),
course_url varchar(255),
css_theme_folder varchar(255),
PRIMARY KEY (id)
) DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
";

@ -121,4 +121,8 @@ $strings['ArchiveUrl'] = 'Archive URL';
$strings['HomeUrl'] = 'Home URL';
$strings['UploadUrl'] = 'Upload URL';
$strings['CourseUrl'] = 'Course URL';
$strings['ThemeFolder'] = 'Theme folder';
$strings['ThemeFolderExplanation'] = 'Theme folder should be located inside the web/css/themes/ folder';

@ -55,7 +55,6 @@ class Virtual
$archivePath = '';
$uploadPath = '';
$passwordEncryption = '';
foreach ($virtualSettings as $setting) {
switch ($setting['variable']) {
case 'vchamilo_upload_real_root':
@ -110,7 +109,10 @@ class Virtual
// Instance cannot have multiple urls
$_configuration['multiple_access_urls'] = false;
$_configuration['virtual_css_theme_folder'] = '';
if (isset($data['css_theme_folder']) && !empty($data['css_theme_folder'])) {
$_configuration['virtual_css_theme_folder'] = $data['css_theme_folder'];
}
$virtualChamilo = $data;
} else {
exit("This portal is disabled. Please contact your administrator");

@ -418,6 +418,14 @@ class InstanceForm extends ChamiloForm
$form->addText('archive_url', $this->_plugin->get_lang('ArchiveUrl'));
$form->addText('home_url', $this->_plugin->get_lang('HomeUrl'));
$form->addText('upload_url', $this->_plugin->get_lang('UploadUrl'));
$form->addText(
'css_theme_folder',
[
$this->_plugin->get_lang('ThemeFolder'),
$this->_plugin->get_lang('ThemeFolderExplanation'),
],
false
);
//$form->addText('course_url', $this->_plugin->get_lang('CourseUrl'));
/**

@ -71,13 +71,14 @@ class ChamiloApi
{
$theme = empty($theme) ? api_get_visual_theme() : $theme;
$accessUrlId = api_get_current_access_url_id();
$customLogoPath = "themes/$theme/images/header-logo-custom$accessUrlId.png";
$themeDir = \Template::getThemeDir($theme);
$customLogoPath = "$themeDir/images/header-logo-custom$accessUrlId.png";
if (file_exists(api_get_path(SYS_PUBLIC_PATH) . "css/$customLogoPath")) {
return api_get_path(WEB_CSS_PATH) . $customLogoPath;
}
$originalLogoPath = "themes/$theme/images/header-logo.png";
$originalLogoPath = "$themeDir/images/header-logo.png";
if (file_exists(api_get_path(SYS_CSS_PATH) . $originalLogoPath)) {
return api_get_path(WEB_CSS_PATH) . $originalLogoPath;

Loading…
Cancel
Save