/**
  * @see AdminToolsFunction::execute($data)
  */
 public function execute($data)
 {
     parent::execute($data);
     $parameters = $data['parameters']['cache.clearCache'];
     if ($parameters['clearWCFCache']) {
         WCF::getCache()->clear(WCF_DIR . 'cache', '*.php', true);
     }
     if ($parameters['clearStandaloneCache']) {
         $sql = "SELECT packageDir FROM wcf" . WCF_N . "_package WHERE packageID = " . PACKAGE_ID;
         $row = WCF::getDB()->getFirstRow($sql);
         WCF::getCache()->clear($row['packageDir'] . 'cache', '*.php', true);
     }
     if ($parameters['clearTemplateCache']) {
         require_once WCF_DIR . 'lib/system/template/ACPTemplate.class.php';
         ACPTemplate::deleteCompiledACPTemplates();
         Template::deleteCompiledTemplates();
     }
     if ($parameters['clearLanguageCache']) {
         LanguageEditor::deleteLanguageFiles('*', '*', '*');
     }
     if ($parameters['clearStandaloneOptions']) {
         Options::resetCache();
         Options::resetFile();
     }
     $this->executed();
 }
 /**
  * @see Form::save()
  */
 public function save()
 {
     if (!$this->preview) {
         parent::save();
         // get languages
         $languages = array();
         $sql = "SELECT\tlanguageID\n\t\t\t\tFROM\twcf" . WCF_N . "_language\n\t\t\t\tWHERE\tlanguageID <> " . $this->sourceLanguageID;
         $result = WCF::getDB()->sendQuery($sql);
         while ($row = WCF::getDB()->fetchArray($result)) {
             $languages[] = $row['languageID'];
         }
         if (count($languages) > 0) {
             // add missing language items
             foreach ($languages as $languageID) {
                 $sql = "INSERT IGNORE INTO\twcf" . WCF_N . "_language_item\n\t\t\t\t\t\t\t\t\t(languageID, languageItem, languageItemValue, languageCategoryID, packageID)\n\t\t\t\t\t\tSELECT\t\t\t" . $languageID . ", languageItem, languageItemValue, languageCategoryID, packageID\n\t\t\t\t\t\tFROM\t\t\twcf" . WCF_N . "_language_item\n\t\t\t\t\t\tWHERE\t\t\tlanguageID = " . $this->sourceLanguageID . "\n\t\t\t\t\t\t\t\t\tAND languageItem NOT IN (\n\t\t\t\t\t\t\t\t\t\tSELECT\tlanguageItem\n\t\t\t\t\t\t\t\t\t\tFROM\twcf" . WCF_N . "_language_item\n\t\t\t\t\t\t\t\t\t\tWHERE\tlanguageID = " . $languageID . "\n\t\t\t\t\t\t\t\t\t)";
                 WCF::getDB()->sendQuery($sql);
                 $this->addedLanguageItems += WCF::getDB()->getAffectedRows();
             }
             // remove obsolete language items
             $languageItemIDs = '';
             $sql = "SELECT\tlanguageItemID \n\t\t\t\t\tFROM\twcf" . WCF_N . "_language_item\n\t\t\t\t\tWHERE\tlanguageID IN (" . implode(',', $languages) . ")\n\t\t\t\t\t\tAND languageItem NOT IN (\n\t\t\t\t\t\t\tSELECT\tlanguageItem\n\t\t\t\t\t\t\tFROM\twcf" . WCF_N . "_language_item\n\t\t\t\t\t\t\tWHERE\tlanguageID = " . $this->sourceLanguageID . "\n\t\t\t\t\t\t)";
             $result = WCF::getDB()->sendQuery($sql);
             while ($row = WCF::getDB()->fetchArray($result)) {
                 $languageItemIDs .= ',' . $row['languageItemID'];
             }
             $sql = "DELETE FROM\twcf" . WCF_N . "_language_item\n\t\t\t\t\tWHERE\t\tlanguageItemID IN (0" . $languageItemIDs . ")";
             WCF::getDB()->sendQuery($sql);
             $this->deletedLanguageItems = WCF::getDB()->getAffectedRows();
         }
         // delete language files
         LanguageEditor::deleteLanguageFiles();
         $this->saved();
         // show success message
         WCF::getTPL()->assign(array('success' => true, 'addedLanguageItems' => $this->addedLanguageItems, 'deletedLanguageItems' => $this->deletedLanguageItems));
     }
 }
 /**
  * Clears relevant caches after package installation, update or uninstallation.
  */
 protected function makeClear()
 {
     require_once WCF_DIR . 'lib/acp/option/Options.class.php';
     require_once WCF_DIR . 'lib/system/language/LanguageEditor.class.php';
     // get dependent (standalone) packages
     $sql = "SELECT\t\tpackage.packageID, packageDir\n\t\t\tFROM\t\twcf" . WCF_N . "_package_dependency package_dependency\n\t\t\tLEFT JOIN\twcf" . WCF_N . "_package package\n\t\t\tON\t\t(package.packageID = package_dependency.packageID)\n\t\t\tWHERE\t\tpackage_dependency.dependency = " . $this->packageID . "\n\t\t\t\t\tAND package.standalone = 1";
     $result = WCF::getDB()->sendQuery($sql);
     while ($row = WCF::getDB()->fetchArray($result)) {
         // delete relevant language files
         LanguageEditor::deleteLanguageFiles('*', '*', $row['packageID']);
         if (!empty($row['packageDir'])) {
             // get real path
             $packageDir = FileUtil::addTrailingSlash(FileUtil::getRealPath(WCF_DIR . $row['packageDir']));
             // reset options.inc.php
             $filename = $packageDir . Options::FILENAME;
             if (file_exists($filename)) {
                 @unlink($filename);
             }
             // clear application cache
             WCF::getCache()->clear($packageDir . 'cache', '*.php', true);
         }
     }
     // clear general options file
     @unlink(WCF_DIR . 'options.inc.php');
     // clear general cache
     WCF::getCache()->clear(WCF_DIR . 'cache', '*.php', true);
     // delete compiled templates
     require_once WCF_DIR . 'lib/system/template/ACPTemplate.class.php';
     ACPTemplate::deleteCompiledACPTemplates();
     Template::deleteCompiledTemplates();
 }
 /**
  * Registers package information into database.
  */
 protected function installPackage()
 {
     $requirements = $this->packageArchive->getAllExistingRequirements();
     // finish installation
     if ($this->action == 'install') {
         $requirementsChanged = true;
         // calculate the number of instances of this package
         $instanceNo = 1;
         $sql = "SELECT\tCOUNT(*) AS count, MAX(instanceNo) AS instanceNo\n\t\t\t\tFROM\twcf" . WCF_N . "_package\n\t\t\t\tWHERE\tpackage = '" . escapeString($this->packageArchive->getPackageInfo('name')) . "'";
         $row = WCF::getDB()->getFirstRow($sql);
         if ($row['count'] > 0) {
             $instanceNo = $row['instanceNo'] + 1;
         }
         // register this package
         $sql = "INSERT INTO \twcf" . WCF_N . "_package\n\t\t\t\t\t\t(package, packageName, instanceNo, packageDescription, packageVersion, packageDate, packageURL, \n\t\t\t\t\t\tisUnique, standalone, author, authorURL, installDate, updateDate)\n\t\t\t\tVALUES\t\t('" . escapeString($this->packageArchive->getPackageInfo('name')) . "',\n\t\t\t\t\t\t'" . escapeString($this->packageArchive->getPackageInfo('packageName')) . "',\n\t\t\t\t\t\t" . $instanceNo . ",\n\t\t\t\t\t\t'" . escapeString($this->packageArchive->getPackageInfo('packageDescription')) . "',\n\t\t\t\t\t\t'" . escapeString($this->packageArchive->getPackageInfo('version')) . "',\n\t\t\t\t\t\t" . intval($this->packageArchive->getPackageInfo('date')) . ",\n\t\t\t\t\t\t'" . escapeString($this->packageArchive->getPackageInfo('packageURL')) . "',\n\t\t\t\t\t\t'" . intval($this->packageArchive->getPackageInfo('isUnique')) . "',\n\t\t\t\t\t\t'" . intval($this->packageArchive->getPackageInfo('standalone')) . "',\n\t\t\t\t\t\t'" . escapeString($this->packageArchive->getAuthorInfo('author')) . "',\n\t\t\t\t\t\t'" . escapeString($this->packageArchive->getAuthorInfo('authorURL')) . "',\n\t\t\t\t\t\t" . TIME_NOW . ",\n\t\t\t\t\t\t" . TIME_NOW . ")";
         WCF::getDB()->sendQuery($sql);
         $this->packageID = WCF::getDB()->getInsertID();
         // package package id in queue
         $sql = "UPDATE\twcf" . WCF_N . "_package_installation_queue\n\t\t\t\tSET \tpackageID \t= " . $this->packageID . " \n\t\t\t\tWHERE \tqueueID \t= " . $this->queueID;
         WCF::getDB()->sendQuery($sql);
     } else {
         $requirementsChanged = false;
         // update this package
         try {
             $sql = "UPDATE \twcf" . WCF_N . "_package \n\t\t\t\t\tSET \tpackageName \t\t= '" . escapeString($this->packageArchive->getPackageInfo('packageName')) . "', \n\t\t\t\t\t\tpackageDescription \t= '" . escapeString($this->packageArchive->getPackageInfo('packageDescription')) . "', \n\t\t\t\t\t\tpackageDate \t\t= " . intval($this->packageArchive->getPackageInfo('date')) . ", \n\t\t\t\t\t\tpackageURL \t\t= '" . escapeString($this->packageArchive->getPackageInfo('packageURL')) . "', \n\t\t\t\t\t\tauthor \t\t\t= '" . escapeString($this->packageArchive->getAuthorInfo('author')) . "', \n\t\t\t\t\t\tauthorURL \t\t= '" . escapeString($this->packageArchive->getAuthorInfo('authorURL')) . "',\n\t\t\t\t\t\tupdateDate\t\t= " . TIME_NOW . "\n\t\t\t\t\tWHERE \tpackageID \t\t= " . $this->packageID;
             WCF::getDB()->sendQuery($sql);
         } catch (DatabaseException $e) {
             // horizon update workaround
             $sql = "UPDATE \twcf" . WCF_N . "_package \n\t\t\t\t\tSET \tpackageName \t\t= '" . escapeString($this->packageArchive->getPackageInfo('packageName')) . "', \n\t\t\t\t\t\tpackageDescription \t= '" . escapeString($this->packageArchive->getPackageInfo('packageDescription')) . "', \n\t\t\t\t\t\tpackageDate \t\t= " . intval($this->packageArchive->getPackageInfo('date')) . ", \n\t\t\t\t\t\tpackageURL \t\t= '" . escapeString($this->packageArchive->getPackageInfo('packageURL')) . "', \n\t\t\t\t\t\tauthor \t\t\t= '" . escapeString($this->packageArchive->getAuthorInfo('author')) . "', \n\t\t\t\t\t\tauthorURL \t\t= '" . escapeString($this->packageArchive->getAuthorInfo('authorURL')) . "'\n\t\t\t\t\tWHERE \tpackageID \t\t= " . $this->packageID;
             WCF::getDB()->sendQuery($sql);
         }
         // check whether the requirements were changed
         $newRequirements = $this->packageArchive->getExistingRequirements();
         // get old requirements
         $sql = "SELECT\trequirement\n\t\t\t\tFROM\twcf" . WCF_N . "_package_requirement\n\t\t\t\tWHERE\tpackageID = " . $this->packageID;
         $result = WCF::getDB()->sendQuery($sql);
         while ($row = WCF::getDB()->fetchArray($result)) {
             $oldRequirement = false;
             foreach ($newRequirements as $key => $requirement) {
                 if ($row['requirement'] == $requirement['packageID']) {
                     $oldRequirement = true;
                     unset($newRequirements[$key]);
                     break;
                 }
             }
             if (!$oldRequirement) {
                 $requirementsChanged = true;
                 break;
             }
         }
         if (count($newRequirements) != 0) {
             $requirementsChanged = true;
         }
         // delete old excluded packages
         $sql = "DELETE FROM\twcf" . WCF_N . "_package_exclusion \n\t\t\t\tWHERE \t\tpackageID = " . $this->packageID;
         WCF::getDB()->sendQuery($sql);
         // delete old requirements
         $sql = "DELETE FROM\twcf" . WCF_N . "_package_requirement \n\t\t\t\tWHERE \t\tpackageID = " . $this->packageID;
         WCF::getDB()->sendQuery($sql);
     }
     // save excluded packages
     if (count($this->packageArchive->getExcludedPackages()) > 0) {
         $insertExcludedPackages = '';
         foreach ($this->packageArchive->getExcludedPackages() as $excludedPackage) {
             if (!empty($insertExcludedPackages)) {
                 $insertExcludedPackages .= ',';
             }
             $insertExcludedPackages .= "(" . $this->packageID . ", '" . escapeString($excludedPackage['name']) . "', '" . (!empty($excludedPackage['version']) ? escapeString($excludedPackage['version']) : '') . "')";
         }
         $sql = "INSERT INTO\twcf" . WCF_N . "_package_exclusion \n\t\t\t\t\t\t(packageID, excludedPackage, excludedPackageVersion)\n\t\t\t\tVALUES \t\t" . $insertExcludedPackages;
         WCF::getDB()->sendQuery($sql);
     }
     // register package requirements
     if (count($requirements) > 0) {
         $insertRequirements = '';
         $requirementIDs = '';
         foreach ($requirements as $identifier => $possibleRequirements) {
             if (count($possibleRequirements) == 1) {
                 $requirement = array_shift($possibleRequirements);
             } else {
                 $requirement = $possibleRequirements[$this->selectedRequirements[$identifier]];
             }
             if (!empty($insertRequirements)) {
                 $insertRequirements .= ',';
             }
             $insertRequirements .= "(" . $this->packageID . ", " . $requirement['packageID'] . ")";
             if (!empty($requirementIDs)) {
                 $requirementIDs .= ',';
             }
             $requirementIDs .= $requirement['packageID'];
         }
         $sql = "INSERT INTO\twcf" . WCF_N . "_package_requirement \n\t\t\t\t\t\t(packageID, requirement)\n\t\t\t\tVALUES \t\t" . $insertRequirements;
         WCF::getDB()->sendQuery($sql);
     }
     // rebuild package dependencies
     if ($requirementsChanged) {
         // build requirement map
         Package::rebuildPackageRequirementMap($this->packageID);
         // rebuild dependencies
         Package::rebuildPackageDependencies($this->packageID);
         if ($this->action == 'update') {
             Package::rebuildParentPackageDependencies($this->packageID);
         }
     }
     // reset package cache
     WCF::getCache()->clearResource('packages');
     // reset all cache resources
     //WCF::getCache()->clear(WCF_DIR.'cache', '*.php');
     // this is a bad fix to avoid
     // logout and some language errors
     // during the installation of package com.woltlab.wcf
     if ($this->action == 'install' && $this->packageArchive->getPackageInfo('name') == 'com.woltlab.wcf') {
         // avoid logout
         // update package id in acp sessions
         $sql = "UPDATE\twcf" . WCF_N . "_acp_session\n\t\t\t\tSET\tpackageID = " . $this->packageID . "\n\t\t\t\tWHERE\tpackageID = 0";
         WCF::getDB()->sendQuery($sql);
         // avoid language errors
         // update package id in language to packages relations
         $sql = "UPDATE\twcf" . WCF_N . "_language_to_packages\n\t\t\t\tSET\tpackageID = " . $this->packageID . "\n\t\t\t\tWHERE\tpackageID = 0";
         WCF::getDB()->sendQuery($sql);
         // update package id in language items
         $sql = "UPDATE\twcf" . WCF_N . "_language_item\n\t\t\t\tSET\tpackageID = " . $this->packageID . "\n\t\t\t\tWHERE\tpackageID = 0";
         WCF::getDB()->sendQuery($sql);
         // reset language cache
         WCF::getCache()->clearResource('languages');
         // rebuild language files
         LanguageEditor::updateAll();
         // delete language files of package 0
         LanguageEditor::deleteLanguageFiles('*', '*', 0);
         // update default group options
         // to avoid permission denied errors after next login
         $sql = "UPDATE\twcf" . WCF_N . "_group_option\n\t\t\t\tSET\tpackageID = " . $this->packageID . "\n\t\t\t\tWHERE\tpackageID = 0";
         WCF::getDB()->sendQuery($sql);
     }
 }
 /**
  * Updates this help item.
  * 
  * @param 	string		$name
  * @param 	string		$text
  * @param 	string		$parentItem
  * @param 	string		$refererPattern
  * @param 	integer		$showOrder
  * @param 	boolean		$isDisabled
  * @param	integer		$languageID
  * @param	integer		$packageID
  */
 public function update($name, $text = '', $parentItem = '', $refererPattern = '', $showOrder = 0, $isDisabled = 0, $languageID = 0, $packageID = PACKAGE_ID)
 {
     if ($parentItem == $this->helpItem) {
         $parentItem = $this->parentHelpItem;
     }
     // update show order
     if ($parentItem == $this->parentHelpItem) {
         if ($this->showOrder != $showOrder) {
             if ($showOrder < $this->showOrder) {
                 $sql = "UPDATE\twcf" . WCF_N . "_help_item\n\t\t\t\t\t\tSET \tshowOrder = showOrder + 1\n\t\t\t\t\t\tWHERE \tshowOrder >= " . $showOrder . "\n\t\t\t\t\t\t\tAND showOrder < " . $this->showOrder . "\n\t\t\t\t\t\t\tAND parentHelpItem = '" . escapeString($parentItem) . "'";
                 WCF::getDB()->sendQuery($sql);
             } else {
                 if ($showOrder > $this->showOrder) {
                     $sql = "UPDATE\twcf" . WCF_N . "_help_item\n\t\t\t\t\t\tSET\tshowOrder = showOrder - 1\n\t\t\t\t\t\tWHERE\tshowOrder <= " . $showOrder . "\n\t\t\t\t\t\t\tAND showOrder > " . $this->showOrder . "\n\t\t\t\t\t\t\tAND parentHelpItem = '" . escapeString($parentItem) . "'";
                     WCF::getDB()->sendQuery($sql);
                 }
             }
         }
     } else {
         $sql = "UPDATE\twcf" . WCF_N . "_help_item\n\t\t\t\tSET \tshowOrder = showOrder - 1\n\t\t\t\tWHERE \tshowOrder >= " . $this->showOrder . "\n\t\t\t\t\tAND parentHelpItem = '" . escapeString($this->parentHelpItem) . "'";
         WCF::getDB()->sendQuery($sql);
         $sql = "UPDATE \twcf" . WCF_N . "_help_item\n\t\t\t\tSET \tshowOrder = showOrder + 1\n\t\t\t\tWHERE \tshowOrder >= " . $showOrder . "\n\t\t\t\t\tAND parentHelpItem = '" . escapeString($parentItem) . "'";
         WCF::getDB()->sendQuery($sql);
     }
     // Update
     $sql = "UPDATE\twcf" . WCF_N . "_help_item\n\t\t\tSET\t" . ($languageID == 0 ? "helpItem = '" . escapeString($name) . "'," : '') . "\n\t\t\t\tparentHelpItem = '" . escapeString($parentItem) . "',\n\t\t\t\trefererPattern = '" . escapeString($refererPattern) . "',\n\t\t\t\tshowOrder = " . $showOrder . ",\n\t\t\t\tisDisabled = " . $isDisabled . "\n\t\t\tWHERE \thelpItemID = " . $this->helpItemID . ";";
     WCF::getDB()->sendQuery($sql);
     if ($languageID != 0) {
         // save language variables
         $language = new LanguageEditor($languageID);
         $language->updateItems(array('wcf.help.item.' . $this->helpItem => $name, 'wcf.help.item.' . $this->helpItem . '.description' => $text), 0, $this->packageID, array('wcf.help.item.' . $this->helpItem => 1, 'wcf.help.item.' . $this->helpItem . '.description' => 1));
         LanguageEditor::deleteLanguageFiles($languageID, 'wcf.help.item');
         $language->deleteCompiledTemplates();
     }
 }