[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * Joomla! Content Management System 5 * 6 * @copyright (C) 2008 Open Source Matters, Inc. <https://www.joomla.org> 7 * @license GNU General Public License version 2 or later; see LICENSE.txt 8 */ 9 10 namespace Joomla\CMS\Updater; 11 12 use Joomla\CMS\Factory; 13 use Joomla\CMS\Filter\InputFilter; 14 use Joomla\CMS\Http\HttpFactory; 15 use Joomla\CMS\Language\Text; 16 use Joomla\CMS\Log\Log; 17 use Joomla\CMS\Object\CMSObject; 18 use Joomla\CMS\Version; 19 use Joomla\Registry\Registry; 20 21 // phpcs:disable PSR1.Files.SideEffects 22 \defined('JPATH_PLATFORM') or die; 23 // phpcs:enable PSR1.Files.SideEffects 24 25 /** 26 * Update class. It is used by Updater::update() to install an update. Use Updater::findUpdates() to find updates for 27 * an extension. 28 * 29 * @since 1.7.0 30 */ 31 class Update extends CMSObject 32 { 33 /** 34 * Update manifest `<name>` element 35 * 36 * @var string 37 * @since 1.7.0 38 */ 39 protected $name; 40 41 /** 42 * Update manifest `<description>` element 43 * 44 * @var string 45 * @since 1.7.0 46 */ 47 protected $description; 48 49 /** 50 * Update manifest `<element>` element 51 * 52 * @var string 53 * @since 1.7.0 54 */ 55 protected $element; 56 57 /** 58 * Update manifest `<type>` element 59 * 60 * @var string 61 * @since 1.7.0 62 */ 63 protected $type; 64 65 /** 66 * Update manifest `<version>` element 67 * 68 * @var string 69 * @since 1.7.0 70 */ 71 protected $version; 72 73 /** 74 * Update manifest `<infourl>` element 75 * 76 * @var string 77 * @since 1.7.0 78 */ 79 protected $infourl; 80 81 /** 82 * Update manifest `<client>` element 83 * 84 * @var string 85 * @since 1.7.0 86 */ 87 protected $client; 88 89 /** 90 * Update manifest `<group>` element 91 * 92 * @var string 93 * @since 1.7.0 94 */ 95 protected $group; 96 97 /** 98 * Update manifest `<downloads>` element 99 * 100 * @var string 101 * @since 1.7.0 102 */ 103 protected $downloads; 104 105 /** 106 * Update manifest `<downloadsource>` elements 107 * 108 * @var DownloadSource[] 109 * @since 3.8.3 110 */ 111 protected $downloadSources = array(); 112 113 /** 114 * Update manifest `<tags>` element 115 * 116 * @var string 117 * @since 1.7.0 118 */ 119 protected $tags; 120 121 /** 122 * Update manifest `<maintainer>` element 123 * 124 * @var string 125 * @since 1.7.0 126 */ 127 protected $maintainer; 128 129 /** 130 * Update manifest `<maintainerurl>` element 131 * 132 * @var string 133 * @since 1.7.0 134 */ 135 protected $maintainerurl; 136 137 /** 138 * Update manifest `<category>` element 139 * 140 * @var string 141 * @since 1.7.0 142 */ 143 protected $category; 144 145 /** 146 * Update manifest `<relationships>` element 147 * 148 * @var string 149 * @since 1.7.0 150 */ 151 protected $relationships; 152 153 /** 154 * Update manifest `<targetplatform>` element 155 * 156 * @var string 157 * @since 1.7.0 158 */ 159 protected $targetplatform; 160 161 /** 162 * Extra query for download URLs 163 * 164 * @var string 165 * @since 3.2.0 166 */ 167 protected $extra_query; 168 169 /** 170 * Resource handle for the XML Parser 171 * 172 * @var resource 173 * @since 3.0.0 174 */ 175 protected $xmlParser; 176 177 /** 178 * Element call stack 179 * 180 * @var array 181 * @since 3.0.0 182 */ 183 protected $stack = array('base'); 184 185 /** 186 * Unused state array 187 * 188 * @var array 189 * @since 3.0.0 190 */ 191 protected $stateStore = array(); 192 193 /** 194 * Object containing the current update data 195 * 196 * @var \stdClass 197 * @since 3.0.0 198 */ 199 protected $currentUpdate; 200 201 /** 202 * Object containing the latest update data 203 * 204 * @var \stdClass 205 * @since 3.0.0 206 */ 207 protected $latest; 208 209 /** 210 * The minimum stability required for updates to be taken into account. The possible values are: 211 * 0 dev Development snapshots, nightly builds, pre-release versions and so on 212 * 1 alpha Alpha versions (work in progress, things are likely to be broken) 213 * 2 beta Beta versions (major functionality in place, show-stopper bugs are likely to be present) 214 * 3 rc Release Candidate versions (almost stable, minor bugs might be present) 215 * 4 stable Stable versions (production quality code) 216 * 217 * @var integer 218 * @since 14.1 219 * 220 * @see Updater 221 */ 222 protected $minimum_stability = Updater::STABILITY_STABLE; 223 224 /** 225 * Array with compatible versions used by the pre-update check 226 * 227 * @var array 228 * @since 3.10.2 229 */ 230 protected $compatibleVersions = array(); 231 232 /** 233 * Gets the reference to the current direct parent 234 * 235 * @return string 236 * 237 * @since 1.7.0 238 */ 239 protected function _getStackLocation() 240 { 241 return implode('->', $this->stack); 242 } 243 244 /** 245 * Get the last position in stack count 246 * 247 * @return string 248 * 249 * @since 1.7.0 250 */ 251 protected function _getLastTag() 252 { 253 return $this->stack[\count($this->stack) - 1]; 254 } 255 256 /** 257 * XML Start Element callback 258 * 259 * @param object $parser Parser object 260 * @param string $name Name of the tag found 261 * @param array $attrs Attributes of the tag 262 * 263 * @return void 264 * 265 * @note This is public because it is called externally 266 * @since 1.7.0 267 */ 268 public function _startElement($parser, $name, $attrs = array()) 269 { 270 $this->stack[] = $name; 271 $tag = $this->_getStackLocation(); 272 273 // Reset the data 274 if (isset($this->$tag)) { 275 $this->$tag->_data = ''; 276 } 277 278 switch ($name) { 279 // This is a new update; create a current update 280 case 'UPDATE': 281 $this->currentUpdate = new \stdClass(); 282 break; 283 284 // Handle the array of download sources 285 case 'DOWNLOADSOURCE': 286 $source = new DownloadSource(); 287 288 foreach ($attrs as $key => $data) { 289 $key = strtolower($key); 290 $source->$key = $data; 291 } 292 293 $this->downloadSources[] = $source; 294 295 break; 296 297 // Don't do anything 298 case 'UPDATES': 299 break; 300 301 // For everything else there's...the default! 302 default: 303 $name = strtolower($name); 304 305 if (!isset($this->currentUpdate->$name)) { 306 $this->currentUpdate->$name = new \stdClass(); 307 } 308 309 $this->currentUpdate->$name->_data = ''; 310 311 foreach ($attrs as $key => $data) { 312 $key = strtolower($key); 313 $this->currentUpdate->$name->$key = $data; 314 } 315 break; 316 } 317 } 318 319 /** 320 * Callback for closing the element 321 * 322 * @param object $parser Parser object 323 * @param string $name Name of element that was closed 324 * 325 * @return void 326 * 327 * @note This is public because it is called externally 328 * @since 1.7.0 329 */ 330 public function _endElement($parser, $name) 331 { 332 array_pop($this->stack); 333 334 switch ($name) { 335 // Closing update, find the latest version and check 336 case 'UPDATE': 337 $product = strtolower(InputFilter::getInstance()->clean(Version::PRODUCT, 'cmd')); 338 339 // Check that the product matches and that the version matches (optionally a regexp) 340 if ( 341 isset($this->currentUpdate->targetplatform->name) 342 && $product == $this->currentUpdate->targetplatform->name 343 && preg_match('/^' . $this->currentUpdate->targetplatform->version . '/', $this->get('jversion.full', JVERSION)) 344 ) { 345 $phpMatch = false; 346 347 // Check if PHP version supported via <php_minimum> tag, assume true if tag isn't present 348 if (!isset($this->currentUpdate->php_minimum) || version_compare(PHP_VERSION, $this->currentUpdate->php_minimum->_data, '>=')) { 349 $phpMatch = true; 350 } 351 352 $dbMatch = false; 353 354 // Check if DB & version is supported via <supported_databases> tag, assume supported if tag isn't present 355 if (isset($this->currentUpdate->supported_databases)) { 356 $db = Factory::getDbo(); 357 $dbType = strtolower($db->getServerType()); 358 $dbVersion = $db->getVersion(); 359 $supportedDbs = $this->currentUpdate->supported_databases; 360 361 // MySQL and MariaDB use the same database driver but not the same version numbers 362 if ($dbType === 'mysql') { 363 // Check whether we have a MariaDB version string and extract the proper version from it 364 if (stripos($dbVersion, 'mariadb') !== false) { 365 // MariaDB: Strip off any leading '5.5.5-', if present 366 $dbVersion = preg_replace('/^5\.5\.5-/', '', $dbVersion); 367 $dbType = 'mariadb'; 368 } 369 } 370 371 // Do we have an entry for the database? 372 if (isset($supportedDbs->$dbType)) { 373 $minimumVersion = $supportedDbs->$dbType; 374 $dbMatch = version_compare($dbVersion, $minimumVersion, '>='); 375 } 376 } else { 377 // Set to true if the <supported_databases> tag is not set 378 $dbMatch = true; 379 } 380 381 // Check minimum stability 382 $stabilityMatch = true; 383 384 if (isset($this->currentUpdate->stability) && ($this->currentUpdate->stability < $this->minimum_stability)) { 385 $stabilityMatch = false; 386 } 387 388 if ($phpMatch && $stabilityMatch && $dbMatch) { 389 if (!empty($this->currentUpdate->downloadurl) && !empty($this->currentUpdate->downloadurl->_data)) { 390 $this->compatibleVersions[] = $this->currentUpdate->version->_data; 391 } 392 393 if ( 394 !isset($this->latest) 395 || version_compare($this->currentUpdate->version->_data, $this->latest->version->_data, '>') 396 ) { 397 $this->latest = $this->currentUpdate; 398 } 399 } 400 } 401 break; 402 case 'UPDATES': 403 // If the latest item is set then we transfer it to where we want to 404 if (isset($this->latest)) { 405 foreach (get_object_vars($this->latest) as $key => $val) { 406 $this->$key = $val; 407 } 408 409 unset($this->latest); 410 unset($this->currentUpdate); 411 } elseif (isset($this->currentUpdate)) { 412 // The update might be for an older version of j! 413 unset($this->currentUpdate); 414 } 415 break; 416 } 417 } 418 419 /** 420 * Character Parser Function 421 * 422 * @param object $parser Parser object. 423 * @param object $data The data. 424 * 425 * @return void 426 * 427 * @note This is public because its called externally. 428 * @since 1.7.0 429 */ 430 public function _characterData($parser, $data) 431 { 432 $tag = $this->_getLastTag(); 433 434 // Throw the data for this item together 435 $tag = strtolower($tag); 436 437 if ($tag === 'tag') { 438 $this->currentUpdate->stability = $this->stabilityTagToInteger((string) $data); 439 440 return; 441 } 442 443 if ($tag === 'downloadsource') { 444 // Grab the last source so we can append the URL 445 $source = end($this->downloadSources); 446 $source->url = $data; 447 448 return; 449 } 450 451 if (isset($this->currentUpdate->$tag)) { 452 $this->currentUpdate->$tag->_data .= $data; 453 } 454 } 455 456 /** 457 * Loads an XML file from a URL. 458 * 459 * @param string $url The URL. 460 * @param int $minimumStability The minimum stability required for updating the extension {@see Updater} 461 * 462 * @return boolean True on success 463 * 464 * @since 1.7.0 465 */ 466 public function loadFromXml($url, $minimumStability = Updater::STABILITY_STABLE) 467 { 468 $version = new Version(); 469 $httpOption = new Registry(); 470 $httpOption->set('userAgent', $version->getUserAgent('Joomla', true, false)); 471 472 try { 473 $http = HttpFactory::getHttp($httpOption); 474 $response = $http->get($url); 475 } catch (\RuntimeException $e) { 476 $response = null; 477 } 478 479 if ($response === null || $response->code !== 200) { 480 // @todo: Add a 'mark bad' setting here somehow 481 Log::add(Text::sprintf('JLIB_UPDATER_ERROR_EXTENSION_OPEN_URL', $url), Log::WARNING, 'jerror'); 482 483 return false; 484 } 485 486 $this->minimum_stability = $minimumStability; 487 488 $this->xmlParser = xml_parser_create(''); 489 xml_set_object($this->xmlParser, $this); 490 xml_set_element_handler($this->xmlParser, '_startElement', '_endElement'); 491 xml_set_character_data_handler($this->xmlParser, '_characterData'); 492 493 if (!xml_parse($this->xmlParser, $response->body)) { 494 Log::add( 495 sprintf( 496 'XML error: %s at line %d', 497 xml_error_string(xml_get_error_code($this->xmlParser)), 498 xml_get_current_line_number($this->xmlParser) 499 ), 500 Log::WARNING, 501 'updater' 502 ); 503 504 return false; 505 } 506 507 xml_parser_free($this->xmlParser); 508 509 return true; 510 } 511 512 /** 513 * Converts a tag to numeric stability representation. If the tag doesn't represent a known stability level (one of 514 * dev, alpha, beta, rc, stable) it is ignored. 515 * 516 * @param string $tag The tag string, e.g. dev, alpha, beta, rc, stable 517 * 518 * @return integer 519 * 520 * @since 3.4 521 */ 522 protected function stabilityTagToInteger($tag) 523 { 524 $constant = '\\Joomla\\CMS\\Updater\\Updater::STABILITY_' . strtoupper($tag); 525 526 if (\defined($constant)) { 527 return \constant($constant); 528 } 529 530 return Updater::STABILITY_STABLE; 531 } 532 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |