xref: /dokuwiki/lib/plugins/extension/Notice.php (revision 4fd6a1d7ae34e34afb3c0bae47639222f884a1b5)
1<?php
2
3
4namespace dokuwiki\plugin\extension;
5
6class Notice
7{
8    const INFO = 'info';
9    const WARNING = 'warning';
10    const ERROR = 'error';
11    const SECURITY = 'security';
12
13    public const ICONS = [
14        self::INFO => 'ⓘ',
15        self::WARNING => '↯',
16        self::ERROR => '⚠',
17        self::SECURITY => '☠',
18    ];
19
20    protected $notices = [
21        self::INFO => [],
22        self::WARNING => [],
23        self::ERROR => [],
24        self::SECURITY => [],
25    ];
26
27    /** @var \helper_plugin_extension */
28    protected $helper;
29
30    /** @var Extension */
31    protected Extension $extension;
32
33    /**
34     * Not public, use list() instead
35     * @param Extension $extension
36     */
37    protected function __construct(Extension $extension)
38    {
39        $this->helper = plugin_load('helper', 'extension');
40        $this->extension = $extension;
41
42        $this->checkDependencies();
43        $this->checkConflicts();
44        $this->checkSecurity();
45        $this->checkFolder();
46        $this->checkPHPVersion();
47        $this->checkUpdateMessage();
48        $this->checkURLChange();
49    }
50
51    /**
52     * Get all notices for the extension
53     *
54     * @return string[][] array of notices grouped by type
55     */
56    public static function list(Extension $extension): array
57    {
58        $self = new self($extension);
59        return $self->notices;
60    }
61
62    /**
63     * Access a language string
64     *
65     * @param string $msg
66     * @return string
67     */
68    protected function getLang($msg)
69    {
70        return strip_tags($this->helper->getLang($msg)); // FIXME existing strings should be adjusted
71    }
72
73    /**
74     * Check that all dependencies are met
75     * @return void
76     */
77    protected function checkDependencies()
78    {
79        if (!$this->extension->isInstalled()) return;
80
81        $dependencies = $this->extension->getDependencyList();
82        $missing = [];
83        foreach ($dependencies as $dependency) {
84            $dep = Extension::createFromId($dependency);
85            if (!$dep->isInstalled()) $missing[] = $dep;
86        }
87        if(!$missing) return;
88
89        $this->notices[self::ERROR][] = sprintf(
90            $this->getLang('missing_dependency'),
91            join(', ', array_map(static fn(Extension $dep) => $dep->getId(true), $missing))
92        );
93    }
94
95    /**
96     * Check if installed dependencies are conflicting
97     * @return void
98     */
99    protected function checkConflicts()
100    {
101        $conflicts = $this->extension->getConflictList();
102        $found = [];
103        foreach ($conflicts as $conflict) {
104            $dep = Extension::createFromId($conflict);
105            if ($dep->isInstalled()) $found[] = $dep;
106        }
107        if(!$found) return;
108
109        $this->notices[self::WARNING][] = sprintf(
110            $this->getLang('found_conflict'),
111            join(', ', array_map(static fn(Extension $dep) => $dep->getId(true), $found))
112        );
113    }
114
115    /**
116     * Check for security issues
117     * @return void
118     */
119    protected function checkSecurity()
120    {
121        if ($issue = $this->extension->getSecurityIssue()) {
122            $this->notices[self::SECURITY][] = sprintf($this->getLang('security_issue'), $issue);
123        }
124        if ($issue = $this->extension->getSecurityWarning()) {
125            $this->notices[self::SECURITY][] = sprintf($this->getLang('security_issue'), $issue);
126        }
127    }
128
129    /**
130     * Check if the extension is installed in correct folder
131     * @return void
132     */
133    protected function checkFolder()
134    {
135        if (!$this->extension->isInWrongFolder()) return;
136
137        $this->notices[self::ERROR][] = sprintf(
138            $this->getLang('wrong_folder'),
139            basename($this->extension->getCurrentDir()),
140            basename($this->extension->getInstallDir())
141        );
142    }
143
144    /**
145     * Check PHP requirements
146     * @return void
147     */
148    protected function checkPHPVersion()
149    {
150        try {
151            Installer::ensurePhpCompatibility($this->extension);
152        } catch (\Exception $e) {
153            $this->notices[self::ERROR][] = $e->getMessage();
154        }
155    }
156
157    /**
158     * Check for update message
159     * @return void
160     */
161    protected function checkUpdateMessage()
162    {
163        // FIXME should we only display this for installed extensions?
164        if ($msg = $this->extension->getUpdateMessage()) {
165            $this->notices[self::WARNING][] = sprintf($this->getLang('update_message'), $msg);
166        }
167    }
168
169    /**
170     * Check for URL changes
171     * @return void
172     */
173    protected function checkURLChange()
174    {
175        if (!$this->extension->hasChangedURL()) return;
176        $this->notices[self::WARNING][] = sprintf(
177            $this->getLang('url_change'),
178            $this->extension->getDownloadURL(),
179            $this->extension->getManager()->getDownloadURL()
180        );
181    }
182
183}
184