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