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