xref: /dokuwiki/lib/plugins/extension/Notice.php (revision 981e70cabab67fd2c1ea32d1f7d1ee51fe3e16a6)
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
42*981e70caSAndreas Gohr        // FIXME sort sensibly
434fd6a1d7SAndreas Gohr        $this->checkDependencies();
444fd6a1d7SAndreas Gohr        $this->checkConflicts();
454fd6a1d7SAndreas Gohr        $this->checkSecurity();
464fd6a1d7SAndreas Gohr        $this->checkFolder();
474fd6a1d7SAndreas Gohr        $this->checkPHPVersion();
484fd6a1d7SAndreas Gohr        $this->checkUpdateMessage();
494fd6a1d7SAndreas Gohr        $this->checkURLChange();
50*981e70caSAndreas Gohr        $this->checkPermissions();
51*981e70caSAndreas Gohr        $this->checkUnusedAuth();
52*981e70caSAndreas Gohr        $this->checkGit();
534fd6a1d7SAndreas Gohr    }
544fd6a1d7SAndreas Gohr
554fd6a1d7SAndreas Gohr    /**
564fd6a1d7SAndreas Gohr     * Get all notices for the extension
574fd6a1d7SAndreas Gohr     *
584fd6a1d7SAndreas Gohr     * @return string[][] array of notices grouped by type
594fd6a1d7SAndreas Gohr     */
604fd6a1d7SAndreas Gohr    public static function list(Extension $extension): array
614fd6a1d7SAndreas Gohr    {
624fd6a1d7SAndreas Gohr        $self = new self($extension);
634fd6a1d7SAndreas Gohr        return $self->notices;
644fd6a1d7SAndreas Gohr    }
654fd6a1d7SAndreas Gohr
664fd6a1d7SAndreas Gohr    /**
674fd6a1d7SAndreas Gohr     * Access a language string
684fd6a1d7SAndreas Gohr     *
694fd6a1d7SAndreas Gohr     * @param string $msg
704fd6a1d7SAndreas Gohr     * @return string
714fd6a1d7SAndreas Gohr     */
724fd6a1d7SAndreas Gohr    protected function getLang($msg)
734fd6a1d7SAndreas Gohr    {
744fd6a1d7SAndreas Gohr        return strip_tags($this->helper->getLang($msg)); // FIXME existing strings should be adjusted
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
187*981e70caSAndreas Gohr    /**
188*981e70caSAndreas Gohr     * Check if the extension dir has the correct permissions to change
189*981e70caSAndreas Gohr     *
190*981e70caSAndreas Gohr     * @return void
191*981e70caSAndreas Gohr     */
192*981e70caSAndreas Gohr    protected function checkPermissions()
193*981e70caSAndreas Gohr    {
194*981e70caSAndreas Gohr        try {
195*981e70caSAndreas Gohr            Installer::ensurePermissions($this->extension);
196*981e70caSAndreas Gohr        } catch (\Exception $e) {
197*981e70caSAndreas Gohr            $this->notices[self::ERROR][] = $e->getMessage();
198*981e70caSAndreas Gohr        }
199*981e70caSAndreas Gohr    }
200*981e70caSAndreas Gohr
201*981e70caSAndreas Gohr    /**
202*981e70caSAndreas Gohr     * Hint about unused auth plugins
203*981e70caSAndreas Gohr     *
204*981e70caSAndreas Gohr     * @return void
205*981e70caSAndreas Gohr     */
206*981e70caSAndreas Gohr    protected function checkUnusedAuth()
207*981e70caSAndreas Gohr    {
208*981e70caSAndreas Gohr        global $conf;
209*981e70caSAndreas Gohr        if (
210*981e70caSAndreas Gohr            $this->extension->isEnabled() &&
211*981e70caSAndreas Gohr            in_array('Auth', $this->extension->getComponentTypes()) &&
212*981e70caSAndreas Gohr            $conf['authtype'] != $this->extension->getID()
213*981e70caSAndreas Gohr        ) {
214*981e70caSAndreas Gohr            $this->notices[self::INFO][] = $this->getLang('auth');
215*981e70caSAndreas Gohr        }
216*981e70caSAndreas Gohr    }
217*981e70caSAndreas Gohr
218*981e70caSAndreas Gohr    /**
219*981e70caSAndreas Gohr     * Hint about installations by git
220*981e70caSAndreas Gohr     *
221*981e70caSAndreas Gohr     * @return void
222*981e70caSAndreas Gohr     */
223*981e70caSAndreas Gohr    protected function checkGit()
224*981e70caSAndreas Gohr    {
225*981e70caSAndreas Gohr        if ($this->extension->isGitControlled()) {
226*981e70caSAndreas Gohr            $this->notices[self::INFO][] = $this->getLang('git');
227*981e70caSAndreas Gohr        }
228*981e70caSAndreas Gohr    }
2294fd6a1d7SAndreas Gohr}
230