/libraries/joomla/installer/adapters/component.php
PHP | 1810 lines | 1023 code | 288 blank | 499 comment | 163 complexity | 7ae3306d694466c1cc74b6404906fde7 MD5 | raw file
Possible License(s): LGPL-2.1
Large files files are truncated, but you can click here to view the full file
1<?php 2/** 3 * @package Joomla.Platform 4 * @subpackage Installer 5 * 6 * @copyright Copyright (C) 2005 - 2012 Open Source Matters, Inc. All rights reserved. 7 * @license GNU General Public License version 2 or later; see LICENSE 8 */ 9 10defined('JPATH_PLATFORM') or die; 11 12jimport('joomla.base.adapterinstance'); 13jimport('joomla.filesystem.folder'); 14 15/** 16 * Component installer 17 * 18 * @package Joomla.Platform 19 * @subpackage Installer 20 * @since 11.1 21 */ 22class JInstallerComponent extends JAdapterInstance 23{ 24 /** 25 * Copy of the XML manifest file 26 * 27 * @var string 28 * @since 11.1 29 */ 30 protected $manifest = null; 31 32 /** 33 * Name of the extension 34 * 35 * @var string 36 * @since 11.1 37 * */ 38 protected $name = null; 39 40 /** 41 * The unique identifier for the extension (e.g. mod_login) 42 * 43 * @var string 44 * @since 11.1 45 * */ 46 protected $element = null; 47 48 /** 49 * The list of current files fo the Joomla! CMS administrator that are installed and is read 50 * from the manifest on disk in the update area to handle doing a diff 51 * and deleting files that are in the old files list and not in the new 52 * files list. 53 * 54 * @var array 55 * @since 11.1 56 * */ 57 protected $oldAdminFiles = null; 58 59 /** 60 * The list of current files that are installed and is read 61 * from the manifest on disk in the update area to handle doing a diff 62 * and deleting files that are in the old files list and not in the new 63 * files list. 64 * 65 * @var array 66 * @since 11.1 67 * */ 68 protected $oldFiles = null; 69 70 /** 71 * A path to the PHP file that the scriptfile declaration in 72 * the manifest refers to. 73 * 74 * @var string 75 * @since 11.1 76 * */ 77 protected $manifest_script = null; 78 79 /** 80 * For legacy installations this is a path to the PHP file that the scriptfile declaration in the 81 * manifest refers to. 82 * 83 * @var string 84 * @since 11.1 85 * */ 86 protected $install_script = null; 87 88 /** 89 * Custom loadLanguage method 90 * 91 * @param string $path The path language files are on. 92 * 93 * @return void 94 * 95 * @since 11.1 96 */ 97 public function loadLanguage($path = null) 98 { 99 $source = $this->parent->getPath('source'); 100 101 if (!$source) 102 { 103 $this->parent 104 ->setPath( 105 'source', 106 ($this->parent->extension->client_id ? JPATH_ADMINISTRATOR : JPATH_SITE) . 107 '/components/' . $this->parent->extension->element 108 ); 109 } 110 111 $this->manifest = $this->parent->getManifest(); 112 $name = strtolower(JFilterInput::getInstance()->clean((string) $this->manifest->name, 'cmd')); 113 114 if (substr($name, 0, 4) == 'com_') 115 { 116 $extension = $name; 117 } 118 else 119 { 120 $extension = 'com_' . $name; 121 } 122 123 $lang = JFactory::getLanguage(); 124 $source = $path ? $path : ($this->parent->extension->client_id ? JPATH_ADMINISTRATOR : JPATH_SITE) . '/components/' . $extension; 125 126 if ($this->manifest->administration->files) 127 { 128 $element = $this->manifest->administration->files; 129 } 130 elseif ($this->manifest->files) 131 { 132 $element = $this->manifest->files; 133 } 134 else 135 { 136 $element = null; 137 } 138 139 if ($element) 140 { 141 $folder = (string) $element->attributes()->folder; 142 143 if ($folder && file_exists($path . '/' . $folder)) 144 { 145 $source = $path . '/' . $folder; 146 } 147 } 148 $lang->load($extension . '.sys', $source, null, false, false) || $lang->load($extension . '.sys', JPATH_ADMINISTRATOR, null, false, false) 149 || $lang->load($extension . '.sys', $source, $lang->getDefault(), false, false) 150 || $lang->load($extension . '.sys', JPATH_ADMINISTRATOR, $lang->getDefault(), false, false); 151 } 152 153 /** 154 * Custom install method for components 155 * 156 * @return boolean True on success 157 * 158 * @since 11.1 159 */ 160 public function install() 161 { 162 // Get a database connector object 163 $db = $this->parent->getDbo(); 164 165 // Get the extension manifest object 166 $this->manifest = $this->parent->getManifest(); 167 168 /* 169 * --------------------------------------------------------------------------------------------- 170 * Manifest Document Setup Section 171 * --------------------------------------------------------------------------------------------- 172 */ 173 174 // Set the extension's name 175 $name = strtolower(JFilterInput::getInstance()->clean((string) $this->manifest->name, 'cmd')); 176 if (substr($name, 0, 4) == 'com_') 177 { 178 $element = $name; 179 } 180 else 181 { 182 $element = 'com_' . $name; 183 } 184 185 $this->set('name', $name); 186 $this->set('element', $element); 187 188 // Get the component description 189 $this->parent->set('message', JText::_((string) $this->manifest->description)); 190 191 // Set the installation target paths 192 $this->parent->setPath('extension_site', JPath::clean(JPATH_SITE . '/components/' . $this->get('element'))); 193 $this->parent->setPath('extension_administrator', JPath::clean(JPATH_ADMINISTRATOR . '/components/' . $this->get('element'))); 194 195 // Copy the admin path as it's used as a common base 196 $this->parent->setPath('extension_root', $this->parent->getPath('extension_administrator')); 197 198 /* 199 * --------------------------------------------------------------------------------------------- 200 * Basic Checks Section 201 * --------------------------------------------------------------------------------------------- 202 */ 203 204 // Make sure that we have an admin element 205 if (!$this->manifest->administration) 206 { 207 JLog::add(JText::_('JLIB_INSTALLER_ERROR_COMP_INSTALL_ADMIN_ELEMENT'), JLog::WARNING, 'jerror'); 208 return false; 209 } 210 211 /* 212 * --------------------------------------------------------------------------------------------- 213 * Filesystem Processing Section 214 * --------------------------------------------------------------------------------------------- 215 */ 216 217 /* 218 * If the component site or admin directory already exists, then we will assume that the component is already 219 * installed or another component is using that directory. 220 */ 221 222 if (file_exists($this->parent->getPath('extension_site')) || file_exists($this->parent->getPath('extension_administrator'))) 223 { 224 // Look for an update function or update tag 225 $updateElement = $this->manifest->update; 226 227 // Upgrade manually set or update function available or update tag detected 228 if ($this->parent->isUpgrade() || ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'update')) 229 || $updateElement) 230 { 231 // Transfer control to the update function 232 return $this->update(); 233 } 234 elseif (!$this->parent->isOverwrite()) 235 { 236 // Overwrite is set. 237 // We didn't have overwrite set, find an update function or find an update tag so lets call it safe 238 if (file_exists($this->parent->getPath('extension_site'))) 239 { 240 // If the site exists say so. 241 JLog::add( 242 JText::sprintf('JLIB_INSTALLER_ERROR_COMP_INSTALL_DIR_SITE', $this->parent->getPath('extension_site')), 243 JLog::WARNING, 'jerror' 244 ); 245 } 246 else 247 { 248 // If the admin exists say so 249 JLog::add( 250 JText::sprintf('JLIB_INSTALLER_ERROR_COMP_INSTALL_DIR_ADMIN', $this->parent->getPath('extension_administrator')), 251 JLog::WARNING, 'jerror' 252 ); 253 } 254 return false; 255 } 256 } 257 258 /* 259 * --------------------------------------------------------------------------------------------- 260 * Installer Trigger Loading 261 * --------------------------------------------------------------------------------------------- 262 */ 263 264 // If there is an manifest class file, lets load it; we'll copy it later (don't have dest yet) 265 $manifestScript = (string) $this->manifest->scriptfile; 266 267 if ($manifestScript) 268 { 269 $manifestScriptFile = $this->parent->getPath('source') . '/' . $manifestScript; 270 271 if (is_file($manifestScriptFile)) 272 { 273 // Load the file 274 include_once $manifestScriptFile; 275 } 276 277 // Set the class name 278 $classname = $this->get('element') . 'InstallerScript'; 279 280 if (class_exists($classname)) 281 { 282 // Create a new instance 283 $this->parent->manifestClass = new $classname($this); 284 285 // And set this so we can copy it later 286 $this->set('manifest_script', $manifestScript); 287 } 288 } 289 290 // Run preflight if possible (since we know we're not an update) 291 ob_start(); 292 ob_implicit_flush(false); 293 294 if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'preflight')) 295 { 296 if ($this->parent->manifestClass->preflight('install', $this) === false) 297 { 298 // Install failed, rollback changes 299 $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_INSTALL_CUSTOM_INSTALL_FAILURE')); 300 return false; 301 } 302 } 303 304 // Create msg object; first use here 305 $msg = ob_get_contents(); 306 ob_end_clean(); 307 308 // If the component directory does not exist, let's create it 309 $created = false; 310 311 if (!file_exists($this->parent->getPath('extension_site'))) 312 { 313 if (!$created = JFolder::create($this->parent->getPath('extension_site'))) 314 { 315 JLog::add( 316 JText::sprintf('JLIB_INSTALLER_ERROR_COMP_INSTALL_FAILED_TO_CREATE_DIRECTORY_SITE', $this->parent->getPath('extension_site')), 317 JLog::WARNING, 'jerror' 318 ); 319 return false; 320 } 321 } 322 323 /* 324 * Since we created the component directory and we will want to remove it if we have to roll back 325 * the installation, let's add it to the installation step stack 326 */ 327 if ($created) 328 { 329 $this->parent->pushStep(array('type' => 'folder', 'path' => $this->parent->getPath('extension_site'))); 330 } 331 332 // If the component admin directory does not exist, let's create it 333 $created = false; 334 335 if (!file_exists($this->parent->getPath('extension_administrator'))) 336 { 337 if (!$created = JFolder::create($this->parent->getPath('extension_administrator'))) 338 { 339 JLog::add( 340 JText::sprintf('JLIB_INSTALLER_ERROR_COMP_INSTALL_FAILED_TO_CREATE_DIRECTORY_ADMIN', $this->parent->getPath('extension_administrator')), 341 JLog::WARNING, 'jerror' 342 ); 343 344 // Install failed, rollback any changes 345 $this->parent->abort(); 346 347 return false; 348 } 349 } 350 351 /* 352 * Since we created the component admin directory and we will want to remove it if we have to roll 353 * back the installation, let's add it to the installation step stack 354 */ 355 if ($created) 356 { 357 $this->parent->pushStep(array('type' => 'folder', 'path' => $this->parent->getPath('extension_administrator'))); 358 } 359 360 // Copy site files 361 if ($this->manifest->files) 362 { 363 if ($this->parent->parseFiles($this->manifest->files) === false) 364 { 365 // Install failed, rollback any changes 366 $this->parent->abort(); 367 368 return false; 369 } 370 } 371 372 // Copy admin files 373 if ($this->manifest->administration->files) 374 { 375 if ($this->parent->parseFiles($this->manifest->administration->files, 1) === false) 376 { 377 // Install failed, rollback any changes 378 $this->parent->abort(); 379 380 return false; 381 } 382 } 383 384 // Parse optional tags 385 $this->parent->parseMedia($this->manifest->media); 386 $this->parent->parseLanguages($this->manifest->languages); 387 $this->parent->parseLanguages($this->manifest->administration->languages, 1); 388 389 // If there is a manifest script, let's copy it. 390 if ($this->get('manifest_script')) 391 { 392 $path['src'] = $this->parent->getPath('source') . '/' . $this->get('manifest_script'); 393 $path['dest'] = $this->parent->getPath('extension_administrator') . '/' . $this->get('manifest_script'); 394 395 if (!file_exists($path['dest']) || $this->parent->isOverwrite()) 396 { 397 if (!$this->parent->copyFiles(array($path))) 398 { 399 // Install failed, rollback changes 400 $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_INSTALL_MANIFEST')); 401 402 return false; 403 } 404 } 405 } 406 407 /* 408 * --------------------------------------------------------------------------------------------- 409 * Database Processing Section 410 * --------------------------------------------------------------------------------------------- 411 */ 412 413 // Run the install queries for the component 414 if (isset($this->manifest->install->sql)) 415 { 416 $result = $this->parent->parseSQLFiles($this->manifest->install->sql); 417 418 if ($result === false) 419 { 420 // Install failed, rollback changes 421 $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_COMP_INSTALL_SQL_ERROR', $db->stderr(true))); 422 423 return false; 424 } 425 } 426 427 /** 428 * --------------------------------------------------------------------------------------------- 429 * Custom Installation Script Section 430 * --------------------------------------------------------------------------------------------- 431 */ 432 433 /* 434 * If we have an install script, let's include it, execute the custom 435 * install method, and append the return value from the custom install 436 * method to the installation message. 437 */ 438 ob_start(); 439 ob_implicit_flush(false); 440 441 if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'install')) 442 { 443 if ($this->parent->manifestClass->install($this) === false) 444 { 445 // Install failed, rollback changes 446 $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_INSTALL_CUSTOM_INSTALL_FAILURE')); 447 448 return false; 449 } 450 } 451 452 // Append messages 453 $msg .= ob_get_contents(); 454 ob_end_clean(); 455 456 /** 457 * --------------------------------------------------------------------------------------------- 458 * Finalization and Cleanup Section 459 * --------------------------------------------------------------------------------------------- 460 */ 461 462 // Add an entry to the extension table with a whole heap of defaults 463 $row = JTable::getInstance('extension'); 464 $row->set('name', $this->get('name')); 465 $row->set('type', 'component'); 466 $row->set('element', $this->get('element')); 467 468 // There is no folder for components 469 $row->set('folder', ''); 470 $row->set('enabled', 1); 471 $row->set('protected', 0); 472 $row->set('access', 0); 473 $row->set('client_id', 1); 474 $row->set('params', $this->parent->getParams()); 475 $row->set('manifest_cache', $this->parent->generateManifestCache()); 476 477 if (!$row->store()) 478 { 479 // Install failed, roll back changes 480 $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_COMP_INSTALL_ROLLBACK', $db->stderr(true))); 481 return false; 482 } 483 484 $eid = $row->extension_id; 485 486 // Clobber any possible pending updates 487 $update = JTable::getInstance('update'); 488 $uid = $update->find(array('element' => $this->get('element'), 'type' => 'component', 'client_id' => 1, 'folder' => '')); 489 490 if ($uid) 491 { 492 $update->delete($uid); 493 } 494 495 // We will copy the manifest file to its appropriate place. 496 if (!$this->parent->copyManifest()) 497 { 498 // Install failed, rollback changes 499 $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_INSTALL_COPY_SETUP')); 500 return false; 501 } 502 503 // Time to build the admin menus 504 if (!$this->_buildAdminMenus($row->extension_id)) 505 { 506 JLog::add(JText::_('JLIB_INSTALLER_ABORT_COMP_BUILDADMINMENUS_FAILED'), JLog::WARNING, 'jerror'); 507 508 // @todo remove code: $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_COMP_INSTALL_ROLLBACK', $db->stderr(true))); 509 // @todo remove code: return false; 510 } 511 512 // Set the schema version to be the latest update version 513 if ($this->manifest->update) 514 { 515 $this->parent->setSchemaVersion($this->manifest->update->schemas, $eid); 516 } 517 518 // Register the component container just under root in the assets table. 519 $asset = JTable::getInstance('Asset'); 520 $asset->name = $row->element; 521 $asset->parent_id = 1; 522 $asset->rules = '{}'; 523 $asset->title = $row->name; 524 $asset->setLocation(1, 'last-child'); 525 if (!$asset->store()) 526 { 527 // Install failed, roll back changes 528 $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_COMP_INSTALL_ROLLBACK', $db->stderr(true))); 529 return false; 530 } 531 532 // And now we run the postflight 533 ob_start(); 534 ob_implicit_flush(false); 535 536 if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'postflight')) 537 { 538 $this->parent->manifestClass->postflight('install', $this); 539 } 540 541 // Append messages 542 $msg .= ob_get_contents(); 543 ob_end_clean(); 544 545 if ($msg != '') 546 { 547 $this->parent->set('extension_message', $msg); 548 } 549 550 return $row->extension_id; 551 } 552 553 /** 554 * Custom update method for components 555 * 556 * @return boolean True on success 557 * 558 * @since 11.1 559 */ 560 public function update() 561 { 562 // Get a database connector object 563 $db = $this->parent->getDbo(); 564 565 // Set the overwrite setting 566 $this->parent->setOverwrite(true); 567 568 // Get the extension manifest object 569 $this->manifest = $this->parent->getManifest(); 570 571 /** 572 * --------------------------------------------------------------------------------------------- 573 * Manifest Document Setup Section 574 * --------------------------------------------------------------------------------------------- 575 */ 576 577 // Set the extension's name 578 $name = strtolower(JFilterInput::getInstance()->clean((string) $this->manifest->name, 'cmd')); 579 if (substr($name, 0, 4) == 'com_') 580 { 581 $element = $name; 582 } 583 else 584 { 585 $element = 'com_' . $name; 586 } 587 588 $this->set('name', $name); 589 $this->set('element', $element); 590 591 // Get the component description 592 $description = (string) $this->manifest->description; 593 594 if ($description) 595 { 596 $this->parent->set('message', JText::_($description)); 597 } 598 else 599 { 600 $this->parent->set('message', ''); 601 } 602 603 // Set the installation target paths 604 $this->parent->setPath('extension_site', JPath::clean(JPATH_SITE . '/components/' . $this->get('element'))); 605 $this->parent->setPath('extension_administrator', JPath::clean(JPATH_ADMINISTRATOR . '/components/' . $this->get('element'))); 606 607 // Copy the admin path as it's used as a common base 608 $this->parent->setPath('extension_root', $this->parent->getPath('extension_administrator')); 609 610 // Hunt for the original XML file 611 $old_manifest = null; 612 613 // Create a new installer because findManifest sets stuff 614 // Look in the administrator first 615 $tmpInstaller = new JInstaller; 616 $tmpInstaller->setPath('source', $this->parent->getPath('extension_administrator')); 617 618 if (!$tmpInstaller->findManifest()) 619 { 620 // Then the site 621 $tmpInstaller->setPath('source', $this->parent->getPath('extension_site')); 622 if ($tmpInstaller->findManifest()) 623 { 624 $old_manifest = $tmpInstaller->getManifest(); 625 } 626 } 627 else 628 { 629 $old_manifest = $tmpInstaller->getManifest(); 630 } 631 632 // Should do this above perhaps? 633 if ($old_manifest) 634 { 635 $this->oldAdminFiles = $old_manifest->administration->files; 636 $this->oldFiles = $old_manifest->files; 637 } 638 else 639 { 640 $this->oldAdminFiles = null; 641 $this->oldFiles = null; 642 } 643 644 /** 645 * --------------------------------------------------------------------------------------------- 646 * Basic Checks Section 647 * --------------------------------------------------------------------------------------------- 648 */ 649 650 // Make sure that we have an admin element 651 if (!$this->manifest->administration) 652 { 653 JLog::add(JText::_('JLIB_INSTALLER_ABORT_COMP_UPDATE_ADMIN_ELEMENT'), JLog::WARNING, 'jerror'); 654 return false; 655 } 656 657 /** 658 * --------------------------------------------------------------------------------------------- 659 * Installer Trigger Loading 660 * --------------------------------------------------------------------------------------------- 661 */ 662 663 // If there is an manifest class file, lets load it; we'll copy it later (don't have dest yet) 664 $manifestScript = (string) $this->manifest->scriptfile; 665 666 if ($manifestScript) 667 { 668 $manifestScriptFile = $this->parent->getPath('source') . '/' . $manifestScript; 669 670 if (is_file($manifestScriptFile)) 671 { 672 // Load the file 673 include_once $manifestScriptFile; 674 } 675 676 // Set the class name 677 $classname = $element . 'InstallerScript'; 678 679 if (class_exists($classname)) 680 { 681 // Create a new instance 682 $this->parent->manifestClass = new $classname($this); 683 684 // And set this so we can copy it later 685 $this->set('manifest_script', $manifestScript); 686 } 687 } 688 689 // Run preflight if possible (since we know we're not an update) 690 ob_start(); 691 ob_implicit_flush(false); 692 693 if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'preflight')) 694 { 695 if ($this->parent->manifestClass->preflight('update', $this) === false) 696 { 697 // Install failed, rollback changes 698 $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_INSTALL_CUSTOM_INSTALL_FAILURE')); 699 700 return false; 701 } 702 } 703 704 // Create msg object; first use here 705 $msg = ob_get_contents(); 706 ob_end_clean(); 707 708 /** 709 * --------------------------------------------------------------------------------------------- 710 * Filesystem Processing Section 711 * --------------------------------------------------------------------------------------------- 712 */ 713 714 // If the component directory does not exist, let's create it 715 $created = false; 716 717 if (!file_exists($this->parent->getPath('extension_site'))) 718 { 719 if (!$created = JFolder::create($this->parent->getPath('extension_site'))) 720 { 721 JLog::add( 722 JText::sprintf('JLIB_INSTALLER_ERROR_COMP_UPDATE_FAILED_TO_CREATE_DIRECTORY_SITE', $this->parent->getPath('extension_site')), 723 JLog::WARNING, 'jerror' 724 ); 725 return false; 726 } 727 } 728 729 /* 730 * Since we created the component directory and will want to remove it if we have to roll back 731 * the installation, lets add it to the installation step stack 732 */ 733 if ($created) 734 { 735 $this->parent->pushStep(array('type' => 'folder', 'path' => $this->parent->getPath('extension_site'))); 736 } 737 738 // If the component admin directory does not exist, let's create it 739 $created = false; 740 741 if (!file_exists($this->parent->getPath('extension_administrator'))) 742 { 743 if (!$created = JFolder::create($this->parent->getPath('extension_administrator'))) 744 { 745 JLog::add( 746 JText::sprintf('JLIB_INSTALLER_ERROR_COMP_UPDATE_FAILED_TO_CREATE_DIRECTORY_ADMIN', $this->parent->getPath('extension_administrator')), 747 JLog::WARNING, 'jerror' 748 ); 749 750 // Install failed, rollback any changes 751 $this->parent->abort(); 752 753 return false; 754 } 755 } 756 757 /* 758 * Since we created the component admin directory and we will want to remove it if we have to roll 759 * back the installation, let's add it to the installation step stack 760 */ 761 if ($created) 762 { 763 $this->parent->pushStep(array('type' => 'folder', 'path' => $this->parent->getPath('extension_administrator'))); 764 } 765 766 // Find files to copy 767 if ($this->manifest->files) 768 { 769 if ($this->parent->parseFiles($this->manifest->files, 0, $this->oldFiles) === false) 770 { 771 // Install failed, rollback any changes 772 $this->parent->abort(); 773 774 return false; 775 } 776 } 777 778 if ($this->manifest->administration->files) 779 { 780 if ($this->parent->parseFiles($this->manifest->administration->files, 1, $this->oldAdminFiles) === false) 781 { 782 // Install failed, rollback any changes 783 $this->parent->abort(); 784 785 return false; 786 } 787 } 788 789 // Parse optional tags 790 $this->parent->parseMedia($this->manifest->media); 791 $this->parent->parseLanguages($this->manifest->languages); 792 $this->parent->parseLanguages($this->manifest->administration->languages, 1); 793 794 // If there is a manifest script, let's copy it. 795 if ($this->get('manifest_script')) 796 { 797 $path['src'] = $this->parent->getPath('source') . '/' . $this->get('manifest_script'); 798 $path['dest'] = $this->parent->getPath('extension_administrator') . '/' . $this->get('manifest_script'); 799 800 if (!file_exists($path['dest']) || $this->parent->isOverwrite()) 801 { 802 if (!$this->parent->copyFiles(array($path))) 803 { 804 // Install failed, rollback changes 805 $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_UPDATE_MANIFEST')); 806 807 return false; 808 } 809 } 810 } 811 812 /** 813 * --------------------------------------------------------------------------------------------- 814 * Database Processing Section 815 * --------------------------------------------------------------------------------------------- 816 */ 817 818 // Let's run the update queries for the component 819 $row = JTable::getInstance('extension'); 820 $eid = $row->find(array('element' => strtolower($this->get('element')), 'type' => 'component')); 821 822 if ($this->manifest->update) 823 { 824 $result = $this->parent->parseSchemaUpdates($this->manifest->update->schemas, $eid); 825 826 if ($result === false) 827 { 828 // Install failed, rollback changes 829 $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_COMP_UPDATE_SQL_ERROR', $db->stderr(true))); 830 831 return false; 832 } 833 } 834 835 // Time to build the admin menus 836 if (!$this->_buildAdminMenus($eid)) 837 { 838 JLog::add(JText::_('JLIB_INSTALLER_ABORT_COMP_BUILDADMINMENUS_FAILED'), JLog::WARNING, 'jerror'); 839 840 // $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_COMP_INSTALL_ROLLBACK', $db->stderr(true))); 841 // Return false; 842 } 843 844 /** 845 * --------------------------------------------------------------------------------------------- 846 * Custom Installation Script Section 847 * --------------------------------------------------------------------------------------------- 848 */ 849 850 /* 851 * If we have an install script, let's include it, execute the custom 852 * update method, and append the return value from the custom update 853 * method to the installation message. 854 */ 855 ob_start(); 856 ob_implicit_flush(false); 857 858 if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'update')) 859 { 860 if ($this->parent->manifestClass->update($this) === false) 861 { 862 // Install failed, rollback changes 863 $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_INSTALL_CUSTOM_INSTALL_FAILURE')); 864 865 return false; 866 } 867 } 868 869 // Append messages 870 $msg .= ob_get_contents(); 871 ob_end_clean(); 872 873 /** 874 * --------------------------------------------------------------------------------------------- 875 * Finalization and Cleanup Section 876 * --------------------------------------------------------------------------------------------- 877 */ 878 879 // Clobber any possible pending updates 880 $update = JTable::getInstance('update'); 881 $uid = $update->find(array('element' => $this->get('element'), 'type' => 'component', 'client_id' => 1, 'folder' => '')); 882 883 if ($uid) 884 { 885 $update->delete($uid); 886 } 887 888 // Update an entry to the extension table 889 if ($eid) 890 { 891 $row->load($eid); 892 } 893 else 894 { 895 // Set the defaults 896 // There is no folder for components 897 $row->folder = ''; 898 $row->enabled = 1; 899 $row->protected = 0; 900 $row->access = 1; 901 $row->client_id = 1; 902 $row->params = $this->parent->getParams(); 903 } 904 905 $row->name = $this->get('name'); 906 $row->type = 'component'; 907 $row->element = $this->get('element'); 908 $row->manifest_cache = $this->parent->generateManifestCache(); 909 910 if (!$row->store()) 911 { 912 // Install failed, roll back changes 913 $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_COMP_UPDATE_ROLLBACK', $db->stderr(true))); 914 915 return false; 916 } 917 918 // We will copy the manifest file to its appropriate place. 919 if (!$this->parent->copyManifest()) 920 { 921 // Install failed, rollback changes 922 $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_UPDATE_COPY_SETUP')); 923 924 return false; 925 } 926 927 // And now we run the postflight 928 ob_start(); 929 ob_implicit_flush(false); 930 931 if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'postflight')) 932 { 933 $this->parent->manifestClass->postflight('update', $this); 934 } 935 936 // Append messages 937 $msg .= ob_get_contents(); 938 ob_end_clean(); 939 940 if ($msg != '') 941 { 942 $this->parent->set('extension_message', $msg); 943 } 944 945 return $row->extension_id; 946 } 947 948 /** 949 * Custom uninstall method for components 950 * 951 * @param integer $id The unique extension id of the component to uninstall 952 * 953 * @return mixed Return value for uninstall method in component uninstall file 954 * 955 * @since 11.1 956 */ 957 public function uninstall($id) 958 { 959 $db = $this->parent->getDbo(); 960 $row = null; 961 $retval = true; 962 963 // First order of business will be to load the component object table from the database. 964 // This should give us the necessary information to proceed. 965 $row = JTable::getInstance('extension'); 966 if (!$row->load((int) $id)) 967 { 968 JLog::add(JText::_('JLIB_INSTALLER_ERROR_COMP_UNINSTALL_ERRORUNKOWNEXTENSION'), JLog::WARNING, 'jerror'); 969 return false; 970 } 971 972 // Is the component we are trying to uninstall a core one? 973 // Because that is not a good idea... 974 if ($row->protected) 975 { 976 JLog::add(JText::_('JLIB_INSTALLER_ERROR_COMP_UNINSTALL_WARNCORECOMPONENT'), JLog::WARNING, 'jerror'); 977 return false; 978 } 979 980 // Get the admin and site paths for the component 981 $this->parent->setPath('extension_administrator', JPath::clean(JPATH_ADMINISTRATOR . '/components/' . $row->element)); 982 $this->parent->setPath('extension_site', JPath::clean(JPATH_SITE . '/components/' . $row->element)); 983 984 // Copy the admin path as it's used as a common base 985 $this->parent->setPath('extension_root', $this->parent->getPath('extension_administrator')); 986 987 /** 988 * --------------------------------------------------------------------------------------------- 989 * Manifest Document Setup Section 990 * --------------------------------------------------------------------------------------------- 991 */ 992 993 // Find and load the XML install file for the component 994 $this->parent->setPath('source', $this->parent->getPath('extension_administrator')); 995 996 // Get the package manifest object 997 // We do findManifest to avoid problem when uninstalling a list of extension: getManifest cache its manifest file 998 $this->parent->findManifest(); 999 $this->manifest = $this->parent->getManifest(); 1000 1001 if (!$this->manifest) 1002 { 1003 // Make sure we delete the folders if no manifest exists 1004 JFolder::delete($this->parent->getPath('extension_administrator')); 1005 JFolder::delete($this->parent->getPath('extension_site')); 1006 1007 // Remove the menu 1008 $this->_removeAdminMenus($row); 1009 1010 // Raise a warning 1011 JLog::add(JText::_('JLIB_INSTALLER_ERROR_COMP_UNINSTALL_ERRORREMOVEMANUALLY'), JLog::WARNING, 'jerror'); 1012 1013 // Return 1014 return false; 1015 } 1016 1017 // Set the extensions name 1018 $name = strtolower(JFilterInput::getInstance()->clean((string) $this->manifest->name, 'cmd')); 1019 if (substr($name, 0, 4) == 'com_') 1020 { 1021 $element = $name; 1022 } 1023 else 1024 { 1025 $element = 'com_' . $name; 1026 } 1027 1028 $this->set('name', $name); 1029 $this->set('element', $element); 1030 1031 // Attempt to load the admin language file; might have uninstall strings 1032 $this->loadLanguage(JPATH_ADMINISTRATOR . '/components/' . $element); 1033 1034 /** 1035 * --------------------------------------------------------------------------------------------- 1036 * Installer Trigger Loading and Uninstall 1037 * --------------------------------------------------------------------------------------------- 1038 */ 1039 1040 // If there is an manifest class file, lets load it; we'll copy it later (don't have dest yet) 1041 $scriptFile = (string) $this->manifest->scriptfile; 1042 1043 if ($scriptFile) 1044 { 1045 $manifestScriptFile = $this->parent->getPath('source') . '/' . $scriptFile; 1046 1047 if (is_file($manifestScriptFile)) 1048 { 1049 // Load the file 1050 include_once $manifestScriptFile; 1051 } 1052 1053 // Set the class name 1054 $classname = $row->element . 'InstallerScript'; 1055 1056 if (class_exists($classname)) 1057 { 1058 // Create a new instance 1059 $this->parent->manifestClass = new $classname($this); 1060 1061 // And set this so we can copy it later 1062 $this->set('manifest_script', $scriptFile); 1063 } 1064 } 1065 1066 ob_start(); 1067 ob_implicit_flush(false); 1068 1069 // Run uninstall if possible 1070 if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'uninstall')) 1071 { 1072 $this->parent->manifestClass->uninstall($this); 1073 } 1074 1075 $msg = ob_get_contents(); 1076 ob_end_clean(); 1077 1078 if ($msg != '') 1079 { 1080 $this->parent->set('extension_message', $msg); 1081 } 1082 1083 /** 1084 * --------------------------------------------------------------------------------------------- 1085 * Database Processing Section 1086 * --------------------------------------------------------------------------------------------- 1087 */ 1088 1089 // Let's run the uninstall queries for the component 1090 if (isset($this->manifest->uninstall->sql)) 1091 { 1092 $result = $this->parent->parseSQLFiles($this->manifest->uninstall->sql); 1093 1094 if ($result === false) 1095 { 1096 // Install failed, rollback changes 1097 JLog::add(JText::sprintf('JLIB_INSTALLER_ERROR_COMP_UNINSTALL_SQL_ERROR', $db->stderr(true)), JLog::WARNING, 'jerror'); 1098 $retval = false; 1099 } 1100 } 1101 1102 $this->_removeAdminMenus($row); 1103 1104 /** 1105 * --------------------------------------------------------------------------------------------- 1106 * Filesystem Processing Section 1107 * --------------------------------------------------------------------------------------------- 1108 */ 1109 1110 // Let's remove those language files and media in the JROOT/images/ folder that are 1111 // associated with the component we are uninstalling 1112 $this->parent->removeFiles($this->manifest->media); 1113 $this->parent->removeFiles($this->manifest->languages); 1114 $this->parent->removeFiles($this->manifest->administration->languages, 1); 1115 1116 // Remove the schema version 1117 $query = $db->getQuery(true); 1118 $query->delete()->from('#__schemas')->where('extension_id = ' . $id); 1119 $db->setQuery($query); 1120 $db->execute(); 1121 1122 // Remove the component container in the assets table. 1123 $asset = JTable::getInstance('Asset'); 1124 if ($asset->loadByName($element)) 1125 { 1126 $asset->delete(); 1127 } 1128 1129 // Remove categories for this component 1130 $query = $db->getQuery(true); 1131 $query->delete()->from('#__categories')->where('extension=' . $db->quote($element), 'OR') 1132 ->where('extension LIKE ' . $db->quote($element . '.%')); 1133 $db->setQuery($query); 1134 $db->execute(); 1135 1136 // Clobber any possible pending updates 1137 $update = JTable::getInstance('update'); 1138 $uid = $update->find(array('element' => $row->element, 'type' => 'component', 'client_id' => 1, 'folder' => '')); 1139 1140 if ($uid) 1141 { 1142 $update->delete($uid); 1143 } 1144 1145 // Now we need to delete the installation directories. This is the final step in uninstalling the component. 1146 if (trim($row->element)) 1147 { 1148 // Delete the component site directory 1149 if (is_dir($this->parent->getPath('extension_site'))) 1150 { 1151 if (!JFolder::delete($this->parent->getPath('extension_site'))) 1152 { 1153 JLog::add(JText::_('JLIB_INSTALLER_ERROR_COMP_UNINSTALL_FAILED_REMOVE_DIRECTORY_SITE'), JLog::WARNING, 'jerror'); 1154 $retval = false; 1155 } 1156 } 1157 1158 // Delete the component admin directory 1159 if (is_dir($this->parent->getPath('extension_administrator'))) 1160 { 1161 if (!JFolder::delete($this->parent->getPath('extension_administrator'))) 1162 { 1163 JLog::add(JText::_('JLIB_INSTALLER_ERROR_COMP_UNINSTALL_FAILED_REMOVE_DIRECTORY_ADMIN'), JLog::WARNING, 'jerror'); 1164 $retval = false; 1165 } 1166 } 1167 1168 // Now we will no longer need the extension object, so let's delete it and free up memory 1169 $row->delete($row->extension_id); 1170 unset($row); 1171 1172 return $retval; 1173 } 1174 else 1175 { 1176 // No component option defined... cannot delete what we don't know about 1177 JLog::add(JText::_('JLIB_INSTALLER_ERROR_COMP_UNINSTALL_NO_OPTION'), JLog::WARNING, 'jerror'); 1178 return false; 1179 } 1180 } 1181 1182 /** 1183 * Method to build menu database entries for a component 1184 * 1185 * @return boolean True if successful 1186 * 1187 * @since 11.1 1188 */ 1189 protected function _buildAdminMenus() 1190 { 1191 $db = $this->parent->getDbo(); 1192 $table = JTable::getInstance('menu'); 1193 $option = $this->get('element'); 1194 1195 // If a component exists with this option in the table then we don't need to add menus 1196 $query = $db->getQuery(true); 1197 $query->select('m.id, e.extension_id'); 1198 $query->from('#__menu AS m'); 1199 $query->leftJoin('#__extensions AS e ON m.component_id = e.extension_id'); 1200 $query->where('m.parent_id = 1'); 1201 $query->where('m.client_id = 1'); 1202 $query->where('e.element = ' . $db->quote($option)); 1203 1204 $db->setQuery($query); 1205 1206 $componentrow = $db->loadObject(); 1207 1208 // Check if menu items exist 1209 if ($componentrow) 1210 { 1211 // Don't do anything if overwrite has not been enabled 1212 if (!$this->parent->isOverwrite()) 1213 { 1214 return true; 1215 } 1216 1217 // Remove existing menu items if overwrite has been enabled 1218 if ($option) 1219 { 1220 // If something goes wrong, there's no way to rollback TODO: Search for better solution 1221 $this->_removeAdminMenus($componentrow); 1222 } 1223 1224 $component_id = $componentrow->extension_id; 1225 } 1226 else 1227 { 1228 // Lets find the extension id 1229 $query->clear(); 1230 $query->select('e.extension_id'); 1231 $query->from('#__extensions AS e'); 1232 $query->where('e.element = ' . $db->quote($option)); 1233 1234 $db->setQuery($query); 1235 1236 // TODO Find Some better way to discover the component_id 1237 $component_id = $db->loadResult(); 1238 } 1239 1240 // Ok, now its time to handle the menus. Start with the component root menu, then handle submenus. 1241 $menuElement = $this->manifest->administration->menu; 1242 1243 if ($menuElement) 1244 { 1245 $data = array(); 1246 $data['menutype'] = 'main'; 1247 $data['client_id'] = 1; 1248 $data['title'] = (string) $menuElement; 1249 $data['alias'] = (string) $menuElement; 1250 $data['link'] = 'index.php?option=' . $option; 1251 $data['type'] = 'component'; 1252 $data['published'] = 0; 1253 $data['parent_id'] = 1; 1254 $data['component_id'] = $component_id; 1255 $data['img'] = ((string) $menuElement->attributes()->img) ? (string) $menuElement->attributes()->img : 'class:component'; 1256 $data['home'] = 0; 1257 1258 try 1259 { 1260 $table->setLocation(1, 'last-child'); 1261 } 1262 catch (InvalidArgumentException $e) 1263 { 1264 JLog::add($e->getMessage(), JLog::WARNING, 'jerror'); 1265 return false; 1266 } 1267 1268 if (!$table->bind($data) || !$table->check() || !$table->store()) 1269 { 1270 // Install failed, warn user and rollback changes 1271 JLog::add($table->getError(), JLog::WARNING, 'jerror'); 1272 return false; 1273 } 1274 1275 /* 1276 * Since we have created a menu item, we add it to the installation step stack 1277 * so that if we have to rollback the changes we can undo it. 1278 */ 1279 $this->parent->pushStep(array('type' => 'menu', 'id' => $component_id)); 1280 } 1281 // No menu element was specified, Let's make a generic menu item 1282 else 1283 { 1284 $data = array(); 1285 $data['menutype'] = 'main'; 1286 $data['client_id'] = 1; 1287 $data['title'] = $option; 1288 $data['alias'] = $option; 1289 $data['link'] = 'index.php?option=' . $option; 1290 $data['type'] = 'component'; 1291 $data['published'] = 0; 1292 $data['parent_id'] = 1; 1293 $data['component_id'] = $component_id; 1294 $data['img'] = 'class:component'; 1295 $data['home'] = 0; 1296 1297 try 1298 { 1299 $table->setLocation(1, 'last-child'); 1300 } 1301 catch (InvalidArgumentException $e) 1302 { 1303 JLog::add($e->getMessage(), JLog::WARNING, 'jerror'); 1304 return false; 1305 } 1306 1307 if (!$table->bind($data) || !$table->check() || !$table->store()) 1308 { 1309 // Install failed, warn user and rollback changes 1310 JLog::add($table->getError(), JLog::WARNING, 'jerror'); 1311 return false; 1312 } 1313 1314 /* 1315 * Since we have created a menu item, we add it to the installation step stack 1316 * so that if we have to rollback the changes we can undo it. 1317 */ 1318 $this->parent->pushStep(array('type' => 'menu', 'id' => $component_id)); 1319 } 1320 1321 /* 1322 * Process SubMenus 1323 */ 1324 1325 if (!$this->manifest->administration->submenu) 1326 { 1327 return true; 1328 } 1329 1330 $parent_id = $table->id; 1331 1332 foreach ($this->manifest->administration->submenu->menu as $child) 1333 { 1334 $data = array(); 1335 $data['menutype'] = 'main'; 1336 $data['client_id'] = 1; 1337 $data['title'] = (string) $child; 1338 $data['alias'] = (string) $child; 1339 $data['type'] = 'component'; 1340 $data['published'] = 0; 1341 $data['parent_id'] = $parent_id; 1342 $data['component_id'] = $component_id; 1343 $data['img'] = ((string) $child->attributes()->img) ? (string) $child->attributes()->img : 'class:component'; 1344 $data['home'] = 0; 1345 1346 // Set the sub menu link 1347 if ((string) $child->attributes()->link) 1348 { 1349 $data['link'] = 'index.php?' . $child->attributes()->link; 1350 } 1351 else 1352 { 1353 $request = array(); 1354 1355 if ((string) $child->attributes()->act) 1356 { 1357 $request[] = 'act=' . $child->attributes()->act; 1358 } 1359 1360 if ((string) $child->attributes()->task) 1361 { 1362 $request[] = 'task=' . $child->attributes()->task; 1363 } 1364 1365 if ((string) $child->attributes()->controller) 1366 { 1367 $request[] = 'controller=' . $child->attributes()->controller; 1368 } 1369 1370 if ((string) $child->attributes()->view) 1371 { 1372 $request[] = 'view=' . $child->attributes()->view; 1373 } 1374 1375 if ((string) $child->attributes()->layout) 1376 { 1377 $request[] = 'layout=' . $child->attributes()->layout; 1378 } 1379 1380 if ((string) $child->attributes()->sub) 1381 { 1382 $request[] = 'sub=' . $child->attributes()->sub; 1383 } 1384 1385 $qstring = (count($request)) ? '&' . implode('&', $request) : ''; 1386 $data['link'] = 'index.php?option=' . $option . $qstring; 1387 } 1388 1389 $table = JTable::getInstance('menu'); 1390 1391 try 1392 { 1393 $table->setLocation($parent_id, 'last-child'); 1394 } 1395 catch (InvalidArgumentException $e) 1396 { 1397 return false; 1398 } 1399 1400 if (!$table->bind($data) || !$table->check() || !$table->store()) 1401 { 1402 // Install failed, rollback changes 1403 return false; 1404 } 1405 1406 /* 1407 * Since we have created a menu item, we add it to the installation step stack 1408 * so that if we have to rollback the changes we can undo it. 1409 */ 1410 $this->parent->pushStep(array('type' => 'menu', 'id' => $component_id)); 1411 } 1412 1413 return true; 1414 } 1415 1416 /** 1417 * Method to remove admin menu references to a component 1418 * 1419 * @param object &$row Component table object. 1420 * 1421 * @return boolean True if successful. 1422 * 1423 * @since 11.1 1424 */ 1425 protected function _removeAdminMenus(&$row) 1426 { 1427 $db = $this->parent->getDbo(); 1428 $table = JTable::getInstance('menu'); 1429 $id = $row->extension_id; 1430 1431 // Get the ids of the menu items 1432 $query = $db->getQuery(true); 1433 $query->select('id'); 1434 $query->from('#__menu'); 1435 $query->where($query->qn('client_id') . ' = 1'); 1436 $query->where($query->qn('component_id') . ' = ' . (int) $id); 1437 1438 $db->setQuery($query); 1439 1440 $ids = $db->loadColumn(); 1441 1442 // Check for error 1443 if (!empty($ids)) 1444 { 1445 // Iterate the items to delete each one. 1446 foreach ($ids as $menuid) 1447 { 1448 if (!$table->delete((int) $menuid)) 1449 { 1450 $this->setError($table->getError()); 1451 return false; 1452 } 1453 } 1454 // Rebuild the whole tree 1455 $table->rebuild(); 1456 1457 } 1458 return true; 1459 } 1460 1461 /** 1462 * Custom rollback method 1463 * - Roll back the component menu item 1464 * 1465 * @param array $step Installation step to rollback. 1466 * 1467 * @return boolean True on success 1468 * 1469 * @since 11.1 1470 */ 1471 protected function _rollback_menu($step) 1472 { 1473 return $this->_removeAdminMenus((object) array('extension_id' => $step['id'])); 1474 } 1475 1476 /** 1477 * Discover unregistered extensions. 1478 * 1479 * @return array A list of extensions. 1480 * 1481 * @since 11.1 1482 */ 1483 public function discover() 1484 { 1485 $results = array(); 1486 $site_components = JFolder::folders(JPATH_SITE . '/components'); 1487 $admin_components = JFolder::folders(JPATH_ADMINISTRATOR . '/components'); 1488 1489 foreach ($site_components as $component) 1490 { 1491 if (file_exists(JPATH_SITE . '/components/' . $component . '/' . str_replace('com_', '', $component) . '.xml')) 1492 { 1493 $manifest_details = JInstaller::parseXMLInstallFile( 1494 JPATH_SITE . '/components/' . $component . '/' . str_replace('com_', '', $component) . '.xml' 1495 ); 1496 $extension = JTable::getInstance('extension'); 1497 $extension->set('type', 'component'); 1498 $extension->set('client_id', 0); 1499 $extension->set('element', $component); 1500 $extension->set('name', $component); 1501 $extension->set('state', -1); 1502 $extension->set('manifest_cache', json_encode($manifest_details)); 1503 $results[] = $extension; 1504 } 1505 } 1506 1507 foreach ($admin_components as $component) 1508 { 1509 if (file_exists(JPATH_ADMINISTRATOR . '/components/' . $component . '/' . str_replace('com_', '', $component) . '.xml')) 1510 { 1511 $manifest_details = JInstaller::parseXMLInstallFile( 1512 JPATH_ADMINISTRATOR . '/components/' . $component . '/' . str_replace('com_', '', $component) . '.xml' 1513 ); 1514 $extension = JTable::getInstance('extension'); 1515 $extension->set('type', 'component'); 1516 $extension->set('client_id', 1); 1517 $extension->set('element', $component); 1518 $extension->set('name', $component); 1519 $extension->set('state', -1); 1520 $extension->set('manifest_cache', json_encode($manifest_details)); 1521 $results[] = $extension; 1522 } 1523 } 1524 return $results; 1525 } 1526 1527 /** 1528 * Install unregistered extensions that have been discovered. 1529 * 1530 * @return mixed 1531 * 1532 * @since 11.1 1533 */ 1534 public function discover_install() 1535 { 1536 // Need to find to find where the XML file is since we don't store this normally 1537 $client = JApplicationHelper::getClientInfo($this->parent->extension->client_id); 1538 $short_element = str_replace('com_', '', $this->parent->extension->element); 1539 $manifestPath = $client->path . '/components/' . $this->parent->extension->element . '/' . $short_element . '.xml'; 1540 $this->parent->manifest = $this->parent->isManifest($manifestPath); 1541 $this->parent->setPath('manifest', $manifestPath); 1542 $this->parent->setPath('source', $client->path . '/components/' . $this->parent->extension->element); 1543 $this->parent->setPath('extension_root', $this->parent->getPath('source')); 1544 1545 $manifest_details = JInstaller::parseXMLInstallFile($this->parent->getPath('manifest')); 1546 $this->parent->extension->manifest_cache = json_encode($manifest_details); 1547 $this->parent->extension->state = 0; 1548 $this->parent->extension->name = $manifest_details['name']; 1549 $this->parent->extension->enabled = 1; 1550 $this->parent->extension->params = $this->parent->getParams(); 1551 1552 try 1553 { 1554 $this->parent->extension->store(); 1555 } 1556 catch (RuntimeException $e) 1557 { 1558 JLog::add(JText::_('JLIB_INSTALLER_ERROR_COMP_DISCOVER_STORE_DETAILS'), JLog::WARNING, 'jerror'); 1559 return false; 1560 } 1561 1562 // Now we need to run any SQL it has, languages, media or menu stuff 1563 1564 // Get a database connector object 1565 $db = $this->parent->getDbo(); 1566 1567 // Get the extension manifest object 1568 $this->manifest = $this->parent->getManifest(); 1569 1570 /** 1571 * --------------------------------------------------------------------------------------------- 1572 * Manifest Document Setup Section 1573 * --------------------------------------------------------------------------------------------- 1574 */ 1575 1576 // Set the extensions name 1577 $name = strtolower(JFilterInput::getInstance()->clean((string) $this->manifest->name, 'cmd')); 1578 if (substr($name, 0, 4) == 'com_') 1579 { 1580 $element = $name; 1581 } 1582 else 1583 { 1584 $element = 'com_' . $name; 1585 } 1586 1587 $this->set('name', $name); 1588 $this->set('element', $element); 1589 1590 // Get the component description 1591 $description = (string) $this->manifest->description; 1592 1593 if ($description) 1594 { 1595 $this->parent->set('message', JText::_((string) $description)); 1596 } 1597 else 1598 { 1599 $this->parent->set('message', ''); 1600 } 1601 1602 // Set the installation target paths 1603 $this->parent->setPath('extension_site', JPath::clean(JPATH_SITE . '/components/' . $this->get('element'))); 1604 $this->parent->setPath('extension_administrator', JPath::clean(JPATH_ADMINISTRATOR . '/components/' . $this->get('element'))); 1605 1606 // Copy the admin path as it's used as a common base 1607 $this->parent->setPath('extension_root', $this->parent->getPath('extension_administrator')); 1608 1609 /** 1610 * --------------------------------------------------------------------------------------------- 1611 * Basic Checks Section 1612 * --------------------------------------------------------------------------------------------- 1613 */ 1614 1615 // Make sure that we have an admin element 1616 if (!$this->manifest->administration) 1617 { 1618 JLog::add(JText::_('JLIB_INSTALLER_ERROR_COMP_INSTALL_ADMIN_ELEMENT'), JLog::WARNING, 'jerror'); 1619 return false; 1620 } 1621 1622 /** 1623 * --------------------------------------------------------------------------------------------- 1624 * Installer Trigger Loading 1625 * --------------------------------------------------------------------------------------------- 1626 */ 1627 // If there is an manifest class file, lets load it; we'll copy it later (don't have dest yet) 1628 $manifestScript = (string) $this->manifest->scriptfile; 1629 1630 if ($manifestScript) 1631 { 1632 $manifestScriptFile = $this->parent->getPath('source') . '/' . $manifestScript; 1633 1634 if (is_file($manifestScriptFile)) 1635 { 1636 // Load the file 1637 include_once $manifestScriptFile; 1638 } 1639 1640 // Set the class name 1641 $classname = $element . 'InstallerScript'; 1642 1643 if (class_exists($classname)) 1644 { 1645 // Create a new instance 1646 $this->parent->manifestClass = new $classname($this); 1647 1648 // And set this so we can copy it later 1649 $this->set('manifest_script', $manifestScript); 1650 } 1651 } 1652 1653 // Run preflight if possible (since we know we're not an update) 1654 ob_start(); 1655 ob_implicit_flush(false); 1656 1657 if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'preflight')) 1658 { 1659 1660 if ($this->parent->manifestClass->preflight('discover_install', $this) === false) 1661 { 1662 // Install failed, rollback changes 1663 $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_COMP_INSTALL_CUSTOM_INSTALL_FAILURE')); 1664 return false; 1665 } 1666 } 1667 1668 // Create msg object; first use here 1669 $msg = ob_get_contents(); 1670 ob_end_clean(); 1671 1672 /* 1673 * 1674 * Normally we would copy files and create directories, lets skip to the optional files 1675 * Note: need to dereference things! 1676 * Parse optional tags 1677 * @todo remove code: $this->parent->parseMedia($this->manifest->media); 1678 * 1679 * We don't do language because 1.6 suggests moving to extension based languages 1680 * @todo remove code: $this->parent->parseLanguages($this->manifest->languages); 1681 * @todo remove code: $this->parent->parseLanguages($this->manifest->administration->languages, 1); 1682 */ 1683 1684 /** 1685 * --------------------------------------------------------------------------------------------- 1686 * Database Processing Section 1687 * --------------------------------------------------------------------------------------------- 1688 */ 1689 1690 // Let's run the install queries for the component 1691 if (isset($this->manifest->install->sql)) 1692 { 1693 $utfresult = $this->parent->parseSQLFiles($this->manifest->install->sql); 1694 1695 if ($utfresult === false) 1696 { 1697 // Install failed, rollback changes 1698 $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_COMP_INSTALL_SQL_ERROR', $db->stderr(true))); 1699 1700 return false; 1701 } 1702 } 1703 1704 // Time to build the admin menus 1705 if (!$this->_buildAdminMenus($this->parent->…
Large files files are truncated, but you can click here to view the full file