| [ Index ] |
PHP Cross Reference of Joomla 2.5.4 DE |
[Summary view] [Print] [Text view]
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 10 defined('JPATH_PLATFORM') or die; 11 12 jimport('joomla.installer.filemanifest'); 13 jimport('joomla.base.adapterinstance'); 14 15 /** 16 * File installer 17 * 18 * @package Joomla.Platform 19 * @subpackage Installer 20 * @since 11.1 21 */ 22 class JInstallerFile extends JAdapterInstance 23 { 24 protected $route = 'install'; 25 26 /** 27 * Custom loadLanguage method 28 * 29 * @param string $path The path on which to find language files. 30 * 31 * @return void 32 * 33 * @since 11.1 34 */ 35 public function loadLanguage($path) 36 { 37 $this->manifest = $this->parent->getManifest(); 38 $extension = 'files_' . str_replace('files_', '', strtolower(JFilterInput::getInstance()->clean((string) $this->manifest->name, 'cmd'))); 39 $lang = JFactory::getLanguage(); 40 $source = $path; 41 $lang->load($extension . '.sys', $source, null, false, false) 42 || $lang->load($extension . '.sys', JPATH_SITE, null, false, false) 43 || $lang->load($extension . '.sys', $source, $lang->getDefault(), false, false) 44 || $lang->load($extension . '.sys', JPATH_SITE, $lang->getDefault(), false, false); 45 } 46 47 /** 48 * Custom install method 49 * 50 * @return boolean True on success 51 * 52 * @since 11.1 53 */ 54 public function install() 55 { 56 // Get the extension manifest object 57 $this->manifest = $this->parent->getManifest(); 58 59 // Manifest Document Setup Section 60 61 // Set the extension's name 62 $name = JFilterInput::getInstance()->clean((string) $this->manifest->name, 'string'); 63 $this->set('name', $name); 64 65 // Set element 66 $manifestPath = JPath::clean($this->parent->getPath('manifest')); 67 $element = preg_replace('/\.xml/', '', basename($manifestPath)); 68 $this->set('element', $element); 69 70 // Get the component description 71 $description = (string) $this->manifest->description; 72 if ($description) 73 { 74 $this->parent->set('message', JText::_($description)); 75 } 76 else 77 { 78 $this->parent->set('message', ''); 79 } 80 81 //Check if the extension by the same name is already installed 82 if ($this->extensionExistsInSystem($element)) 83 { 84 // Package with same name already exists 85 if (!$this->parent->getOverwrite()) 86 { 87 // we're not overwriting so abort 88 $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_FILE_SAME_NAME')); 89 return false; 90 } 91 else 92 { 93 // swap to the update route 94 $this->route = 'update'; 95 } 96 } 97 // Set the file root path 98 $this->parent->setPath('extension_root', JPATH_ROOT); 99 100 /** 101 * --------------------------------------------------------------------------------------------- 102 * Installer Trigger Loading 103 * --------------------------------------------------------------------------------------------- 104 */ 105 // If there is an manifest class file, lets load it; we'll copy it later (don't have dest yet) 106 $this->scriptElement = $this->manifest->scriptfile; 107 $manifestScript = (string) $this->manifest->scriptfile; 108 109 if ($manifestScript) 110 { 111 $manifestScriptFile = $this->parent->getPath('source') . '/' . $manifestScript; 112 113 if (is_file($manifestScriptFile)) 114 { 115 // load the file 116 include_once $manifestScriptFile; 117 } 118 119 // Set the class name 120 $classname = $element . 'InstallerScript'; 121 122 if (class_exists($classname)) 123 { 124 // create a new instance 125 $this->parent->manifestClass = new $classname($this); 126 // and set this so we can copy it later 127 $this->set('manifest_script', $manifestScript); 128 129 // Note: if we don't find the class, don't bother to copy the file 130 } 131 } 132 133 // run preflight if possible (since we know we're not an update) 134 ob_start(); 135 ob_implicit_flush(false); 136 137 if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'preflight')) 138 { 139 if ($this->parent->manifestClass->preflight($this->route, $this) === false) 140 { 141 // Install failed, rollback changes 142 $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_FILE_INSTALL_CUSTOM_INSTALL_FAILURE')); 143 144 return false; 145 } 146 } 147 148 $msg = ob_get_contents(); // create msg object; first use here 149 ob_end_clean(); 150 151 // Populate File and Folder List to copy 152 $this->populateFilesAndFolderList(); 153 154 // Filesystem Processing Section 155 156 // Now that we have folder list, lets start creating them 157 foreach ($this->folderList as $folder) 158 { 159 if (!JFolder::exists($folder)) 160 { 161 162 if (!$created = JFolder::create($folder)) 163 { 164 JError::raiseWarning(1, JText::sprintf('JLIB_INSTALLER_ABORT_FILE_INSTALL_FAIL_SOURCE_DIRECTORY', $folder)); 165 // If installation fails, rollback 166 $this->parent->abort(); 167 return false; 168 } 169 170 // Since we created a directory and will want to remove it if we have to roll back. 171 // the installation due to some errors, let's add it to the installation step stack. 172 173 if ($created) 174 { 175 $this->parent->pushStep(array('type' => 'folder', 'path' => $folder)); 176 } 177 } 178 179 } 180 181 // Now that we have file list, let's start copying them 182 $this->parent->copyFiles($this->fileList); 183 184 // Parse optional tags 185 $this->parent->parseLanguages($this->manifest->languages); 186 187 // Finalization and Cleanup Section 188 189 // Get a database connector object 190 $db = $this->parent->getDbo(); 191 192 // Check to see if a module by the same name is already installed 193 // If it is, then update the table because if the files aren't there 194 // we can assume that it was (badly) uninstalled 195 // If it isn't, add an entry to extensions 196 $query = $db->getQuery(true); 197 $query->select($query->qn('extension_id')) 198 ->from($query->qn('#__extensions')); 199 $query->where($query->qn('type') . ' = ' . $query->q('file')) 200 ->where($query->qn('element') . ' = ' . $query->q($element)); 201 $db->setQuery($query); 202 try 203 { 204 $db->Query(); 205 } 206 catch (JException $e) 207 { 208 // Install failed, roll back changes 209 $this->parent->abort( 210 JText::sprintf('JLIB_INSTALLER_ABORT_FILE_ROLLBACK', JText::_('JLIB_INSTALLER_' . $this->route), $db->stderr(true)) 211 ); 212 return false; 213 } 214 $id = $db->loadResult(); 215 $row = JTable::getInstance('extension'); 216 217 if ($id) 218 { 219 // Load the entry and update the manifest_cache 220 $row->load($id); 221 // Update name 222 $row->set('name', $this->get('name')); 223 // Update manifest 224 $row->manifest_cache = $this->parent->generateManifestCache(); 225 if (!$row->store()) 226 { 227 // Install failed, roll back changes 228 $this->parent->abort( 229 JText::sprintf('JLIB_INSTALLER_ABORT_FILE_ROLLBACK', JText::_('JLIB_INSTALLER_' . $this->route), $db->stderr(true)) 230 ); 231 return false; 232 } 233 } 234 else 235 { 236 // Add an entry to the extension table with a whole heap of defaults 237 $row->set('name', $this->get('name')); 238 $row->set('type', 'file'); 239 $row->set('element', $this->get('element')); 240 // There is no folder for files so leave it blank 241 $row->set('folder', ''); 242 $row->set('enabled', 1); 243 $row->set('protected', 0); 244 $row->set('access', 0); 245 $row->set('client_id', 0); 246 $row->set('params', ''); 247 $row->set('system_data', ''); 248 $row->set('manifest_cache', $this->parent->generateManifestCache()); 249 250 if (!$row->store()) 251 { 252 // Install failed, roll back changes 253 $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_FILE_INSTALL_ROLLBACK', $db->stderr(true))); 254 return false; 255 } 256 257 // Set the insert id 258 $row->set('extension_id', $db->insertid()); 259 260 // Since we have created a module item, we add it to the installation step stack 261 // so that if we have to rollback the changes we can undo it. 262 $this->parent->pushStep(array('type' => 'extension', 'extension_id' => $row->extension_id)); 263 } 264 265 /* 266 * Let's run the queries for the file 267 */ 268 // second argument is the utf compatible version attribute 269 if (strtolower($this->route) == 'install') 270 { 271 $utfresult = $this->parent->parseSQLFiles($this->manifest->install->sql); 272 273 if ($utfresult === false) 274 { 275 // Install failed, rollback changes 276 $this->parent->abort( 277 JText::sprintf('JLIB_INSTALLER_ABORT_FILE_INSTALL_SQL_ERROR', JText::_('JLIB_INSTALLER_' . $this->route), $db->stderr(true)) 278 ); 279 280 return false; 281 } 282 283 // Set the schema version to be the latest update version 284 if ($this->manifest->update) 285 { 286 $this->parent->setSchemaVersion($this->manifest->update->schemas, $row->extension_id); 287 } 288 } 289 elseif (strtolower($this->route) == 'update') 290 { 291 if ($this->manifest->update) 292 { 293 $result = $this->parent->parseSchemaUpdates($this->manifest->update->schemas, $row->extension_id); 294 if ($result === false) 295 { 296 // Install failed, rollback changes 297 $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_FILE_UPDATE_SQL_ERROR', $db->stderr(true))); 298 return false; 299 } 300 } 301 } 302 303 // Start Joomla! 1.6 304 ob_start(); 305 ob_implicit_flush(false); 306 307 if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, $this->route)) 308 { 309 if ($this->parent->manifestClass->{$this->route}($this) === false) 310 { 311 // Install failed, rollback changes 312 $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_FILE_INSTALL_CUSTOM_INSTALL_FAILURE')); 313 314 return false; 315 } 316 } 317 318 $msg .= ob_get_contents(); // append messages 319 ob_end_clean(); 320 321 // Lastly, we will copy the manifest file to its appropriate place. 322 $manifest = array(); 323 $manifest['src'] = $this->parent->getPath('manifest'); 324 $manifest['dest'] = JPATH_MANIFESTS . '/files/' . basename($this->parent->getPath('manifest')); 325 if (!$this->parent->copyFiles(array($manifest), true)) 326 { 327 // Install failed, rollback changes 328 $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_FILE_INSTALL_COPY_SETUP')); 329 return false; 330 } 331 332 // Clobber any possible pending updates 333 $update = JTable::getInstance('update'); 334 $uid = $update->find( 335 array('element' => $this->get('element'), 'type' => 'file', 'client_id' => '', 'folder' => '') 336 ); 337 338 if ($uid) 339 { 340 $update->delete($uid); 341 } 342 343 // And now we run the postflight 344 ob_start(); 345 ob_implicit_flush(false); 346 347 if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'postflight')) 348 { 349 $this->parent->manifestClass->postflight($this->route, $this); 350 } 351 352 $msg .= ob_get_contents(); // append messages 353 ob_end_clean(); 354 355 if ($msg != '') 356 { 357 $this->parent->set('extension_message', $msg); 358 } 359 360 return $row->get('extension_id'); 361 } 362 363 /** 364 * Custom update method 365 * 366 * @return boolean True on success 367 * 368 * @since 11.1 369 */ 370 public function update() 371 { 372 // Set the overwrite setting 373 $this->parent->setOverwrite(true); 374 $this->parent->setUpgrade(true); 375 $this->route = 'update'; 376 377 // ...and adds new files 378 return $this->install(); 379 } 380 381 /** 382 * Custom uninstall method 383 * 384 * @param string $id The id of the file to uninstall 385 * 386 * @return boolean True on success 387 * 388 * @since 11.1 389 */ 390 public function uninstall($id) 391 { 392 // Initialise variables. 393 $row = JTable::getInstance('extension'); 394 if (!$row->load($id)) 395 { 396 JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_FILE_UNINSTALL_LOAD_ENTRY')); 397 return false; 398 } 399 400 if ($row->protected) 401 { 402 JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_FILE_UNINSTALL_WARNCOREFILE')); 403 return false; 404 } 405 406 $retval = true; 407 $manifestFile = JPATH_MANIFESTS . '/files/' . $row->element . '.xml'; 408 409 // Because files may not have their own folders we cannot use the standard method of finding an installation manifest 410 if (file_exists($manifestFile)) 411 { 412 // Set the plugin root path 413 $this->parent->setPath('extension_root', JPATH_ROOT); // . '/files/' . $manifest->filename); 414 415 $xml = JFactory::getXML($manifestFile); 416 417 // If we cannot load the XML file return null 418 if (!$xml) 419 { 420 JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_FILE_UNINSTALL_LOAD_MANIFEST')); 421 return false; 422 } 423 424 /* 425 * Check for a valid XML root tag. 426 */ 427 if ($xml->getName() != 'extension') 428 { 429 JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_FILE_UNINSTALL_INVALID_MANIFEST')); 430 return false; 431 } 432 433 $this->manifest = $xml; 434 435 // If there is an manifest class file, let's load it 436 $this->scriptElement = $this->manifest->scriptfile; 437 $manifestScript = (string) $this->manifest->scriptfile; 438 439 if ($manifestScript) 440 { 441 $manifestScriptFile = $this->parent->getPath('extension_root') . '/' . $manifestScript; 442 443 if (is_file($manifestScriptFile)) 444 { 445 // Load the file 446 include_once $manifestScriptFile; 447 } 448 449 // Set the class name 450 $classname = $row->element . 'InstallerScript'; 451 452 if (class_exists($classname)) 453 { 454 // Create a new instance 455 $this->parent->manifestClass = new $classname($this); 456 // And set this so we can copy it later 457 $this->set('manifest_script', $manifestScript); 458 459 // Note: if we don't find the class, don't bother to copy the file 460 } 461 } 462 463 ob_start(); 464 ob_implicit_flush(false); 465 466 // Run uninstall if possible 467 if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'uninstall')) 468 { 469 $this->parent->manifestClass->uninstall($this); 470 } 471 472 $msg = ob_get_contents(); 473 ob_end_clean(); 474 475 /* 476 * Let's run the uninstall queries for the component 477 * If Joomla 1.5 compatible, with discreet sql files - execute appropriate 478 * file for utf-8 support or non-utf support 479 */ 480 // Try for Joomla 1.5 type queries 481 // Second argument is the utf compatible version attribute 482 $utfresult = $this->parent->parseSQLFiles($this->manifest->uninstall->sql); 483 484 if ($utfresult === false) 485 { 486 // Install failed, rollback changes 487 JError::raiseWarning(100, JText::sprintf('JLIB_INSTALLER_ERROR_FILE_UNINSTALL_SQL_ERROR', $db->stderr(true))); 488 $retval = false; 489 } 490 491 // Remove the schema version 492 $db = JFactory::getDbo(); 493 $query = $db->getQuery(true); 494 $query->delete() 495 ->from('#__schemas') 496 ->where('extension_id = ' . $row->extension_id); 497 $db->setQuery($query); 498 $db->Query(); 499 500 // Set root folder names 501 $packagePath = $this->parent->getPath('source'); 502 $jRootPath = JPath::clean(JPATH_ROOT); 503 504 // Loop through all elements and get list of files and folders 505 foreach ($xml->fileset->files as $eFiles) 506 { 507 $folder = (string) $eFiles->attributes()->folder; 508 $target = (string) $eFiles->attributes()->target; 509 // Create folder path 510 if (empty($target)) 511 { 512 $targetFolder = JPATH_ROOT; 513 } 514 else 515 { 516 $targetFolder = JPATH_ROOT . '/' . $target; 517 } 518 519 $folderList = array(); 520 // Check if all children exists 521 if (count($eFiles->children()) > 0) 522 { 523 // Loop through all filenames elements 524 foreach ($eFiles->children() as $eFileName) 525 { 526 if ($eFileName->getName() == 'folder') 527 { 528 $folderList[] = $targetFolder . '/' . $eFileName; 529 530 } 531 else 532 { 533 $fileName = $targetFolder . '/' . $eFileName; 534 JFile::delete($fileName); 535 } 536 } 537 } 538 539 // Delete any folders that don't have any content in them. 540 foreach ($folderList as $folder) 541 { 542 $files = JFolder::files($folder); 543 if (!count($files)) 544 { 545 JFolder::delete($folder); 546 } 547 } 548 } 549 550 JFile::delete($manifestFile); 551 552 } 553 else 554 { 555 JError::raiseWarning(100, JText::_('JLIB_INSTALLER_ERROR_FILE_UNINSTALL_INVALID_NOTFOUND_MANIFEST')); 556 // Delete the row because its broken 557 $row->delete(); 558 return false; 559 } 560 561 $this->parent->removeFiles($xml->languages); 562 563 $row->delete(); 564 565 return $retval; 566 } 567 568 /** 569 * Function used to check if extension is already installed 570 * 571 * @param string $extension The element name of the extension to install 572 * 573 * @return boolean True if extension exists 574 * 575 * @since 11.1 576 */ 577 protected function extensionExistsInSystem($extension = null) 578 { 579 // Get a database connector object 580 $db = $this->parent->getDBO(); 581 582 $query = $db->getQuery(true); 583 $query->select($query->qn('extension_id')) 584 ->from($query->qn('#__extensions')); 585 $query->where($query->qn('type') . ' = ' . $query->q('file')) 586 ->where($query->qn('element') . ' = ' . $query->q($extension)); 587 $db->setQuery($query); 588 589 try 590 { 591 $db->Query(); 592 } 593 catch (JException $e) 594 { 595 // Install failed, roll back changes 596 $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_FILE_ROLLBACK', $db->stderr(true))); 597 return false; 598 } 599 $id = $db->loadResult(); 600 601 if (empty($id)) 602 { 603 return false; 604 } 605 606 return true; 607 608 } 609 610 /** 611 * Function used to populate files and folder list 612 * 613 * @return boolean none 614 * 615 * @since 11.1 616 */ 617 protected function populateFilesAndFolderList() 618 { 619 620 // Initialise variable 621 $this->folderList = array(); 622 $this->fileList = array(); 623 624 // Get fileset 625 $eFileset = $this->manifest->fileset->files; 626 627 // Set root folder names 628 $packagePath = $this->parent->getPath('source'); 629 $jRootPath = JPath::clean(JPATH_ROOT); 630 631 // Loop through all elements and get list of files and folders 632 foreach ($this->manifest->fileset->files as $eFiles) 633 { 634 // Check if the element is files element 635 $folder = (string) $eFiles->attributes()->folder; 636 $target = (string) $eFiles->attributes()->target; 637 638 //Split folder names into array to get folder names. This will 639 // help in creating folders 640 $arrList = preg_split("#/|\\/#", $target); 641 642 $folderName = $jRootPath; 643 foreach ($arrList as $dir) 644 { 645 if (empty($dir)) 646 { 647 continue; 648 } 649 650 $folderName .= '/' . $dir; 651 // Check if folder exists, if not then add to the array for folder creation 652 if (!JFolder::exists($folderName)) 653 { 654 array_push($this->folderList, $folderName); 655 } 656 } 657 658 // Create folder path 659 $sourceFolder = empty($folder) ? $packagePath : $packagePath . '/' . $folder; 660 $targetFolder = empty($target) ? $jRootPath : $jRootPath . '/' . $target; 661 662 // Check if source folder exists 663 if (!JFolder::exists($sourceFolder)) 664 { 665 JError::raiseWarning(1, JText::sprintf('JLIB_INSTALLER_ABORT_FILE_INSTALL_FAIL_SOURCE_DIRECTORY', $sourceFolder)); 666 // If installation fails, rollback 667 $this->parent->abort(); 668 return false; 669 } 670 671 // Check if all children exists 672 if (count($eFiles->children())) 673 { 674 // Loop through all filenames elements 675 foreach ($eFiles->children() as $eFileName) 676 { 677 $path['src'] = $sourceFolder . '/' . $eFileName; 678 $path['dest'] = $targetFolder . '/' . $eFileName; 679 $path['type'] = 'file'; 680 if ($eFileName->getName() == 'folder') 681 { 682 $folderName = $targetFolder . '/' . $eFileName; 683 array_push($this->folderList, $folderName); 684 $path['type'] = 'folder'; 685 } 686 687 array_push($this->fileList, $path); 688 } 689 } 690 else 691 { 692 $files = JFolder::files($sourceFolder); 693 foreach ($files as $file) 694 { 695 $path['src'] = $sourceFolder . '/' . $file; 696 $path['dest'] = $targetFolder . '/' . $file; 697 698 array_push($this->fileList, $path); 699 } 700 701 } 702 } 703 } 704 705 /** 706 * Refreshes the extension table cache 707 * 708 * @return boolean result of operation, true if updated, false on failure 709 * 710 * @since 11.1 711 */ 712 public function refreshManifestCache() 713 { 714 // Need to find to find where the XML file is since we don't store this normally 715 $manifestPath = JPATH_MANIFESTS . '/files/' . $this->parent->extension->element . '.xml'; 716 $this->parent->manifest = $this->parent->isManifest($manifestPath); 717 $this->parent->setPath('manifest', $manifestPath); 718 719 $manifest_details = JApplicationHelper::parseXMLInstallFile($this->parent->getPath('manifest')); 720 $this->parent->extension->manifest_cache = json_encode($manifest_details); 721 $this->parent->extension->name = $manifest_details['name']; 722 723 try 724 { 725 return $this->parent->extension->store(); 726 } 727 catch (JException $e) 728 { 729 JError::raiseWarning(101, JText::_('JLIB_INSTALLER_ERROR_PACK_REFRESH_MANIFEST_CACHE')); 730 return false; 731 } 732 } 733 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Tue Apr 3 11:40:28 2012 | Cross-referenced by PHPXref 0.7.1 |