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