X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=lib%2Ftheme.php;h=ef7290de2398ea2cdb973f3dea636f3831424a34;hb=fe6498e7c875f5b386a9c7d2cc1fba5677daae09;hp=a9d0cbc84d2f57802e7b23a790d6f805b2639b7c;hpb=640e7e7c43fa8e9b1a8516b486e560df84bd9887;p=quix0rs-gnu-social.git diff --git a/lib/theme.php b/lib/theme.php index a9d0cbc84d..ef7290de23 100644 --- a/lib/theme.php +++ b/lib/theme.php @@ -38,7 +38,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { * Themes are directories with some expected sub-directories and files * in them. They're found in either local/theme (for locally-installed themes) * or theme/ subdir of installation dir. - * + * * Note that the 'local' directory can be overridden as $config['local']['path'] * and $config['local']['dir'] etc. * @@ -51,11 +51,16 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ */ - class Theme { + const FALLBACK = 'neo'; + + var $name = null; var $dir = null; var $path = null; + protected $metadata = null; // access via getMetadata() lazy-loader + protected $externals = null; + protected $deps = null; /** * Constructor @@ -64,12 +69,16 @@ class Theme * * @param string $name Name of the theme; defaults to config value */ - function __construct($name=null) { if (empty($name)) { $name = common_config('site', 'theme'); } + if (!self::validName($name)) { + // TRANS: Server exception displayed if a theme name was invalid. + throw new ServerException(_('Invalid theme name.')); + } + $this->name = $name; // Check to see if it's in the local dir @@ -90,34 +99,77 @@ class Theme $fulldir = $instroot.'/'.$name; if (file_exists($fulldir) && is_dir($fulldir)) { - $this->dir = $fulldir; $this->path = $this->relativeThemePath('theme', 'theme', $name); + return; } + + // Ruh roh. Fall back to default, then. + + common_log(LOG_WARNING, sprintf("Unable to find theme '%s', falling back to default theme '%s'", + $name, + Theme::FALLBACK)); + + $this->name = Theme::FALLBACK; + $this->dir = $instroot.'/'.Theme::FALLBACK; + $this->path = $this->relativeThemePath('theme', 'theme', Theme::FALLBACK); + } /** * Build a full URL to the given theme's base directory, possibly * using an offsite theme server path. - * + * * @param string $group configuration section name to pull paths from * @param string $fallbackSubdir default subdirectory under INSTALLDIR * @param string $name theme name - * + * * @return string URL - * + * * @todo consolidate code with that for other customizable paths */ - protected function relativeThemePath($group, $fallbackSubdir, $name) { - $path = common_config($group, 'path'); + if (GNUsocial::isHTTPS()) { + $sslserver = common_config($group, 'sslserver'); + + if (empty($sslserver)) { + if (is_string(common_config('site', 'sslserver')) && + mb_strlen(common_config('site', 'sslserver')) > 0) { + $server = common_config('site', 'sslserver'); + } else if (common_config('site', 'server')) { + $server = common_config('site', 'server'); + } + $path = common_config('site', 'path') . '/'; + if ($fallbackSubdir) { + $path .= $fallbackSubdir . '/'; + } + } else { + $server = $sslserver; + $path = common_config($group, 'sslpath'); + if (empty($path)) { + $path = common_config($group, 'path'); + } + } - if (empty($path)) { - $path = common_config('site', 'path') . '/'; - if ($fallbackSubdir) { - $path .= $fallbackSubdir . '/'; + $protocol = 'https'; + } else { + $path = common_config($group, 'path'); + + if (empty($path)) { + $path = common_config('site', 'path') . '/'; + if ($fallbackSubdir) { + $path .= $fallbackSubdir . '/'; + } } + + $server = common_config($group, 'server'); + + if (empty($server)) { + $server = common_config('site', 'server'); + } + + $protocol = 'http'; } if ($path[strlen($path)-1] != '/') { @@ -128,27 +180,7 @@ class Theme $path = '/'.$path; } - $server = common_config($group, 'server'); - - if (empty($server)) { - $server = common_config('site', 'server'); - } - - $ssl = common_config($group, 'ssl'); - - if (is_null($ssl)) { // null -> guess - if (common_config('site', 'ssl') == 'always' && - !common_config($group, 'server')) { - $ssl = true; - } else { - $ssl = false; - } - } - - $protocol = ($ssl) ? 'https' : 'http'; - - $path = $protocol . '://'.$server.$path.$name; - return $path; + return $protocol.'://'.$server.$path.$name; } /** @@ -158,7 +190,6 @@ class Theme * * @return string full pathname, like /var/www/mublog/theme/default/logo.png */ - function getFile($relative) { return $this->dir.'/'.$relative; @@ -171,12 +202,106 @@ class Theme * * @return string full URL, like 'http://example.com/theme/default/logo.png' */ - function getPath($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() + { + if ($this->deps === null) { + $chain = $this->doGetDeps(array($this->name)); + array_pop($chain); // Drop us back off + $this->deps = $chain; + } + return $this->deps; + } + + 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() + { + if ($this->metadata == null) { + $this->metadata = $this->doGetMetadata(); + } + return $this->metadata; + } + + /** + * 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 + */ + private function doGetMetadata() + { + $iniFile = $this->getFile('theme.ini'); + if (file_exists($iniFile)) { + return parse_ini_file($iniFile); + } else { + return array(); + } + } + + /** + * Get list of any external URLs required by this theme and any + * dependencies. These are lazy-loaded from theme.ini. + * + * @return array of URL strings + */ + function getExternals() + { + if ($this->externals == null) { + $data = $this->getMetadata(); + if (!empty($data['external'])) { + $ext = (array)$data['external']; + } else { + $ext = array(); + } + + if (!empty($data['include'])) { + $theme = new Theme($data['include']); + $ext = array_merge($ext, $theme->getExternals()); + } + + $this->externals = array_unique($ext); + } + return $this->externals; + } + /** * Gets the full path of a file in a theme dir based on its relative name * @@ -185,7 +310,6 @@ class Theme * * @return string File path to the theme file */ - static function file($relative, $name=null) { $theme = new Theme($name); @@ -200,7 +324,6 @@ class Theme * * @return string URL of the file */ - static function path($relative, $name=null) { $theme = new Theme($name); @@ -212,7 +335,6 @@ class Theme * * @return array list of available theme names */ - static function listAvailable() { $local = self::subdirsOf(self::localRoot()); @@ -232,7 +354,6 @@ class Theme * * @return array relative filenames of subdirs, or empty array */ - protected static function subdirsOf($dir) { $subdirs = array(); @@ -257,7 +378,6 @@ class Theme * * @return string local root dir for themes */ - protected static function localRoot() { $basedir = common_config('local', 'dir'); @@ -274,7 +394,6 @@ class Theme * * @return string root dir for StatusNet themes */ - protected static function installRoot() { $instroot = common_config('theme', 'dir'); @@ -285,4 +404,9 @@ class Theme return $instroot; } + + static function validName($name) + { + return preg_match('/^[a-z0-9][a-z0-9_-]*$/i', $name); + } }