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