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