/** * Returns a list of available updates for installed packages. * * @param boolean $removeRequirements * @return array */ public static function getAvailableUpdates($removeRequirements = true) { $updates = array(); // get update server data $updateServers = PackageUpdateServer::getActiveUpdateServers(); $packageUpdateServerIDs = array_keys($updateServers); if (empty($packageUpdateServerIDs)) { return $updates; } // get existing packages and their versions $existingPackages = array(); $sql = "SELECT\tpackageID, package, instanceNo, packageDescription,\n\t\t\t\tpackageVersion, packageDate, author, authorURL, isApplication,\n\t\t\t\tCASE WHEN instanceName <> '' THEN instanceName ELSE packageName END AS packageName\n\t\t\tFROM\twcf" . WCF_N . "_package"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(); while ($row = $statement->fetchArray()) { $existingPackages[$row['package']][] = $row; } if (empty($existingPackages)) { return $updates; } // get all update versions $conditions = new PreparedStatementConditionBuilder(); $conditions->add("pu.packageUpdateServerID IN (?)", array($packageUpdateServerIDs)); $conditions->add("package IN (SELECT DISTINCT package FROM wcf" . WCF_N . "_package)"); $sql = "SELECT\t\tpu.packageUpdateID, pu.packageUpdateServerID, pu.package,\n\t\t\t\t\tpuv.packageUpdateVersionID, puv.updateType, puv.packageDate, puv.filename, puv.packageVersion\n\t\t\tFROM\t\twcf" . WCF_N . "_package_update pu\n\t\t\tLEFT JOIN\twcf" . WCF_N . "_package_update_version puv\n\t\t\tON\t\t(puv.packageUpdateID = pu.packageUpdateID)\n\t\t\t" . $conditions; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute($conditions->getParameters()); while ($row = $statement->fetchArray()) { // test version foreach ($existingPackages[$row['package']] as $existingVersion) { if (Package::compareVersion($existingVersion['packageVersion'], $row['packageVersion'], '<')) { // package data if (!isset($updates[$existingVersion['packageID']])) { $existingVersion['versions'] = array(); $updates[$existingVersion['packageID']] = $existingVersion; } // version data if (!isset($updates[$existingVersion['packageID']]['versions'][$row['packageVersion']])) { $updates[$existingVersion['packageID']]['versions'][$row['packageVersion']] = array('updateType' => $row['updateType'], 'packageDate' => $row['packageDate'], 'packageVersion' => $row['packageVersion'], 'servers' => array()); } // server data $updates[$existingVersion['packageID']]['versions'][$row['packageVersion']]['servers'][] = array('packageUpdateID' => $row['packageUpdateID'], 'packageUpdateServerID' => $row['packageUpdateServerID'], 'packageUpdateVersionID' => $row['packageUpdateVersionID'], 'filename' => $row['filename']); } } } // sort package versions // and remove old versions foreach ($updates as $packageID => $data) { uksort($updates[$packageID]['versions'], array('Package', 'compareVersion')); $updates[$packageID]['version'] = end($updates[$packageID]['versions']); } // remove requirements of application packages if ($removeRequirements) { foreach ($existingPackages as $identifier => $instances) { foreach ($instances as $instance) { if ($instance['isApplication'] && isset($updates[$instance['packageID']])) { $updates = self::removeUpdateRequirements($updates, $updates[$instance['packageID']]['version']['servers'][0]['packageUpdateVersionID']); } } } } return $updates; }
/** * Returns a result list of a search for installable packages. * * @return array */ public function search() { PackageUpdateDispatcher::getInstance()->refreshPackageDatabase(); $availableUpdateServers = PackageUpdateServer::getActiveUpdateServers(); // there are no available package update servers if (empty($availableUpdateServers)) { WCF::getTPL()->assign(array('packageUpdates' => array())); return array('count' => 0, 'pageCount' => 0, 'searchID' => 0, 'template' => WCF::getTPL()->fetch('packageSearchResultList')); } $conditions = new PreparedStatementConditionBuilder(); $conditions->add("package_update.packageUpdateServerID IN (?)", array(array_keys($availableUpdateServers))); if (!empty($this->parameters['package'])) { $conditions->add("package_update.package LIKE ?", array('%' . $this->parameters['package'] . '%')); } if (!empty($this->parameters['packageDescription'])) { $conditions->add("package_update.packageDescription LIKE ?", array('%' . $this->parameters['packageDescription'] . '%')); } if (!empty($this->parameters['packageName'])) { $conditions->add("package_update.packageName LIKE ?", array('%' . $this->parameters['packageName'] . '%')); } $conditions->add("package.packageID IS NULL"); // find matching packages $sql = "SELECT\t\tpackage_update.packageUpdateID\n\t\t\tFROM\t\twcf" . WCF_N . "_package_update package_update\n\t\t\tLEFT JOIN\twcf" . WCF_N . "_package package\n\t\t\tON\t\t(package.package = package_update.package)\n\t\t\t" . $conditions . "\n\t\t\tORDER BY\tpackage_update.packageName ASC"; $statement = WCF::getDB()->prepareStatement($sql, 1000); $statement->execute($conditions->getParameters()); $packageUpdateIDs = array(); while ($row = $statement->fetchArray()) { $packageUpdateIDs[] = $row['packageUpdateID']; } // no matches found if (empty($packageUpdateIDs)) { WCF::getTPL()->assign(array('packageUpdates' => array())); return array('count' => 0, 'pageCount' => 0, 'searchID' => 0, 'template' => WCF::getTPL()->fetch('packageSearchResultList')); } // get excluded packages $sql = "SELECT\t*\n\t\t\tFROM\twcf" . WCF_N . "_package_update_exclusion"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(); $excludedPackages = array(); while ($row = $statement->fetchArray()) { $package = $row['excludedPackage']; $packageVersion = $row['excludedPackageVersion']; $packageUpdateVersionID = $row['packageUpdateVersionID']; if (!isset($excludedPackages[$packageUpdateVersionID][$package])) { $excludedPackages[$packageUpdateVersionID][$package] = $packageVersion; } else { if (Package::compareVersion($excludedPackages[$packageUpdateVersionID][$package], $packageVersion) == 1) { $excludedPackages[$packageUpdateVersionID][$package] = $packageVersion; } } } // get installed packages $sql = "SELECT\tpackage, packageVersion\n\t\t\tFROM\twcf" . WCF_N . "_package"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(); $installedPackages = array(); while ($row = $statement->fetchArray()) { $installedPackages[$row['package']] = $row['packageVersion']; } // filter by version $conditions = new PreparedStatementConditionBuilder(); $conditions->add("puv.packageUpdateID IN (?)", array($packageUpdateIDs)); $sql = "SELECT\t\tpu.package, puv.packageUpdateVersionID, puv.packageUpdateID, puv.packageVersion, puv.isAccessible\n\t\t\tFROM\t\twcf" . WCF_N . "_package_update_version puv\n\t\t\tLEFT JOIN\twcf" . WCF_N . "_package_update pu\n\t\t\tON\t\t(pu.packageUpdateID = puv.packageUpdateID)\n\t\t\t" . $conditions; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute($conditions->getParameters()); $packageVersions = array(); while ($row = $statement->fetchArray()) { $package = $row['package']; $packageVersion = $row['packageVersion']; $packageUpdateVersionID = $row['packageUpdateVersionID']; // check excluded packages if (isset($excludedPackages[$packageUpdateVersionID])) { $isExcluded = false; foreach ($excludedPackages[$packageUpdateVersionID] as $excludedPackage => $excludedPackageVersion) { if (isset($installedPackages[$excludedPackage]) && Package::compareVersion($excludedPackageVersion, $installedPackages[$excludedPackage]) <= 0) { // excluded, ignore $isExcluded = true; break; } } if ($isExcluded) { continue; } } if (!isset($packageVersions[$package])) { $packageVersions[$package] = array(); } $packageUpdateID = $row['packageUpdateID']; if (!isset($packageVersions[$package][$packageUpdateID])) { $packageVersions[$package][$packageUpdateID] = array('accessible' => array(), 'existing' => array()); } if ($row['isAccessible']) { $packageVersions[$package][$packageUpdateID]['accessible'][$row['packageUpdateVersionID']] = $packageVersion; } $packageVersions[$package][$packageUpdateID]['existing'][$row['packageUpdateVersionID']] = $packageVersion; } // all found versions are excluded if (empty($packageVersions)) { WCF::getTPL()->assign(array('packageUpdates' => array())); return array('count' => 0, 'pageCount' => 0, 'searchID' => 0, 'template' => WCF::getTPL()->fetch('packageSearchResultList')); } // determine highest versions $packageUpdates = array(); foreach ($packageVersions as $package => $versionData) { $accessible = $existing = $versions = array(); foreach ($versionData as $packageUpdateID => $versionTypes) { // ignore unaccessible packages if (empty($versionTypes['accessible'])) { continue; } uasort($versionTypes['accessible'], array('wcf\\data\\package\\Package', 'compareVersion')); uasort($versionTypes['existing'], array('wcf\\data\\package\\Package', 'compareVersion')); $accessibleVersion = array_slice($versionTypes['accessible'], -1, 1, true); $existingVersion = array_slice($versionTypes['existing'], -1, 1, true); $ak = key($accessibleVersion); $av = current($accessibleVersion); $ek = key($existingVersion); $ev = current($existingVersion); $accessible[$av] = $ak; $existing[$ev] = $ek; $versions[$ak] = $packageUpdateID; $versions[$ek] = $packageUpdateID; } // ignore packages without accessible versions if (empty($accessible)) { continue; } uksort($accessible, array('wcf\\data\\package\\Package', 'compareVersion')); uksort($existing, array('wcf\\data\\package\\Package', 'compareVersion')); $accessible = array_pop($accessible); $existing = array_pop($existing); $packageUpdates[$versions[$accessible]] = array('accessible' => $accessible, 'existing' => $existing); } // no found packages is accessible if (empty($packageUpdates)) { WCF::getTPL()->assign(array('packageUpdates' => array())); return array('count' => 0, 'pageCount' => 0, 'searchID' => 0, 'template' => WCF::getTPL()->fetch('packageSearchResultList')); } $search = SearchEditor::create(array('userID' => WCF::getUser()->userID, 'searchData' => serialize($packageUpdates), 'searchTime' => TIME_NOW, 'searchType' => 'acpPackageSearch')); // forward call to build the actual result list $updateAction = new PackageUpdateAction(array(), 'getResultList', array('pageNo' => 1, 'search' => $search)); $returnValues = $updateAction->executeAction(); return $returnValues['returnValues']; }
/** * Returns a list of available updates for installed packages. * * @param boolean $removeRequirements * @param boolean $removeOlderMinorReleases * @return array */ public function getAvailableUpdates($removeRequirements = true, $removeOlderMinorReleases = false) { $updates = array(); // get update server data $updateServers = PackageUpdateServer::getActiveUpdateServers(); $packageUpdateServerIDs = array_keys($updateServers); if (empty($packageUpdateServerIDs)) { return $updates; } // get existing packages and their versions $existingPackages = array(); $sql = "SELECT\tpackageID, package, packageDescription, packageName,\n\t\t\t\tpackageVersion, packageDate, author, authorURL, isApplication\n\t\t\tFROM\twcf" . WCF_N . "_package"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(); while ($row = $statement->fetchArray()) { $existingPackages[$row['package']][] = $row; } if (empty($existingPackages)) { return $updates; } // get all update versions $conditions = new PreparedStatementConditionBuilder(); $conditions->add("pu.packageUpdateServerID IN (?)", array($packageUpdateServerIDs)); $conditions->add("package IN (SELECT DISTINCT package FROM wcf" . WCF_N . "_package)"); $sql = "SELECT\t\tpu.packageUpdateID, pu.packageUpdateServerID, pu.package,\n\t\t\t\t\tpuv.packageUpdateVersionID, puv.isCritical, puv.packageDate, puv.filename, puv.packageVersion\n\t\t\tFROM\t\twcf" . WCF_N . "_package_update pu\n\t\t\tLEFT JOIN\twcf" . WCF_N . "_package_update_version puv\n\t\t\tON\t\t(puv.packageUpdateID = pu.packageUpdateID AND puv.isAccessible = 1)\n\t\t\t" . $conditions; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute($conditions->getParameters()); while ($row = $statement->fetchArray()) { // test version foreach ($existingPackages[$row['package']] as $existingVersion) { if (Package::compareVersion($existingVersion['packageVersion'], $row['packageVersion'], '<')) { // package data if (!isset($updates[$existingVersion['packageID']])) { $existingVersion['versions'] = array(); $updates[$existingVersion['packageID']] = $existingVersion; } // version data if (!isset($updates[$existingVersion['packageID']]['versions'][$row['packageVersion']])) { $updates[$existingVersion['packageID']]['versions'][$row['packageVersion']] = array('isCritical' => $row['isCritical'], 'packageDate' => $row['packageDate'], 'packageVersion' => $row['packageVersion'], 'servers' => array()); } // server data $updates[$existingVersion['packageID']]['versions'][$row['packageVersion']]['servers'][] = array('packageUpdateID' => $row['packageUpdateID'], 'packageUpdateServerID' => $row['packageUpdateServerID'], 'packageUpdateVersionID' => $row['packageUpdateVersionID'], 'filename' => $row['filename']); } } } // sort package versions // and remove old versions foreach ($updates as $packageID => $data) { uksort($updates[$packageID]['versions'], array('wcf\\data\\package\\Package', 'compareVersion')); $updates[$packageID]['version'] = end($updates[$packageID]['versions']); } // remove requirements of application packages if ($removeRequirements) { foreach ($existingPackages as $identifier => $instances) { foreach ($instances as $instance) { if ($instance['isApplication'] && isset($updates[$instance['packageID']])) { $updates = $this->removeUpdateRequirements($updates, $updates[$instance['packageID']]['version']['servers'][0]['packageUpdateVersionID']); } } } } // remove older minor releases from list, e.g. only display 1.0.2, even if 1.0.1 is available if ($removeOlderMinorReleases) { foreach ($updates as &$updateData) { $highestVersions = array(); foreach ($updateData['versions'] as $versionNumber => $dummy) { if (preg_match('~^(\\d+\\.\\d+)\\.~', $versionNumber, $matches)) { $major = $matches[1]; if (isset($highestVersions[$major])) { if (Package::compareVersion($highestVersions[$major], $versionNumber, '<')) { // version is newer, discard current version unset($updateData['versions'][$highestVersions[$major]]); $highestVersions[$major] = $versionNumber; } else { // version is lower, discard unset($updateData['versions'][$versionNumber]); } } else { $highestVersions[$major] = $versionNumber; } } } } unset($updateData); } return $updates; }
/** * Creates a new instance of PackageInstallationScheduler * * @param array<string> $selectedPackages */ public function __construct(array $selectedPackages) { $this->selectedPackages = $selectedPackages; $this->packageUpdateServers = PackageUpdateServer::getActiveUpdateServers(); }
/** * @see wcf\page\IPage::readData() */ public function readData() { parent::readData(); $this->updateServers = PackageUpdateServer::getActiveUpdateServers(); }