1<?php 2// (c) Copyright by authors of the Tiki Wiki CMS Groupware Project 3// 4// All Rights Reserved. See copyright.txt for details and a complete list of authors. 5// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details. 6// $Id$ 7 8//this script may only be included - so its better to die if called directly. 9if (strpos($_SERVER['SCRIPT_NAME'], basename(__FILE__)) !== false) { 10 header('location: index.php'); 11 exit; 12} 13 14class cssLib extends TikiLib 15{ 16 function list_layouts($theme = null, $theme_option = null) 17 { 18 global $prefs; 19 20 if (empty($theme) && empty($theme_option)) { // if you submit no parameters, return the current theme/theme option 21 if (isset($prefs['site_theme'])) { 22 $theme = $prefs['site_theme']; 23 } 24 if (isset($prefs['theme_option'])) { 25 $theme_option = $prefs['theme_option']; 26 } 27 } 28 29 $themelib = TikiLib::lib('theme'); 30 31 $available_layouts = []; 32 foreach (scandir(TIKI_PATH . '/templates/layouts/') as $layoutName) { 33 if ($layoutName[0] != '.' && $layoutName != 'index.php') { 34 $available_layouts[$layoutName] = ucfirst($layoutName); 35 } 36 } 37 foreach (\Tiki\Package\ExtensionManager::getPaths() as $path) { 38 if (file_exists($path . '/templates/layouts/')) { 39 foreach (scandir($path . '/templates/layouts/') as $layoutName) { 40 if ($layoutName[0] != '.' && $layoutName != 'index.php') { 41 $available_layouts[$layoutName] = ucfirst($layoutName); 42 } 43 } 44 } 45 } 46 47 $main_theme_path = $themelib->get_theme_path($theme, '', '', 'templates'); // path to the main site theme 48 49 if (file_exists(TIKI_PATH . "/" . $main_theme_path . '/layouts/')) { 50 foreach (scandir(TIKI_PATH . "/" . $main_theme_path . '/layouts/') as $layoutName) { 51 if ($layoutName[0] != '.' && $layoutName != 'index.php') { 52 $available_layouts[$layoutName] = ucfirst($layoutName); 53 } 54 } 55 } 56 57 if ($theme_option) { 58 $theme_path = $themelib->get_theme_path($theme, $theme_option, '', 'templates'); // path to the site theme options 59 60 if (file_exists(TIKI_PATH . "/" . $theme_path . '/layouts/')) { 61 foreach (scandir(TIKI_PATH . "/" . $theme_path . '/layouts/') as $layoutName) { 62 if ($layoutName[0] != '.' && $layoutName != 'index.php') { 63 $available_layouts[$layoutName] = ucfirst($layoutName); 64 } 65 } 66 } 67 } 68 return $available_layouts; 69 } 70 71 function list_user_selectable_layouts($theme = null, $theme_option = null) 72 { 73 global $prefs; 74 75 if (empty($theme) && empty($theme_option)) { // if you submit no parameters, return the current theme/theme option 76 if (isset($prefs['site_theme'])) { 77 $theme = $prefs['site_theme']; 78 } 79 if (isset($prefs['theme_option'])) { 80 $theme_option = $prefs['theme_option']; 81 } 82 } 83 84 $selectable_layouts = []; 85 $available_layouts = $this->list_layouts($theme, $theme_option); 86 87 foreach ($available_layouts as $layoutName => $layoutLabel) { 88 if ($layoutName == 'mobile' 89 || $layoutName == 'layout_plain.tpl' 90 || $layoutName == 'internal' 91 ) { 92 // hide layouts that are for internal use only 93 continue; 94 } elseif ($layoutName == 'basic') { 95 $selectable_layouts[$layoutName] = tra('Single Container'); 96 } elseif ($layoutName == 'classic') { 97 $selectable_layouts[$layoutName] = tra('Classic Tiki (3 containers - header, middle, footer)'); 98 } elseif ($layoutName == 'social') { 99 $selectable_layouts[$layoutName] = tra('Classic Bootstrap (fixed top navbar)'); 100 } else { 101 $selectable_layouts[$layoutName] = $layoutLabel; 102 } 103 } 104 105 return $selectable_layouts; 106 } 107 108 function list_css($path, $recursive = false) 109 { 110 $files = $this->list_files($path, '.css', $recursive); 111 foreach ($files as $i => $file) { 112 $files[$i] = preg_replace("|^$path/(.*)\.css$|", '$1', $file); 113 } 114 return $files; 115 } 116 117 function list_files($path, $extension, $recursive) 118 { 119 $back = []; 120 121 $handle = opendir($path); 122 123 while ($file = readdir($handle)) { 124 if ((substr($file, -4, 4) == $extension) and (preg_match('/^[-_a-zA-Z0-9\.]*$/', $file))) { 125 $back[] = "$path/$file"; 126 } elseif ($recursive 127 && $file != '.svn' 128 && $file != '.' 129 && $file != '..' 130 && is_dir("$path/$file") 131 && ! file_exists("db/$file/local.php") 132 ) { 133 $back = array_merge($back, $this->list_files("$path/$file", $extension, $recursive)); 134 } 135 } 136 closedir($handle); 137 sort($back); 138 return $back; 139 } 140 141 function browse_css($path) 142 { 143 if (! is_file($path)) { 144 return ['error' => "No such file : $path"]; 145 } 146 147 $meat = implode('', file($path)); 148 149 $find[0] = '/\}/'; 150 $repl[0] = "\n}\n"; 151 152 $find[1] = '/\{/'; 153 $repl[1] = "\n{\n"; 154 155 $find[2] = '/\/\*/'; 156 $repl[2] = "\n/*\n"; 157 158 $find[3] = '/\*\//'; 159 $repl[3] = "\n*/\n"; 160 161 $find[4] = '/;/'; 162 $repl[4] = ";\n"; 163 164 $find[5] = '/(W|w)hite/'; 165 $repl[5] = '#FFFFFF'; 166 167 $find[6] = '/(B|b)lack/'; 168 $repl[6] = '#000000'; 169 170 $res = preg_replace($find, $repl, $meat); 171 return [ 172 'error' => '', 173 'content' => explode("\n", $res) 174 ]; 175 } 176 177 function parse_css($data) 178 { 179 $back = []; 180 181 $index = 0; 182 $type = ''; 183 184 foreach ($data as $line) { 185 $line = trim($line); 186 187 if ($line) { 188 if (($type != 'comment') and ($line == '/*')) { 189 $type = 'comment'; 190 191 $index++; 192 $back["$index"]['comment'] = ''; 193 $back["$index"]['items'] = []; 194 $back["$index"]['attributes'] = []; 195 } elseif (($type == 'comment') and ($line == '*/')) { 196 $type = ''; 197 } elseif ($type == 'comment') { 198 $back["$index"]['comment'] .= "$line\n"; 199 } elseif (($type == 'items') and ($line == '{')) { 200 $type = 'attributes'; 201 } elseif ($type == 'items') { 202 $li = explode(',', $line); 203 204 foreach ($li as $l) { 205 $l = trim($l); 206 207 if ($l) { 208 $back["$index"]['items'][] = $l; 209 } 210 } 211 } elseif (($type == 'attributes') and ($line == '}')) { 212 $type = ''; 213 214 $index++; 215 $back["$index"]['comment'] = ''; 216 $back["$index"]['items'] = []; 217 $back["$index"]['attributes'] = []; 218 } elseif ($type == 'attributes') { 219 $parts = explode(':', str_replace(';', '', $line)); 220 221 if (isset($parts[0]) && isset($parts[1])) { 222 $obj = trim($parts[0]); 223 224 $back["$index"]['attributes']["$obj"] = trim($parts[1]); 225 } 226 } else { 227 $li = explode(',', $line); 228 229 foreach ($li as $l) { 230 $l = trim($l); 231 232 if ($l) { 233 $back["$index"]['items'][] = $l; 234 } 235 } 236 237 $type = 'items'; 238 } 239 240 $back['content'] = $line; 241 } 242 } 243 244 return $back; 245 } 246 247 /** 248 * Find the version of Tiki that a CSS is compatible with 249 * 250 * @TODO: cache the results 251 * @TODO: only read the first 30 lines or so of the file 252 */ 253 function version_css($path) 254 { 255 if (! file_exists($path)) { 256 return false; 257 } 258 259 $data = implode('', file($path)); 260 $pos = strpos($data, '@version'); 261 262 if ($pos === false) { 263 return false; 264 } 265 // get version 266 preg_match("/(@[V|v]ersion):?\s?([\d]+)\.([\d]+)/i", $data, $matches); 267 $version = $matches[2] . '.' . $matches[3]; 268 269 return $version; 270 } 271} 272