1<?php 2/** 3 * DokuWiki Plugin styling (Admin Component) 4 * 5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 6 * @author Andreas Gohr <andi@splitbrain.org> 7 */ 8class admin_plugin_styling extends DokuWiki_Admin_Plugin 9{ 10 11 public $ispopup = false; 12 13 /** 14 * @return int sort number in admin menu 15 */ 16 public function getMenuSort() 17 { 18 return 1000; 19 } 20 21 /** 22 * @return bool true if only access for superuser, false is for superusers and moderators 23 */ 24 public function forAdminOnly() 25 { 26 return true; 27 } 28 29 /** 30 * handle the different actions (also called from ajax) 31 */ 32 public function handle() 33 { 34 global $INPUT; 35 $run = $INPUT->extract('run')->str('run'); 36 if (!$run) return; 37 $run = 'run'.ucfirst($run); 38 $this->$run(); 39 } 40 41 /** 42 * Render HTML output, e.g. helpful text and a form 43 */ 44 public function html() 45 { 46 $class = 'nopopup'; 47 if ($this->ispopup) $class = 'ispopup page'; 48 49 echo '<div id="plugin__styling" class="'.$class.'">'; 50 ptln('<h1>'.$this->getLang('menu').'</h1>'); 51 $this->form(); 52 echo '</div>'; 53 } 54 55 /** 56 * Create the actual editing form 57 */ 58 public function form() 59 { 60 global $conf; 61 global $ID; 62 63 $styleUtil = new \dokuwiki\StyleUtils($conf['template'], true, true); 64 $styleini = $styleUtil->cssStyleini(); 65 $replacements = $styleini['replacements']; 66 67 if ($this->ispopup) { 68 $target = DOKU_BASE.'lib/plugins/styling/popup.php'; 69 } else { 70 $target = wl($ID, array('do' => 'admin', 'page' => 'styling')); 71 } 72 73 if (empty($replacements)) { 74 echo '<p class="error">'.$this->getLang('error').'</p>'; 75 } else { 76 echo $this->locale_xhtml('intro'); 77 78 echo '<form class="styling" method="post" action="'.$target.'">'; 79 80 echo '<table><tbody>'; 81 foreach ($replacements as $key => $value) { 82 $name = tpl_getLang($key); 83 if (empty($name)) $name = $this->getLang($key); 84 if (empty($name)) $name = $key; 85 86 echo '<tr>'; 87 echo '<td><label for="tpl__'.hsc($key).'">'.$name.'</label></td>'; 88 echo '<td><input type="'.$this->colorType($key).'" name="tpl['.hsc($key).']" id="tpl__'.hsc($key).'" 89 value="'.hsc($this->colorValue($value)).'" dir="ltr" /></td>'; 90 echo '</tr>'; 91 } 92 echo '</tbody></table>'; 93 94 echo '<p>'; 95 echo '<button type="submit" name="run[preview]" class="btn_preview primary">'. 96 $this->getLang('btn_preview').'</button> '; 97 #FIXME only if preview.ini exists: 98 echo '<button type="submit" name="run[reset]">'.$this->getLang('btn_reset').'</button>'; 99 echo '</p>'; 100 101 echo '<p>'; 102 echo '<button type="submit" name="run[save]" class="primary">'.$this->getLang('btn_save').'</button>'; 103 echo '</p>'; 104 105 echo '<p>'; 106 #FIXME only if local.ini exists: 107 echo '<button type="submit" name="run[revert]">'.$this->getLang('btn_revert').'</button>'; 108 echo '</p>'; 109 110 echo '</form>'; 111 112 echo tpl_locale_xhtml('style'); 113 } 114 } 115 116 /** 117 * Adjust three char color codes to the 6 char one supported by browser's color input 118 * 119 * @param string $value 120 * @return string 121 */ 122 protected function colorValue($value) 123 { 124 if (preg_match('/^#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])$/', $value, $match)) { 125 return '#' . $match[1] . $match[1] . $match[2] . $match[2] . $match[3] . $match[3]; 126 } 127 return $value; 128 } 129 130 /** 131 * Decide the input type based on the key name 132 * 133 * @param string $key 134 * @return string color|text 135 */ 136 protected function colorType($key) 137 { 138 static $colors = array( 139 'text', 140 'background', 141 'text_alt', 142 'background_alt', 143 'text_neu', 144 'background_neu', 145 'border', 146 'highlight', 147 'background_site', 148 'link', 149 'existing', 150 'missing', 151 ); 152 153 if (preg_match('/colou?r/', $key) || in_array(trim($key, '_'), $colors)) { 154 return 'color'; 155 } else { 156 return 'text'; 157 } 158 } 159 160 /** 161 * saves the preview.ini (alos called from ajax directly) 162 */ 163 public function runPreview() 164 { 165 global $conf; 166 $ini = $conf['cachedir'].'/preview.ini'; 167 io_saveFile($ini, $this->makeini()); 168 } 169 170 /** 171 * deletes the preview.ini 172 */ 173 protected function runReset() 174 { 175 global $conf; 176 $ini = $conf['cachedir'].'/preview.ini'; 177 io_saveFile($ini, ''); 178 } 179 180 /** 181 * deletes the local style.ini replacements 182 */ 183 protected function runRevert() 184 { 185 $this->replaceIni(''); 186 $this->runReset(); 187 } 188 189 /** 190 * save the local style.ini replacements 191 */ 192 protected function runSave() 193 { 194 $this->replaceIni($this->makeini()); 195 $this->runReset(); 196 } 197 198 /** 199 * create the replacement part of a style.ini from submitted data 200 * 201 * @return string 202 */ 203 protected function makeini() 204 { 205 global $INPUT; 206 207 $ini = "[replacements]\n"; 208 $ini .= ";These overwrites have been generated from the Template styling Admin interface\n"; 209 $ini .= ";Any values in this section will be overwritten by that tool again\n"; 210 foreach ($INPUT->arr('tpl') as $key => $val) { 211 $ini .= $key.' = "'.addslashes($val).'"'."\n"; 212 } 213 214 return $ini; 215 } 216 217 /** 218 * replaces the replacement parts in the local ini 219 * 220 * @param string $new the new ini contents 221 */ 222 protected function replaceIni($new) 223 { 224 global $conf; 225 $ini = DOKU_CONF."tpl/".$conf['template']."/style.ini"; 226 if (file_exists($ini)) { 227 $old = io_readFile($ini); 228 $old = preg_replace('/\[replacements\]\n.*?(\n\[.*]|$)/s', '\\1', $old); 229 $old = trim($old); 230 } else { 231 $old = ''; 232 } 233 234 io_makeFileDir($ini); 235 io_saveFile($ini, "$old\n\n$new"); 236 } 237} 238 239// vim:ts=4:sw=4:et: 240