1<?php 2 3/** 4 * DokuWiki Plugin doxycode (Tagmanager Helper Component) 5 * 6 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 7 * @author Lukas Probsthain <lukas.probsthain@gmail.com> 8 */ 9 10use dokuwiki\Extension\Plugin; 11 12class helper_plugin_doxycode_tagmanager extends Plugin 13{ 14 private $tagfile_dir; // convenience variable for accessing the tag files 15 16 public function __construct() 17 { 18 $this->tagfile_dir = DOKU_PLUGIN . $this->getPluginName() . '/tagfiles/'; 19 } 20 21 /** 22 * List tag files in the tag file directory. 23 * 24 * Returns an array with file names (without extension) as keys and empty 25 * arrays as values. This ensures compatibility with the tag file configuration from loadTagFileConfig(). 26 * The list of tag files can then be merged with the tag file configuration. 27 * 28 * @return array associative array where the keys are the file names (without extension) of all XML files 29 * in the directory, and the values are empty arrays. 30 */ 31 public function listTagFiles() 32 { 33 // Find all XML files in the directory 34 $files = glob($this->tagfile_dir . '*.xml'); 35 36 // Array to hold file names without extension 37 $fileNames = []; 38 39 foreach ($files as $file) { 40 // Get the file name without extension 41 $fileNames[] = pathinfo($file, PATHINFO_FILENAME); 42 } 43 44 return array_fill_keys($fileNames, []); 45 } 46 47 public function getTagFileDir() 48 { 49 return $this->tagfile_dir; 50 } 51 52 53 /** 54 * The function `loadTagFileConfig()` reads and decodes the contents of a JSON file containing tagfile 55 * configuration, returning the decoded configuration array. 56 * 57 * @return array configuration array loaded from the tagconfig.json file. If the file does not exist or 58 * if there is an error reading or decoding the JSON content, an empty array is returned. 59 */ 60 public function loadTagFileConfig() 61 { 62 // /path/to/dokuwiki/lib/plugins/doxycode/tagfiles/ 63 64 $filename = $this->tagfile_dir . 'tagconfig.json'; 65 66 // Check if the file exists 67 if (!file_exists($filename)) { 68 // admin needs to update the tagfile configuration 69 return []; 70 } 71 72 // Read the contents of the file 73 $jsonContent = file_get_contents($filename); 74 if ($jsonContent === false) { 75 return []; 76 } 77 78 // Decode the JSON content 79 $config = json_decode($jsonContent, true); 80 if ($config === null) { 81 return []; 82 } 83 84 return $config; 85 } 86 87 /** 88 * The function checks if a directory exists and creates it if it doesn't. 89 * 90 * @return bool either the result of the `mkdir()` function if the directory does not exist and is 91 * successfully created, or `true` if the directory already exists. 92 */ 93 public function createTagFileDir() 94 { 95 if (!is_dir($this->tagfile_dir)) { 96 return mkdir($this->tagfile_dir); 97 } else { 98 return true; 99 } 100 } 101 102 /** 103 * Save the tag file configuration as json in the tag file directory. 104 * 105 * This function filters the relevant keys from the tag file configuration 106 * and saves all entries as a 'tagconfig.json' in the tag file directory. 107 * 108 * @param Array &$tag_config Array with tag file configuration entries. 109 * @param Bool $restore_mtime Restore the file modification time so 110 * that the cache files are not invalidated. Defaults to false. 111 */ 112 public function saveTagFileConfig(&$tag_config, $restore_mtime = false) 113 { 114 /** @var String[] $save_key_selection Configuration keys that are allowed in the stored configuration file. */ 115 $save_key_selection = [ 116 'remote_url', 117 'update_period', 118 'docu_url', 119 'enabled', 120 'last_update', 121 'force_runner', 122 'description']; 123 124 /** 125 * @var String[] Copied tag file configuration entries. 126 * 127 * We copy over the allowed configuration $key => $value pairs so the original configuration is not modified. 128 */ 129 $selected_config = []; 130 131 // create the tag file directory if not existent (might happen after installing the plugin) 132 $this->createTagFileDir(); 133 134 $config_filename = $this->tagfile_dir . 'tagconfig.json'; 135 136 // loop over all configuration entries 137 foreach ($tag_config as $name => $tag_conf) { 138 // loop over all keys in configuration 139 foreach ($tag_conf as $key => $value) { 140 if (in_array($key, $save_key_selection)) { 141 $selected_config[$name][$key] = $value; 142 } 143 } 144 } 145 146 // Convert the selected configuration to JSON 147 $jsonData = json_encode($selected_config, JSON_PRETTY_PRINT); 148 149 // save the mtime so we can restore it later 150 $original_mtime = filemtime($config_filename); 151 152 file_put_contents($config_filename, $jsonData); 153 154 // restore the mtime if we have an original mtime and restoring is enabled 155 if ($original_mtime !== false && $restore_mtime) { 156 touch($config_filename, $original_mtime); 157 } 158 } 159 160 /** 161 * Convert the internal tag file name to a full file path with extension. 162 * 163 * @param String $tag_name Internal tag file name 164 * @return String Full file path with extension for this tag file 165 */ 166 public function getFileName($tag_name) 167 { 168 return $this->tagfile_dir . $tag_name . '.xml'; 169 } 170 171 /** 172 * Load the configuration of tag files and optionally filter them by names. 173 * 174 * @param String|Array $tag_names Internal tag file names (without extension) for filtering the configuration 175 * @return Array Filtered tag file configuration 176 */ 177 public function getFilteredTagConfig($tag_names = null) 178 { 179 $tag_conf = $this->loadTagFileConfig(); 180 181 // filter out tag files 182 $tag_conf = $this->filterConfig($tag_conf, 'isConfigEnabled'); 183 184 185 if ($tag_names) { 186 // convert to array if only one tag_name was given 187 $tag_names = is_array($tag_names) ? $tag_names : [$tag_names]; 188 189 // filter tag_config by tag_names 190 $tag_conf = array_intersect_key($tag_conf, array_flip($tag_names)); 191 } 192 193 return $tag_conf; 194 } 195 196 /** 197 * Filter a tag file configuration array for entries that are enabled. 198 * 199 * @param Array &$tag_conf Array with tag file configuration entries. 200 * @return Array Array with enabled tag file configuration entries. 201 */ 202 public function filterConfig($tag_config, $filter, $inverse = false) 203 { 204 $filter = is_array($filter) ? $filter : [$filter]; 205 206 foreach ($filter as $function) { 207 if ($inverse) { 208 // Apply the inverse filter 209 $tag_config = array_filter($tag_config, function ($item) use ($function) { 210 return !$this->$function($item); 211 }); 212 } else { 213 // Apply the standard filter 214 $tag_config = array_filter($tag_config, array($this, $function)); 215 } 216 } 217 return $tag_config; 218 } 219 220 /** 221 * Check if a tag file configuration is enabled. 222 * 223 * Tag file configurations can be disabled through the admin interface. 224 * The parameters of the tag file (remote config, ...) will still be saved. 225 * But the tag file can't be used. 226 * 227 * This function is used in @see filterEnabledConfig to filter a tag file configuration array for 228 * entries that are enabled. 229 * 230 * @param Array &$tag_config Tag file configuration entry 231 * @return bool Is this tag file configuration enabled? 232 */ 233 public function isConfigEnabled(&$tag_config) 234 { 235 return boolval($tag_config['enabled']); 236 } 237 238 /** 239 * Check if a tag file configuration represents a remote tag File 240 * 241 * @param Array &$tag_config Tag file configuration entry 242 * @return bool Is this a remote tag file configuration? 243 */ 244 public function isValidRemoteConfig(&$tag_config) 245 { 246 247 // TODO: should we check if the URL contains a valid XML extension? 248 // TODO: should we also check if a valid period was set? 249 // otherwise we could simply fall back to the default update period in the task runner action 250 if (strlen($tag_config['remote_url']) > 0) { 251 return true; 252 } else { 253 return false; 254 } 255 } 256 257 /** 258 * Check if a tag file configuration has the force runner flag enabled. 259 * 260 * Some tag files are huge and cause long building times. 261 * We want to build the doxygen code snippet through the dokuwiki task runner in those cases. 262 * Otherwise the loading time of the page might exceed the maximum php execution time. 263 * This flag can be set through the admin interface. 264 * 265 * @param Array &$tag_config Tag file configuration entry 266 * @return bool Is this the force runner flag enabled? 267 */ 268 public function isForceRenderTaskSet(&$tag_config) 269 { 270 $force_render = false; 271 foreach ($tag_config as $key => $tag_conf) { 272 if ($tag_conf['force_runner']) { 273 $force_render = true; 274 break; 275 } 276 } 277 278 return $force_render; 279 } 280} 281