Ticket #2638: allow themes to specify a base theme to load with 'include' setting in a theme.ini file
This commit is contained in:
parent
11f7fce3bb
commit
c24458a9f0
|
@ -200,7 +200,7 @@ class Action extends HTMLOutputter // lawsuit
|
||||||
|
|
||||||
if (Event::handle('StartShowStatusNetStyles', array($this)) &&
|
if (Event::handle('StartShowStatusNetStyles', array($this)) &&
|
||||||
Event::handle('StartShowLaconicaStyles', array($this))) {
|
Event::handle('StartShowLaconicaStyles', array($this))) {
|
||||||
$this->cssLink('css/display.css',null, 'screen, projection, tv, print');
|
$this->primaryCssLink(null, 'screen, projection, tv, print');
|
||||||
Event::handle('EndShowStatusNetStyles', array($this));
|
Event::handle('EndShowStatusNetStyles', array($this));
|
||||||
Event::handle('EndShowLaconicaStyles', array($this));
|
Event::handle('EndShowLaconicaStyles', array($this));
|
||||||
}
|
}
|
||||||
|
@ -248,6 +248,18 @@ class Action extends HTMLOutputter // lawsuit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function primaryCssLink($mainTheme=null, $media=null)
|
||||||
|
{
|
||||||
|
// If the currently-selected theme has dependencies on other themes,
|
||||||
|
// we'll need to load their display.css files as well in order.
|
||||||
|
$theme = new Theme($mainTheme);
|
||||||
|
$baseThemes = $theme->getDeps();
|
||||||
|
foreach ($baseThemes as $baseTheme) {
|
||||||
|
$this->cssLink('css/display.css', $baseTheme, $media);
|
||||||
|
}
|
||||||
|
$this->cssLink('css/display.css', $mainTheme, $media);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show javascript headers
|
* Show javascript headers
|
||||||
*
|
*
|
||||||
|
|
|
@ -54,6 +54,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
|
||||||
|
|
||||||
class Theme
|
class Theme
|
||||||
{
|
{
|
||||||
|
var $name = null;
|
||||||
var $dir = null;
|
var $dir = null;
|
||||||
var $path = null;
|
var $path = null;
|
||||||
|
|
||||||
|
@ -70,6 +71,10 @@ class Theme
|
||||||
if (empty($name)) {
|
if (empty($name)) {
|
||||||
$name = common_config('site', 'theme');
|
$name = common_config('site', 'theme');
|
||||||
}
|
}
|
||||||
|
if (!self::validName($name)) {
|
||||||
|
throw new ServerException("Invalid theme name.");
|
||||||
|
}
|
||||||
|
$this->name = $name;
|
||||||
|
|
||||||
// Check to see if it's in the local dir
|
// Check to see if it's in the local dir
|
||||||
|
|
||||||
|
@ -177,6 +182,58 @@ class Theme
|
||||||
return $this->path.'/'.$relative;
|
return $this->path.'/'.$relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch a list of other themes whose CSS needs to be pulled in before
|
||||||
|
* this theme's, based on following the theme.ini 'include' settings.
|
||||||
|
* (May be empty if this theme has no include dependencies.)
|
||||||
|
*
|
||||||
|
* @return array of strings with theme names
|
||||||
|
*/
|
||||||
|
function getDeps()
|
||||||
|
{
|
||||||
|
$chain = $this->doGetDeps(array($this->name));
|
||||||
|
array_pop($chain); // Drop us back off
|
||||||
|
return $chain;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function doGetDeps($chain)
|
||||||
|
{
|
||||||
|
$data = $this->getMetadata();
|
||||||
|
if (!empty($data['include'])) {
|
||||||
|
$include = $data['include'];
|
||||||
|
|
||||||
|
// Protect against cycles!
|
||||||
|
if (!in_array($include, $chain)) {
|
||||||
|
try {
|
||||||
|
$theme = new Theme($include);
|
||||||
|
array_unshift($chain, $include);
|
||||||
|
return $theme->doGetDeps($chain);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
common_log(LOG_ERR,
|
||||||
|
"Exception while fetching theme dependencies " .
|
||||||
|
"for $this->name: " . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $chain;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pull data from the theme's theme.ini file.
|
||||||
|
* @fixme calling getFile will fall back to default theme, this may be unsafe.
|
||||||
|
*
|
||||||
|
* @return associative array of strings
|
||||||
|
*/
|
||||||
|
function getMetadata()
|
||||||
|
{
|
||||||
|
$iniFile = $this->getFile('theme.ini');
|
||||||
|
if (file_exists($iniFile)) {
|
||||||
|
return parse_ini_file($iniFile);
|
||||||
|
} else {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the full path of a file in a theme dir based on its relative name
|
* Gets the full path of a file in a theme dir based on its relative name
|
||||||
*
|
*
|
||||||
|
@ -285,4 +342,9 @@ class Theme
|
||||||
|
|
||||||
return $instroot;
|
return $instroot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static function validName($name)
|
||||||
|
{
|
||||||
|
return preg_match('/^[a-z0-9][a-z0-9_-]*$/i', $name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -198,7 +198,7 @@ class ThemeUploader
|
||||||
protected function validateFile($filename, $ext)
|
protected function validateFile($filename, $ext)
|
||||||
{
|
{
|
||||||
$this->validateFileOrFolder($filename);
|
$this->validateFileOrFolder($filename);
|
||||||
$this->validateExtension($ext);
|
$this->validateExtension($filename, $ext);
|
||||||
// @fixme validate content
|
// @fixme validate content
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,13 +216,17 @@ class ThemeUploader
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function validateExtension($ext)
|
protected function validateExtension($base, $ext)
|
||||||
{
|
{
|
||||||
$allowed = array('css', // CSS may need validation
|
$allowed = array('css', // CSS may need validation
|
||||||
'png', 'gif', 'jpg', 'jpeg',
|
'png', 'gif', 'jpg', 'jpeg',
|
||||||
'svg', // SVG images/fonts may need validation
|
'svg', // SVG images/fonts may need validation
|
||||||
'ttf', 'eot', 'woff');
|
'ttf', 'eot', 'woff');
|
||||||
if (!in_array(strtolower($ext), $allowed)) {
|
if (!in_array(strtolower($ext), $allowed)) {
|
||||||
|
if ($ext == 'ini' && $base == 'theme') {
|
||||||
|
// theme.ini exception
|
||||||
|
return true;
|
||||||
|
}
|
||||||
$msg = sprintf(_("Theme contains file of type '.%s', " .
|
$msg = sprintf(_("Theme contains file of type '.%s', " .
|
||||||
"which is not allowed."),
|
"which is not allowed."),
|
||||||
$ext);
|
$ext);
|
||||||
|
|
|
@ -241,7 +241,7 @@ class MobileProfilePlugin extends WAP20Plugin
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$action->cssLink('css/display.css');
|
$action->primaryCssLink();
|
||||||
|
|
||||||
if (file_exists(Theme::file('css/mp-screen.css'))) {
|
if (file_exists(Theme::file('css/mp-screen.css'))) {
|
||||||
$action->cssLink('css/mp-screen.css', null, 'screen');
|
$action->cssLink('css/mp-screen.css', null, 'screen');
|
||||||
|
|
Loading…
Reference in New Issue
Block a user