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 424fd6a1d7SAndreas Gohr $this->checkSecurity(); 43*8fe483c9SAndreas Gohr $this->checkURLChange(); 444fd6a1d7SAndreas Gohr $this->checkFolder(); 454fd6a1d7SAndreas Gohr $this->checkPHPVersion(); 46*8fe483c9SAndreas Gohr $this->checkDependencies(); 47*8fe483c9SAndreas Gohr $this->checkConflicts(); 484fd6a1d7SAndreas Gohr $this->checkUpdateMessage(); 49981e70caSAndreas Gohr $this->checkPermissions(); 50981e70caSAndreas Gohr $this->checkUnusedAuth(); 51981e70caSAndreas Gohr $this->checkGit(); 524fd6a1d7SAndreas Gohr } 534fd6a1d7SAndreas Gohr 544fd6a1d7SAndreas Gohr /** 554fd6a1d7SAndreas Gohr * Get all notices for the extension 564fd6a1d7SAndreas Gohr * 574fd6a1d7SAndreas Gohr * @return string[][] array of notices grouped by type 584fd6a1d7SAndreas Gohr */ 594fd6a1d7SAndreas Gohr public static function list(Extension $extension): array 604fd6a1d7SAndreas Gohr { 614fd6a1d7SAndreas Gohr $self = new self($extension); 624fd6a1d7SAndreas Gohr return $self->notices; 634fd6a1d7SAndreas Gohr } 644fd6a1d7SAndreas Gohr 654fd6a1d7SAndreas Gohr /** 664fd6a1d7SAndreas Gohr * Access a language string 674fd6a1d7SAndreas Gohr * 684fd6a1d7SAndreas Gohr * @param string $msg 694fd6a1d7SAndreas Gohr * @return string 704fd6a1d7SAndreas Gohr */ 714fd6a1d7SAndreas Gohr protected function getLang($msg) 724fd6a1d7SAndreas Gohr { 73*8fe483c9SAndreas Gohr // FIXME existing strings should be adjusted 74*8fe483c9SAndreas Gohr return strip_tags(preg_replace('/<br ?\/?>/', "\n", $this->helper->getLang($msg))); 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 187981e70caSAndreas Gohr /** 188981e70caSAndreas Gohr * Check if the extension dir has the correct permissions to change 189981e70caSAndreas Gohr * 190981e70caSAndreas Gohr * @return void 191981e70caSAndreas Gohr */ 192981e70caSAndreas Gohr protected function checkPermissions() 193981e70caSAndreas Gohr { 194981e70caSAndreas Gohr try { 195981e70caSAndreas Gohr Installer::ensurePermissions($this->extension); 196981e70caSAndreas Gohr } catch (\Exception $e) { 197981e70caSAndreas Gohr $this->notices[self::ERROR][] = $e->getMessage(); 198981e70caSAndreas Gohr } 199981e70caSAndreas Gohr } 200981e70caSAndreas Gohr 201981e70caSAndreas Gohr /** 202981e70caSAndreas Gohr * Hint about unused auth plugins 203981e70caSAndreas Gohr * 204981e70caSAndreas Gohr * @return void 205981e70caSAndreas Gohr */ 206981e70caSAndreas Gohr protected function checkUnusedAuth() 207981e70caSAndreas Gohr { 208981e70caSAndreas Gohr global $conf; 209981e70caSAndreas Gohr if ( 210981e70caSAndreas Gohr $this->extension->isEnabled() && 211981e70caSAndreas Gohr in_array('Auth', $this->extension->getComponentTypes()) && 212981e70caSAndreas Gohr $conf['authtype'] != $this->extension->getID() 213981e70caSAndreas Gohr ) { 214981e70caSAndreas Gohr $this->notices[self::INFO][] = $this->getLang('auth'); 215981e70caSAndreas Gohr } 216981e70caSAndreas Gohr } 217981e70caSAndreas Gohr 218981e70caSAndreas Gohr /** 219981e70caSAndreas Gohr * Hint about installations by git 220981e70caSAndreas Gohr * 221981e70caSAndreas Gohr * @return void 222981e70caSAndreas Gohr */ 223981e70caSAndreas Gohr protected function checkGit() 224981e70caSAndreas Gohr { 225981e70caSAndreas Gohr if ($this->extension->isGitControlled()) { 226981e70caSAndreas Gohr $this->notices[self::INFO][] = $this->getLang('git'); 227981e70caSAndreas Gohr } 228981e70caSAndreas Gohr } 2294fd6a1d7SAndreas Gohr} 230