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