14fd6a1d7SAndreas Gohr<?php 24fd6a1d7SAndreas Gohr 34fd6a1d7SAndreas Gohrnamespace dokuwiki\plugin\extension; 44fd6a1d7SAndreas Gohr 54fd6a1d7SAndreas Gohrclass Notice 64fd6a1d7SAndreas Gohr{ 77c184cfcSAndreas Gohr public const INFO = 'info'; 87c184cfcSAndreas Gohr public const WARNING = 'warning'; 97c184cfcSAndreas Gohr public const ERROR = 'error'; 107c184cfcSAndreas 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 { 72*cf461f20SAndreas Gohr return $this->helper->getLang($msg); 734fd6a1d7SAndreas Gohr } 744fd6a1d7SAndreas Gohr 754fd6a1d7SAndreas Gohr /** 764fd6a1d7SAndreas Gohr * Check that all dependencies are met 774fd6a1d7SAndreas Gohr * @return void 784fd6a1d7SAndreas Gohr */ 794fd6a1d7SAndreas Gohr protected function checkDependencies() 804fd6a1d7SAndreas Gohr { 814fd6a1d7SAndreas Gohr if (!$this->extension->isInstalled()) return; 824fd6a1d7SAndreas Gohr 834fd6a1d7SAndreas Gohr $dependencies = $this->extension->getDependencyList(); 844fd6a1d7SAndreas Gohr $missing = []; 854fd6a1d7SAndreas Gohr foreach ($dependencies as $dependency) { 864fd6a1d7SAndreas Gohr $dep = Extension::createFromId($dependency); 874fd6a1d7SAndreas Gohr if (!$dep->isInstalled()) $missing[] = $dep; 884fd6a1d7SAndreas Gohr } 894fd6a1d7SAndreas Gohr if (!$missing) return; 904fd6a1d7SAndreas Gohr 914fd6a1d7SAndreas Gohr $this->notices[self::ERROR][] = sprintf( 924fd6a1d7SAndreas Gohr $this->getLang('missing_dependency'), 937c184cfcSAndreas Gohr implode(', ', array_map(static fn(Extension $dep) => $dep->getId(true), $missing)) 944fd6a1d7SAndreas Gohr ); 954fd6a1d7SAndreas Gohr } 964fd6a1d7SAndreas Gohr 974fd6a1d7SAndreas Gohr /** 984fd6a1d7SAndreas Gohr * Check if installed dependencies are conflicting 994fd6a1d7SAndreas Gohr * @return void 1004fd6a1d7SAndreas Gohr */ 1014fd6a1d7SAndreas Gohr protected function checkConflicts() 1024fd6a1d7SAndreas Gohr { 1034fd6a1d7SAndreas Gohr $conflicts = $this->extension->getConflictList(); 1044fd6a1d7SAndreas Gohr $found = []; 1054fd6a1d7SAndreas Gohr foreach ($conflicts as $conflict) { 1064fd6a1d7SAndreas Gohr $dep = Extension::createFromId($conflict); 1074fd6a1d7SAndreas Gohr if ($dep->isInstalled()) $found[] = $dep; 1084fd6a1d7SAndreas Gohr } 1094fd6a1d7SAndreas Gohr if (!$found) return; 1104fd6a1d7SAndreas Gohr 1114fd6a1d7SAndreas Gohr $this->notices[self::WARNING][] = sprintf( 1124fd6a1d7SAndreas Gohr $this->getLang('found_conflict'), 1137c184cfcSAndreas Gohr implode(', ', array_map(static fn(Extension $dep) => $dep->getId(true), $found)) 1144fd6a1d7SAndreas Gohr ); 1154fd6a1d7SAndreas Gohr } 1164fd6a1d7SAndreas Gohr 1174fd6a1d7SAndreas Gohr /** 1184fd6a1d7SAndreas Gohr * Check for security issues 1194fd6a1d7SAndreas Gohr * @return void 1204fd6a1d7SAndreas Gohr */ 1214fd6a1d7SAndreas Gohr protected function checkSecurity() 1224fd6a1d7SAndreas Gohr { 1234fd6a1d7SAndreas Gohr if ($issue = $this->extension->getSecurityIssue()) { 1244fd6a1d7SAndreas Gohr $this->notices[self::SECURITY][] = sprintf($this->getLang('security_issue'), $issue); 1254fd6a1d7SAndreas Gohr } 1264fd6a1d7SAndreas Gohr if ($issue = $this->extension->getSecurityWarning()) { 127*cf461f20SAndreas Gohr $this->notices[self::SECURITY][] = sprintf($this->getLang('security_warning'), $issue); 1284fd6a1d7SAndreas Gohr } 1294fd6a1d7SAndreas Gohr } 1304fd6a1d7SAndreas Gohr 1314fd6a1d7SAndreas Gohr /** 1324fd6a1d7SAndreas Gohr * Check if the extension is installed in correct folder 1334fd6a1d7SAndreas Gohr * @return void 1344fd6a1d7SAndreas Gohr */ 1354fd6a1d7SAndreas Gohr protected function checkFolder() 1364fd6a1d7SAndreas Gohr { 1374fd6a1d7SAndreas Gohr if (!$this->extension->isInWrongFolder()) return; 1384fd6a1d7SAndreas Gohr 1394fd6a1d7SAndreas Gohr $this->notices[self::ERROR][] = sprintf( 1404fd6a1d7SAndreas Gohr $this->getLang('wrong_folder'), 1414fd6a1d7SAndreas Gohr basename($this->extension->getCurrentDir()), 1424fd6a1d7SAndreas Gohr basename($this->extension->getInstallDir()) 1434fd6a1d7SAndreas Gohr ); 1444fd6a1d7SAndreas Gohr } 1454fd6a1d7SAndreas Gohr 1464fd6a1d7SAndreas Gohr /** 1474fd6a1d7SAndreas Gohr * Check PHP requirements 1484fd6a1d7SAndreas Gohr * @return void 1494fd6a1d7SAndreas Gohr */ 1504fd6a1d7SAndreas Gohr protected function checkPHPVersion() 1514fd6a1d7SAndreas Gohr { 1524fd6a1d7SAndreas Gohr try { 1534fd6a1d7SAndreas Gohr Installer::ensurePhpCompatibility($this->extension); 1544fd6a1d7SAndreas Gohr } catch (\Exception $e) { 1554fd6a1d7SAndreas Gohr $this->notices[self::ERROR][] = $e->getMessage(); 1564fd6a1d7SAndreas Gohr } 1574fd6a1d7SAndreas Gohr } 1584fd6a1d7SAndreas Gohr 1594fd6a1d7SAndreas Gohr /** 1604fd6a1d7SAndreas Gohr * Check for update message 1614fd6a1d7SAndreas Gohr * @return void 1624fd6a1d7SAndreas Gohr */ 1634fd6a1d7SAndreas Gohr protected function checkUpdateMessage() 1644fd6a1d7SAndreas Gohr { 165d98308b7SAndreas Gohr // only display this for installed extensions 166d98308b7SAndreas Gohr if (!$this->extension->isInstalled()) return; 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