/** * Steps through the installation process of a package. */ protected function install() { try { // open package file if (!FileUtil::isURL($this->packageArchive->getArchive())) { $this->assignPackageInfo(); } switch ($this->step) { // prepare package installation case '': // download package file if necessary if (FileUtil::isURL($this->packageArchive->getArchive())) { // get return value and update entry in // package_installation_queue with this value $archive = $this->packageArchive->downloadArchive(); $sql = "UPDATE\twcf" . WCF_N . "_package_installation_queue\n\t\t\t\t\t\t\tSET\tarchive = '" . escapeString($archive) . "' \n\t\t\t\t\t\t\tWHERE\tqueueID = " . $this->queueID; WCF::getDB()->sendQuery($sql); $this->assignPackageInfo(); } // check package file $this->checkArchive(); // show confirm package installation site if necessary if ($this->confirmInstallation == 1 && $this->parentQueueID == 0) { $this->nextStep = 'confirm'; } else { if ($this->parentQueueID == 0) { $this->nextStep = 'installationFrame'; } else { $this->nextStep = 'requirements'; } } HeaderUtil::redirect('index.php?page=Package&action=' . $this->action . '&queueID=' . $this->queueID . '&step=' . $this->nextStep . '&packageID=' . PACKAGE_ID . SID_ARG_2ND_NOT_ENCODED); exit; break; // show confirm package installation site // show confirm package installation site case 'confirm': // get requirements $requirements = $this->packageArchive->getRequirements(); $openRequirements = $this->packageArchive->getOpenRequirements(); $updatableInstances = array(); $missingPackages = 0; foreach ($requirements as $key => $requirement) { if (isset($openRequirements[$requirement['name']])) { $requirements[$key]['open'] = 1; $requirements[$key]['action'] = $openRequirements[$requirement['name']]['action']; if (!isset($requirements[$key]['file'])) { $missingPackages++; } } else { $requirements[$key]['open'] = 0; } } // get other instances if ($this->action == 'install') { $updatableInstances = $this->packageArchive->getUpdatableInstances(); } WCFACP::getMenu()->setActiveMenuItem('wcf.acp.menu.link.package'); WCF::getTPL()->assign(array('archive' => $this->packageArchive, 'package' => $this->package, 'requiredPackages' => $requirements, 'missingPackages' => $missingPackages, 'updatableInstances' => $updatableInstances, 'excludingPackages' => $this->packageArchive->getConflictedExcludingPackages(), 'excludedPackages' => $this->packageArchive->getConflictedExcludedPackages())); WCF::getTPL()->display('packageInstallationConfirm'); exit; break; case 'changeToUpdate': // get package id $updatePackageID = 0; if (isset($_REQUEST['updatePackageID'])) { $updatePackageID = intval($_REQUEST['updatePackageID']); } // check package id $updatableInstances = $this->packageArchive->getUpdatableInstances(); if (!isset($updatableInstances[$updatePackageID])) { throw new IllegalLinkException(); } // update queue entry $sql = "UPDATE\twcf" . WCF_N . "_package_installation_queue\n\t\t\t\t\t\tSET\taction = 'update',\n\t\t\t\t\t\t\tpackageID = " . $updatePackageID . "\n\t\t\t\t\t\tWHERE\tqueueID = " . $this->queueID; WCF::getDB()->sendQuery($sql); HeaderUtil::redirect('index.php?page=Package&action=update&queueID=' . $this->queueID . '&step=installationFrame&packageID=' . PACKAGE_ID . SID_ARG_2ND_NOT_ENCODED); exit; break; // cancel the installation // cancel the installation case 'cancel': $this->packageArchive->deleteArchive(); $sql = "DELETE FROM\twcf" . WCF_N . "_package_installation_queue\n\t\t\t\t\t\tWHERE\t\tqueueID = " . $this->queueID; WCF::getDB()->sendQuery($sql); HeaderUtil::redirect('index.php?page=PackageList&packageID=' . PACKAGE_ID . SID_ARG_2ND_NOT_ENCODED); break; // show the installation frame // show the installation frame case 'installationFrame': $this->calcProgress(0); $this->nextStep = 'requirements'; WCF::getTPL()->assign(array('nextStep' => $this->nextStep)); WCF::getTPL()->display('packageInstallationFrame'); exit; break; // check if this package depends on other packages // check if this package depends on other packages case 'requirements': if ($this->installPackageRequirements()) { $this->calcProgress(1); $this->nextStep = 'exclusions'; } else { WCF::getTPL()->display('packageInstallationRequirements'); exit; } break; // check for conflicted exclusions // check for conflicted exclusions case 'exclusions': $this->checkExclusions(); $this->calcProgress(1); $this->nextStep = 'package'; break; // install package itself // install package itself case 'package': // install selectable package requirements $this->installSelectablePackageRequirements(); // install package $this->installPackage(); $this->calcProgress(2); $this->nextStep = 'parent'; break; // manage parent packages (these are needed by plugins) // manage parent packages (these are needed by plugins) case 'parent': $this->installPackageParent(); $this->rebuildConfigFiles(); $this->calcProgress(3); $this->nextStep = 'packageInstallationPlugins'; break; // install packageInstallationPlugins // install packageInstallationPlugins case 'packageInstallationPlugins': if ($this->hasPackageInstallationPlugins()) { $this->installPackageInstallationPlugins(); } $this->calcProgress(4); $this->nextStep = 'execPackageInstallationPlugins'; break; // At this point execution of packageInstallationPlugins starts. The getNextStep method will return // the class name of the first available packageInstallationPlugin. Thus in the next installation step // this switch will jump into the default: directive. The default: directive will then be called for // every available packageInstallationPlugin. The actual execution of the respective packageInstallationPlugin // is being done there. // At this point execution of packageInstallationPlugins starts. The getNextStep method will return // the class name of the first available packageInstallationPlugin. Thus in the next installation step // this switch will jump into the default: directive. The default: directive will then be called for // every available packageInstallationPlugin. The actual execution of the respective packageInstallationPlugin // is being done there. case 'execPackageInstallationPlugins': $this->loadPackageInstallationPlugins(); $this->calcProgress(5); $this->nextStep = $this->getNextPackageInstallationPlugin(''); break; // check if this package has optional packages // check if this package has optional packages case 'optionals': // update package version before installing optionals $this->updatePackageVersion(); // install optional packages if ($this->installPackageOptionals()) { $this->calcProgress(6); $this->nextStep = 'finish'; } else { WCF::getTPL()->display('packageInstallationOptionals'); exit; } break; // finish installation // finish installation case 'finish': $this->calcProgress(7); $this->nextStep = $this->finishInstallation(); break; // start rollback of all installations in the active process // start rollback of all installations in the active process case 'rollback': // delete packages that are not rollbackable $sql = "DELETE FROM\twcf" . WCF_N . "_package_installation_queue\n\t\t\t\t\t\tWHERE\t\tprocessNo = " . $this->processNo . "\n\t\t\t\t\t\t\t\tAND (\n\t\t\t\t\t\t\t\t\taction <> 'install'\n\t\t\t\t\t\t\t\t\tOR cancelable = 0\n\t\t\t\t\t\t\t\t)"; WCF::getDB()->sendQuery($sql); // enable rollback for all other packages $sql = "UPDATE\twcf" . WCF_N . "_package_installation_queue\n\t\t\t\t\t\tSET\taction = 'rollback',\n\t\t\t\t\t\t\tdone = 0\n\t\t\t\t\t\tWHERE\tprocessNo = " . $this->processNo . "\n\t\t\t\t\t\t\tAND action = 'install'\n\t\t\t\t\t\t\tAND cancelable = 1"; WCF::getDB()->sendQuery($sql); HeaderUtil::redirect('index.php?page=Package&action=openQueue&processNo=' . $this->processNo . '&packageID=' . PACKAGE_ID . SID_ARG_2ND_NOT_ENCODED); exit; break; // execute PackageInstallationPlugins // execute PackageInstallationPlugins default: $this->executePackageInstallationPlugin($this->step); $this->nextStep = $this->getNextPackageInstallationPlugin($this->step); } WCF::getTPL()->assign(array('nextStep' => $this->nextStep)); WCF::getTPL()->display('packageInstallationNext'); } catch (SystemException $e) { $this->showPackageInstallationException($e); } }