1e1d9dcc8SAndreas Gohr<?php 2e1d9dcc8SAndreas Gohr 3e1d9dcc8SAndreas Gohrnamespace dokuwiki\Extension; 4e1d9dcc8SAndreas Gohr 5*3d041397SAndreas Gohruse dokuwiki\Logger; 6*3d041397SAndreas Gohr 7e1d9dcc8SAndreas Gohr/** 8e1d9dcc8SAndreas Gohr * Provides standard DokuWiki plugin behaviour 9e1d9dcc8SAndreas Gohr */ 10e1d9dcc8SAndreas Gohrtrait PluginTrait 11e1d9dcc8SAndreas Gohr{ 12e1d9dcc8SAndreas Gohr protected $localised = false; // set to true by setupLocale() after loading language dependent strings 131490c177SAndreas Gohr protected $lang = []; // array to hold language dependent strings, best accessed via ->getLang() 14e1d9dcc8SAndreas Gohr protected $configloaded = false; // set to true by loadConfig() after loading plugin configuration variables 151490c177SAndreas Gohr protected $conf = []; // array to hold plugin settings, best accessed via ->getConf() 16e1d9dcc8SAndreas Gohr 17e1d9dcc8SAndreas Gohr /** 18e1d9dcc8SAndreas Gohr * @see PluginInterface::getInfo() 19e1d9dcc8SAndreas Gohr */ 20e1d9dcc8SAndreas Gohr public function getInfo() 21e1d9dcc8SAndreas Gohr { 22*3d041397SAndreas Gohr $class = get_class($this); 23*3d041397SAndreas Gohr $parts = sexplode('_', $class, 3); 24*3d041397SAndreas Gohr $ext = $parts[2]; 25e1d9dcc8SAndreas Gohr 26*3d041397SAndreas Gohr if (empty($ext)) { 27*3d041397SAndreas Gohr throw new \RuntimeException('Class does not follow the plugin naming convention'); 28*3d041397SAndreas Gohr } 29*3d041397SAndreas Gohr 30*3d041397SAndreas Gohr $base = [ 31*3d041397SAndreas Gohr 'base' => $ext, 32*3d041397SAndreas Gohr 'author' => 'Unknown', 33*3d041397SAndreas Gohr 'email' => 'unknown@example.com', 34e1d9dcc8SAndreas Gohr 'date' => '0000-00-00', 35*3d041397SAndreas Gohr 'name' => $ext . ' plugin', 36*3d041397SAndreas Gohr 'desc' => 'Unknown purpose - bad plugin.info.txt', 37*3d041397SAndreas Gohr 'url' => 'https://www.dokuwiki.org/plugins/' . $ext, 381490c177SAndreas Gohr ]; 39*3d041397SAndreas Gohr 40*3d041397SAndreas Gohr $file = DOKU_PLUGIN . '/' . $ext . '/plugin.info.txt'; 41*3d041397SAndreas Gohr if (file_exists($file)) { 42*3d041397SAndreas Gohr $raw = confToHash($file); 43*3d041397SAndreas Gohr 44*3d041397SAndreas Gohr // check if all required fields are present 45*3d041397SAndreas Gohr $msg = 'Extension %s does not provide a valid %s in %s'; 46*3d041397SAndreas Gohr foreach (array_keys($base) as $line) { 47*3d041397SAndreas Gohr if (empty($raw[$line])) Logger::error(sprintf($msg, [$ext, $line, $file])); 48*3d041397SAndreas Gohr } 49*3d041397SAndreas Gohr 50*3d041397SAndreas Gohr return array_merge($base, $raw); 51*3d041397SAndreas Gohr } 52*3d041397SAndreas Gohr 53*3d041397SAndreas Gohr Logger::error(sprintf('Extension %s does not provide a plugin.info.txt in %s', $ext, $file)); 54*3d041397SAndreas Gohr return $base; 55e1d9dcc8SAndreas Gohr } 56e1d9dcc8SAndreas Gohr 57e1d9dcc8SAndreas Gohr /** 58e1d9dcc8SAndreas Gohr * @see PluginInterface::isSingleton() 59e1d9dcc8SAndreas Gohr */ 60e1d9dcc8SAndreas Gohr public function isSingleton() 61e1d9dcc8SAndreas Gohr { 62e1d9dcc8SAndreas Gohr return true; 63e1d9dcc8SAndreas Gohr } 64e1d9dcc8SAndreas Gohr 65e1d9dcc8SAndreas Gohr /** 66e1d9dcc8SAndreas Gohr * @see PluginInterface::loadHelper() 67e1d9dcc8SAndreas Gohr */ 68e1d9dcc8SAndreas Gohr public function loadHelper($name, $msg = true) 69e1d9dcc8SAndreas Gohr { 70e1d9dcc8SAndreas Gohr $obj = plugin_load('helper', $name); 71e1d9dcc8SAndreas Gohr if (is_null($obj) && $msg) msg("Helper plugin $name is not available or invalid.", -1); 72e1d9dcc8SAndreas Gohr return $obj; 73e1d9dcc8SAndreas Gohr } 74e1d9dcc8SAndreas Gohr 75e1d9dcc8SAndreas Gohr // region introspection methods 76e1d9dcc8SAndreas Gohr 77e1d9dcc8SAndreas Gohr /** 78e1d9dcc8SAndreas Gohr * @see PluginInterface::getPluginType() 79e1d9dcc8SAndreas Gohr */ 80e1d9dcc8SAndreas Gohr public function getPluginType() 81e1d9dcc8SAndreas Gohr { 821490c177SAndreas Gohr [$t] = explode('_', get_class($this), 2); 83e1d9dcc8SAndreas Gohr return $t; 84e1d9dcc8SAndreas Gohr } 85e1d9dcc8SAndreas Gohr 86e1d9dcc8SAndreas Gohr /** 87e1d9dcc8SAndreas Gohr * @see PluginInterface::getPluginName() 88e1d9dcc8SAndreas Gohr */ 89e1d9dcc8SAndreas Gohr public function getPluginName() 90e1d9dcc8SAndreas Gohr { 91a19c9aa0SGerrit Uitslag [/* t */, /* p */, $n] = sexplode('_', get_class($this), 4, ''); 92e1d9dcc8SAndreas Gohr return $n; 93e1d9dcc8SAndreas Gohr } 94e1d9dcc8SAndreas Gohr 95e1d9dcc8SAndreas Gohr /** 96e1d9dcc8SAndreas Gohr * @see PluginInterface::getPluginComponent() 97e1d9dcc8SAndreas Gohr */ 98e1d9dcc8SAndreas Gohr public function getPluginComponent() 99e1d9dcc8SAndreas Gohr { 100a19c9aa0SGerrit Uitslag [/* t */, /* p */, /* n */, $c] = sexplode('_', get_class($this), 4, ''); 101ec34bb30SAndreas Gohr return $c; 102e1d9dcc8SAndreas Gohr } 103e1d9dcc8SAndreas Gohr 104e1d9dcc8SAndreas Gohr // endregion 105e1d9dcc8SAndreas Gohr // region localization methods 106e1d9dcc8SAndreas Gohr 107e1d9dcc8SAndreas Gohr /** 108e1d9dcc8SAndreas Gohr * @see PluginInterface::getLang() 109e1d9dcc8SAndreas Gohr */ 110e1d9dcc8SAndreas Gohr public function getLang($id) 111e1d9dcc8SAndreas Gohr { 112e1d9dcc8SAndreas Gohr if (!$this->localised) $this->setupLocale(); 113e1d9dcc8SAndreas Gohr 1141490c177SAndreas Gohr return ($this->lang[$id] ?? ''); 115e1d9dcc8SAndreas Gohr } 116e1d9dcc8SAndreas Gohr 117e1d9dcc8SAndreas Gohr /** 118e1d9dcc8SAndreas Gohr * @see PluginInterface::locale_xhtml() 119e1d9dcc8SAndreas Gohr */ 120e1d9dcc8SAndreas Gohr public function locale_xhtml($id) 121e1d9dcc8SAndreas Gohr { 122e1d9dcc8SAndreas Gohr return p_cached_output($this->localFN($id)); 123e1d9dcc8SAndreas Gohr } 124e1d9dcc8SAndreas Gohr 125e1d9dcc8SAndreas Gohr /** 126e1d9dcc8SAndreas Gohr * @see PluginInterface::localFN() 127e1d9dcc8SAndreas Gohr */ 128e1d9dcc8SAndreas Gohr public function localFN($id, $ext = 'txt') 129e1d9dcc8SAndreas Gohr { 130e1d9dcc8SAndreas Gohr global $conf; 131e1d9dcc8SAndreas Gohr $plugin = $this->getPluginName(); 132e1d9dcc8SAndreas Gohr $file = DOKU_CONF . 'plugin_lang/' . $plugin . '/' . $conf['lang'] . '/' . $id . '.' . $ext; 133e1d9dcc8SAndreas Gohr if (!file_exists($file)) { 134e1d9dcc8SAndreas Gohr $file = DOKU_PLUGIN . $plugin . '/lang/' . $conf['lang'] . '/' . $id . '.' . $ext; 135e1d9dcc8SAndreas Gohr if (!file_exists($file)) { 136e1d9dcc8SAndreas Gohr //fall back to english 137e1d9dcc8SAndreas Gohr $file = DOKU_PLUGIN . $plugin . '/lang/en/' . $id . '.' . $ext; 138e1d9dcc8SAndreas Gohr } 139e1d9dcc8SAndreas Gohr } 140e1d9dcc8SAndreas Gohr return $file; 141e1d9dcc8SAndreas Gohr } 142e1d9dcc8SAndreas Gohr 143e1d9dcc8SAndreas Gohr /** 144e1d9dcc8SAndreas Gohr * @see PluginInterface::setupLocale() 145e1d9dcc8SAndreas Gohr */ 146e1d9dcc8SAndreas Gohr public function setupLocale() 147e1d9dcc8SAndreas Gohr { 148e1d9dcc8SAndreas Gohr if ($this->localised) return; 149e1d9dcc8SAndreas Gohr 150e1d9dcc8SAndreas Gohr global $conf, $config_cascade; // definitely don't invoke "global $lang" 151e1d9dcc8SAndreas Gohr $path = DOKU_PLUGIN . $this->getPluginName() . '/lang/'; 152e1d9dcc8SAndreas Gohr 1531490c177SAndreas Gohr $lang = []; 154e1d9dcc8SAndreas Gohr 155e1d9dcc8SAndreas Gohr // don't include once, in case several plugin components require the same language file 156e1d9dcc8SAndreas Gohr @include($path . 'en/lang.php'); 157e1d9dcc8SAndreas Gohr foreach ($config_cascade['lang']['plugin'] as $config_file) { 158e1d9dcc8SAndreas Gohr if (file_exists($config_file . $this->getPluginName() . '/en/lang.php')) { 159e1d9dcc8SAndreas Gohr include($config_file . $this->getPluginName() . '/en/lang.php'); 160e1d9dcc8SAndreas Gohr } 161e1d9dcc8SAndreas Gohr } 162e1d9dcc8SAndreas Gohr 163e1d9dcc8SAndreas Gohr if ($conf['lang'] != 'en') { 164e1d9dcc8SAndreas Gohr @include($path . $conf['lang'] . '/lang.php'); 165e1d9dcc8SAndreas Gohr foreach ($config_cascade['lang']['plugin'] as $config_file) { 166e1d9dcc8SAndreas Gohr if (file_exists($config_file . $this->getPluginName() . '/' . $conf['lang'] . '/lang.php')) { 167e1d9dcc8SAndreas Gohr include($config_file . $this->getPluginName() . '/' . $conf['lang'] . '/lang.php'); 168e1d9dcc8SAndreas Gohr } 169e1d9dcc8SAndreas Gohr } 170e1d9dcc8SAndreas Gohr } 171e1d9dcc8SAndreas Gohr 172e1d9dcc8SAndreas Gohr $this->lang = $lang; 173e1d9dcc8SAndreas Gohr $this->localised = true; 174e1d9dcc8SAndreas Gohr } 175e1d9dcc8SAndreas Gohr 176e1d9dcc8SAndreas Gohr // endregion 177e1d9dcc8SAndreas Gohr // region configuration methods 178e1d9dcc8SAndreas Gohr 179e1d9dcc8SAndreas Gohr /** 180e1d9dcc8SAndreas Gohr * @see PluginInterface::getConf() 181e1d9dcc8SAndreas Gohr */ 182e1d9dcc8SAndreas Gohr public function getConf($setting, $notset = false) 183e1d9dcc8SAndreas Gohr { 184e1d9dcc8SAndreas Gohr 185e1d9dcc8SAndreas Gohr if (!$this->configloaded) { 186e1d9dcc8SAndreas Gohr $this->loadConfig(); 187e1d9dcc8SAndreas Gohr } 188e1d9dcc8SAndreas Gohr 189e1d9dcc8SAndreas Gohr if (isset($this->conf[$setting])) { 190e1d9dcc8SAndreas Gohr return $this->conf[$setting]; 191e1d9dcc8SAndreas Gohr } else { 192e1d9dcc8SAndreas Gohr return $notset; 193e1d9dcc8SAndreas Gohr } 194e1d9dcc8SAndreas Gohr } 195e1d9dcc8SAndreas Gohr 196e1d9dcc8SAndreas Gohr /** 197e1d9dcc8SAndreas Gohr * @see PluginInterface::loadConfig() 198e1d9dcc8SAndreas Gohr */ 199e1d9dcc8SAndreas Gohr public function loadConfig() 200e1d9dcc8SAndreas Gohr { 201e1d9dcc8SAndreas Gohr global $conf; 202e1d9dcc8SAndreas Gohr 203e1d9dcc8SAndreas Gohr $defaults = $this->readDefaultSettings(); 204e1d9dcc8SAndreas Gohr $plugin = $this->getPluginName(); 205e1d9dcc8SAndreas Gohr 206e1d9dcc8SAndreas Gohr foreach ($defaults as $key => $value) { 207e1d9dcc8SAndreas Gohr if (isset($conf['plugin'][$plugin][$key])) continue; 208e1d9dcc8SAndreas Gohr $conf['plugin'][$plugin][$key] = $value; 209e1d9dcc8SAndreas Gohr } 210e1d9dcc8SAndreas Gohr 211e1d9dcc8SAndreas Gohr $this->configloaded = true; 212e1d9dcc8SAndreas Gohr $this->conf =& $conf['plugin'][$plugin]; 213e1d9dcc8SAndreas Gohr } 214e1d9dcc8SAndreas Gohr 215e1d9dcc8SAndreas Gohr /** 216e1d9dcc8SAndreas Gohr * read the plugin's default configuration settings from conf/default.php 217e1d9dcc8SAndreas Gohr * this function is automatically called through getConf() 218e1d9dcc8SAndreas Gohr * 219e1d9dcc8SAndreas Gohr * @return array setting => value 220e1d9dcc8SAndreas Gohr */ 221e1d9dcc8SAndreas Gohr protected function readDefaultSettings() 222e1d9dcc8SAndreas Gohr { 223e1d9dcc8SAndreas Gohr 224e1d9dcc8SAndreas Gohr $path = DOKU_PLUGIN . $this->getPluginName() . '/conf/'; 2251490c177SAndreas Gohr $conf = []; 226e1d9dcc8SAndreas Gohr 227e1d9dcc8SAndreas Gohr if (file_exists($path . 'default.php')) { 228e1d9dcc8SAndreas Gohr include($path . 'default.php'); 229e1d9dcc8SAndreas Gohr } 230e1d9dcc8SAndreas Gohr 231e1d9dcc8SAndreas Gohr return $conf; 232e1d9dcc8SAndreas Gohr } 233e1d9dcc8SAndreas Gohr 234e1d9dcc8SAndreas Gohr // endregion 235e1d9dcc8SAndreas Gohr // region output methods 236e1d9dcc8SAndreas Gohr 237e1d9dcc8SAndreas Gohr /** 238e1d9dcc8SAndreas Gohr * @see PluginInterface::email() 239e1d9dcc8SAndreas Gohr */ 240e1d9dcc8SAndreas Gohr public function email($email, $name = '', $class = '', $more = '') 241e1d9dcc8SAndreas Gohr { 242e1d9dcc8SAndreas Gohr if (!$email) return $name; 243e1d9dcc8SAndreas Gohr $email = obfuscate($email); 244e1d9dcc8SAndreas Gohr if (!$name) $name = $email; 2451490c177SAndreas Gohr $class = "class='" . ($class ?: 'mail') . "'"; 246e1d9dcc8SAndreas Gohr return "<a href='mailto:$email' $class title='$email' $more>$name</a>"; 247e1d9dcc8SAndreas Gohr } 248e1d9dcc8SAndreas Gohr 249e1d9dcc8SAndreas Gohr /** 250e1d9dcc8SAndreas Gohr * @see PluginInterface::external_link() 251e1d9dcc8SAndreas Gohr */ 252e1d9dcc8SAndreas Gohr public function external_link($link, $title = '', $class = '', $target = '', $more = '') 253e1d9dcc8SAndreas Gohr { 254e1d9dcc8SAndreas Gohr global $conf; 255e1d9dcc8SAndreas Gohr 256e1d9dcc8SAndreas Gohr $link = htmlentities($link); 257e1d9dcc8SAndreas Gohr if (!$title) $title = $link; 258e1d9dcc8SAndreas Gohr if (!$target) $target = $conf['target']['extern']; 259e1d9dcc8SAndreas Gohr if ($conf['relnofollow']) $more .= ' rel="nofollow"'; 260e1d9dcc8SAndreas Gohr 261e1d9dcc8SAndreas Gohr if ($class) $class = " class='$class'"; 262e1d9dcc8SAndreas Gohr if ($target) $target = " target='$target'"; 263e1d9dcc8SAndreas Gohr if ($more) $more = " " . trim($more); 264e1d9dcc8SAndreas Gohr 265e1d9dcc8SAndreas Gohr return "<a href='$link'$class$target$more>$title</a>"; 266e1d9dcc8SAndreas Gohr } 267e1d9dcc8SAndreas Gohr 268e1d9dcc8SAndreas Gohr /** 269e1d9dcc8SAndreas Gohr * @see PluginInterface::render_text() 270e1d9dcc8SAndreas Gohr */ 271e1d9dcc8SAndreas Gohr public function render_text($text, $format = 'xhtml') 272e1d9dcc8SAndreas Gohr { 273e1d9dcc8SAndreas Gohr return p_render($format, p_get_instructions($text), $info); 274e1d9dcc8SAndreas Gohr } 275e1d9dcc8SAndreas Gohr 276e1d9dcc8SAndreas Gohr // endregion 277e1d9dcc8SAndreas Gohr} 278