xref: /dokuwiki/lib/plugins/extension/Notice.php (revision 8fe483c9dd38f0052abe729cc74057c9cdf54ad3)
14fd6a1d7SAndreas Gohr<?php
24fd6a1d7SAndreas Gohr
34fd6a1d7SAndreas Gohr
44fd6a1d7SAndreas Gohrnamespace dokuwiki\plugin\extension;
54fd6a1d7SAndreas Gohr
64fd6a1d7SAndreas Gohrclass Notice
74fd6a1d7SAndreas Gohr{
84fd6a1d7SAndreas Gohr    const INFO = 'info';
94fd6a1d7SAndreas Gohr    const WARNING = 'warning';
104fd6a1d7SAndreas Gohr    const ERROR = 'error';
114fd6a1d7SAndreas Gohr    const SECURITY = 'security';
124fd6a1d7SAndreas Gohr
134fd6a1d7SAndreas Gohr    public const ICONS = [
144fd6a1d7SAndreas Gohr        self::INFO => 'ⓘ',
154fd6a1d7SAndreas Gohr        self::WARNING => '↯',
164fd6a1d7SAndreas Gohr        self::ERROR => '⚠',
174fd6a1d7SAndreas Gohr        self::SECURITY => '☠',
184fd6a1d7SAndreas Gohr    ];
194fd6a1d7SAndreas Gohr
204fd6a1d7SAndreas Gohr    protected $notices = [
214fd6a1d7SAndreas Gohr        self::INFO => [],
224fd6a1d7SAndreas Gohr        self::WARNING => [],
234fd6a1d7SAndreas Gohr        self::ERROR => [],
244fd6a1d7SAndreas Gohr        self::SECURITY => [],
254fd6a1d7SAndreas Gohr    ];
264fd6a1d7SAndreas Gohr
274fd6a1d7SAndreas Gohr    /** @var \helper_plugin_extension */
284fd6a1d7SAndreas Gohr    protected $helper;
294fd6a1d7SAndreas Gohr
304fd6a1d7SAndreas Gohr    /** @var Extension */
314fd6a1d7SAndreas Gohr    protected Extension $extension;
324fd6a1d7SAndreas Gohr
334fd6a1d7SAndreas Gohr    /**
344fd6a1d7SAndreas Gohr     * Not public, use list() instead
354fd6a1d7SAndreas Gohr     * @param Extension $extension
364fd6a1d7SAndreas Gohr     */
374fd6a1d7SAndreas Gohr    protected function __construct(Extension $extension)
384fd6a1d7SAndreas Gohr    {
394fd6a1d7SAndreas Gohr        $this->helper = plugin_load('helper', 'extension');
404fd6a1d7SAndreas Gohr        $this->extension = $extension;
414fd6a1d7SAndreas Gohr
424fd6a1d7SAndreas Gohr        $this->checkSecurity();
43*8fe483c9SAndreas Gohr        $this->checkURLChange();
444fd6a1d7SAndreas Gohr        $this->checkFolder();
454fd6a1d7SAndreas Gohr        $this->checkPHPVersion();
46*8fe483c9SAndreas Gohr        $this->checkDependencies();
47*8fe483c9SAndreas Gohr        $this->checkConflicts();
484fd6a1d7SAndreas Gohr        $this->checkUpdateMessage();
49981e70caSAndreas Gohr        $this->checkPermissions();
50981e70caSAndreas Gohr        $this->checkUnusedAuth();
51981e70caSAndreas Gohr        $this->checkGit();
524fd6a1d7SAndreas Gohr    }
534fd6a1d7SAndreas Gohr
544fd6a1d7SAndreas Gohr    /**
554fd6a1d7SAndreas Gohr     * Get all notices for the extension
564fd6a1d7SAndreas Gohr     *
574fd6a1d7SAndreas Gohr     * @return string[][] array of notices grouped by type
584fd6a1d7SAndreas Gohr     */
594fd6a1d7SAndreas Gohr    public static function list(Extension $extension): array
604fd6a1d7SAndreas Gohr    {
614fd6a1d7SAndreas Gohr        $self = new self($extension);
624fd6a1d7SAndreas Gohr        return $self->notices;
634fd6a1d7SAndreas Gohr    }
644fd6a1d7SAndreas Gohr
654fd6a1d7SAndreas Gohr    /**
664fd6a1d7SAndreas Gohr     * Access a language string
674fd6a1d7SAndreas Gohr     *
684fd6a1d7SAndreas Gohr     * @param string $msg
694fd6a1d7SAndreas Gohr     * @return string
704fd6a1d7SAndreas Gohr     */
714fd6a1d7SAndreas Gohr    protected function getLang($msg)
724fd6a1d7SAndreas Gohr    {
73*8fe483c9SAndreas Gohr        // FIXME existing strings should be adjusted
74*8fe483c9SAndreas Gohr        return strip_tags(preg_replace('/<br ?\/?>/', "\n", $this->helper->getLang($msg)));
754fd6a1d7SAndreas Gohr    }
764fd6a1d7SAndreas Gohr
774fd6a1d7SAndreas Gohr    /**
784fd6a1d7SAndreas Gohr     * Check that all dependencies are met
794fd6a1d7SAndreas Gohr     * @return void
804fd6a1d7SAndreas Gohr     */
814fd6a1d7SAndreas Gohr    protected function checkDependencies()
824fd6a1d7SAndreas Gohr    {
834fd6a1d7SAndreas Gohr        if (!$this->extension->isInstalled()) return;
844fd6a1d7SAndreas Gohr
854fd6a1d7SAndreas Gohr        $dependencies = $this->extension->getDependencyList();
864fd6a1d7SAndreas Gohr        $missing = [];
874fd6a1d7SAndreas Gohr        foreach ($dependencies as $dependency) {
884fd6a1d7SAndreas Gohr            $dep = Extension::createFromId($dependency);
894fd6a1d7SAndreas Gohr            if (!$dep->isInstalled()) $missing[] = $dep;
904fd6a1d7SAndreas Gohr        }
914fd6a1d7SAndreas Gohr        if (!$missing) return;
924fd6a1d7SAndreas Gohr
934fd6a1d7SAndreas Gohr        $this->notices[self::ERROR][] = sprintf(
944fd6a1d7SAndreas Gohr            $this->getLang('missing_dependency'),
954fd6a1d7SAndreas Gohr            join(', ', array_map(static fn(Extension $dep) => $dep->getId(true), $missing))
964fd6a1d7SAndreas Gohr        );
974fd6a1d7SAndreas Gohr    }
984fd6a1d7SAndreas Gohr
994fd6a1d7SAndreas Gohr    /**
1004fd6a1d7SAndreas Gohr     * Check if installed dependencies are conflicting
1014fd6a1d7SAndreas Gohr     * @return void
1024fd6a1d7SAndreas Gohr     */
1034fd6a1d7SAndreas Gohr    protected function checkConflicts()
1044fd6a1d7SAndreas Gohr    {
1054fd6a1d7SAndreas Gohr        $conflicts = $this->extension->getConflictList();
1064fd6a1d7SAndreas Gohr        $found = [];
1074fd6a1d7SAndreas Gohr        foreach ($conflicts as $conflict) {
1084fd6a1d7SAndreas Gohr            $dep = Extension::createFromId($conflict);
1094fd6a1d7SAndreas Gohr            if ($dep->isInstalled()) $found[] = $dep;
1104fd6a1d7SAndreas Gohr        }
1114fd6a1d7SAndreas Gohr        if (!$found) return;
1124fd6a1d7SAndreas Gohr
1134fd6a1d7SAndreas Gohr        $this->notices[self::WARNING][] = sprintf(
1144fd6a1d7SAndreas Gohr            $this->getLang('found_conflict'),
1154fd6a1d7SAndreas Gohr            join(', ', array_map(static fn(Extension $dep) => $dep->getId(true), $found))
1164fd6a1d7SAndreas Gohr        );
1174fd6a1d7SAndreas Gohr    }
1184fd6a1d7SAndreas Gohr
1194fd6a1d7SAndreas Gohr    /**
1204fd6a1d7SAndreas Gohr     * Check for security issues
1214fd6a1d7SAndreas Gohr     * @return void
1224fd6a1d7SAndreas Gohr     */
1234fd6a1d7SAndreas Gohr    protected function checkSecurity()
1244fd6a1d7SAndreas Gohr    {
1254fd6a1d7SAndreas Gohr        if ($issue = $this->extension->getSecurityIssue()) {
1264fd6a1d7SAndreas Gohr            $this->notices[self::SECURITY][] = sprintf($this->getLang('security_issue'), $issue);
1274fd6a1d7SAndreas Gohr        }
1284fd6a1d7SAndreas Gohr        if ($issue = $this->extension->getSecurityWarning()) {
1294fd6a1d7SAndreas Gohr            $this->notices[self::SECURITY][] = sprintf($this->getLang('security_issue'), $issue);
1304fd6a1d7SAndreas Gohr        }
1314fd6a1d7SAndreas Gohr    }
1324fd6a1d7SAndreas Gohr
1334fd6a1d7SAndreas Gohr    /**
1344fd6a1d7SAndreas Gohr     * Check if the extension is installed in correct folder
1354fd6a1d7SAndreas Gohr     * @return void
1364fd6a1d7SAndreas Gohr     */
1374fd6a1d7SAndreas Gohr    protected function checkFolder()
1384fd6a1d7SAndreas Gohr    {
1394fd6a1d7SAndreas Gohr        if (!$this->extension->isInWrongFolder()) return;
1404fd6a1d7SAndreas Gohr
1414fd6a1d7SAndreas Gohr        $this->notices[self::ERROR][] = sprintf(
1424fd6a1d7SAndreas Gohr            $this->getLang('wrong_folder'),
1434fd6a1d7SAndreas Gohr            basename($this->extension->getCurrentDir()),
1444fd6a1d7SAndreas Gohr            basename($this->extension->getInstallDir())
1454fd6a1d7SAndreas Gohr        );
1464fd6a1d7SAndreas Gohr    }
1474fd6a1d7SAndreas Gohr
1484fd6a1d7SAndreas Gohr    /**
1494fd6a1d7SAndreas Gohr     * Check PHP requirements
1504fd6a1d7SAndreas Gohr     * @return void
1514fd6a1d7SAndreas Gohr     */
1524fd6a1d7SAndreas Gohr    protected function checkPHPVersion()
1534fd6a1d7SAndreas Gohr    {
1544fd6a1d7SAndreas Gohr        try {
1554fd6a1d7SAndreas Gohr            Installer::ensurePhpCompatibility($this->extension);
1564fd6a1d7SAndreas Gohr        } catch (\Exception $e) {
1574fd6a1d7SAndreas Gohr            $this->notices[self::ERROR][] = $e->getMessage();
1584fd6a1d7SAndreas Gohr        }
1594fd6a1d7SAndreas Gohr    }
1604fd6a1d7SAndreas Gohr
1614fd6a1d7SAndreas Gohr    /**
1624fd6a1d7SAndreas Gohr     * Check for update message
1634fd6a1d7SAndreas Gohr     * @return void
1644fd6a1d7SAndreas Gohr     */
1654fd6a1d7SAndreas Gohr    protected function checkUpdateMessage()
1664fd6a1d7SAndreas Gohr    {
1674fd6a1d7SAndreas Gohr        // FIXME should we only display this for installed extensions?
1684fd6a1d7SAndreas Gohr        if ($msg = $this->extension->getUpdateMessage()) {
1694fd6a1d7SAndreas Gohr            $this->notices[self::WARNING][] = sprintf($this->getLang('update_message'), $msg);
1704fd6a1d7SAndreas Gohr        }
1714fd6a1d7SAndreas Gohr    }
1724fd6a1d7SAndreas Gohr
1734fd6a1d7SAndreas Gohr    /**
1744fd6a1d7SAndreas Gohr     * Check for URL changes
1754fd6a1d7SAndreas Gohr     * @return void
1764fd6a1d7SAndreas Gohr     */
1774fd6a1d7SAndreas Gohr    protected function checkURLChange()
1784fd6a1d7SAndreas Gohr    {
1794fd6a1d7SAndreas Gohr        if (!$this->extension->hasChangedURL()) return;
1804fd6a1d7SAndreas Gohr        $this->notices[self::WARNING][] = sprintf(
1814fd6a1d7SAndreas Gohr            $this->getLang('url_change'),
1824fd6a1d7SAndreas Gohr            $this->extension->getDownloadURL(),
1834fd6a1d7SAndreas Gohr            $this->extension->getManager()->getDownloadURL()
1844fd6a1d7SAndreas Gohr        );
1854fd6a1d7SAndreas Gohr    }
1864fd6a1d7SAndreas Gohr
187981e70caSAndreas Gohr    /**
188981e70caSAndreas Gohr     * Check if the extension dir has the correct permissions to change
189981e70caSAndreas Gohr     *
190981e70caSAndreas Gohr     * @return void
191981e70caSAndreas Gohr     */
192981e70caSAndreas Gohr    protected function checkPermissions()
193981e70caSAndreas Gohr    {
194981e70caSAndreas Gohr        try {
195981e70caSAndreas Gohr            Installer::ensurePermissions($this->extension);
196981e70caSAndreas Gohr        } catch (\Exception $e) {
197981e70caSAndreas Gohr            $this->notices[self::ERROR][] = $e->getMessage();
198981e70caSAndreas Gohr        }
199981e70caSAndreas Gohr    }
200981e70caSAndreas Gohr
201981e70caSAndreas Gohr    /**
202981e70caSAndreas Gohr     * Hint about unused auth plugins
203981e70caSAndreas Gohr     *
204981e70caSAndreas Gohr     * @return void
205981e70caSAndreas Gohr     */
206981e70caSAndreas Gohr    protected function checkUnusedAuth()
207981e70caSAndreas Gohr    {
208981e70caSAndreas Gohr        global $conf;
209981e70caSAndreas Gohr        if (
210981e70caSAndreas Gohr            $this->extension->isEnabled() &&
211981e70caSAndreas Gohr            in_array('Auth', $this->extension->getComponentTypes()) &&
212981e70caSAndreas Gohr            $conf['authtype'] != $this->extension->getID()
213981e70caSAndreas Gohr        ) {
214981e70caSAndreas Gohr            $this->notices[self::INFO][] = $this->getLang('auth');
215981e70caSAndreas Gohr        }
216981e70caSAndreas Gohr    }
217981e70caSAndreas Gohr
218981e70caSAndreas Gohr    /**
219981e70caSAndreas Gohr     * Hint about installations by git
220981e70caSAndreas Gohr     *
221981e70caSAndreas Gohr     * @return void
222981e70caSAndreas Gohr     */
223981e70caSAndreas Gohr    protected function checkGit()
224981e70caSAndreas Gohr    {
225981e70caSAndreas Gohr        if ($this->extension->isGitControlled()) {
226981e70caSAndreas Gohr            $this->notices[self::INFO][] = $this->getLang('git');
227981e70caSAndreas Gohr        }
228981e70caSAndreas Gohr    }
2294fd6a1d7SAndreas Gohr}
230