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