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