/**
  * Updates information parsed from a packages_update.xml into the database.
  * 
  * @param 	array		$allNewPackages
  * @param	integer		$packageUpdateServerID
  */
 protected static function savePackageUpdates(array &$allNewPackages, $packageUpdateServerID)
 {
     // find existing packages and delete them
     // get existing packages
     $existingPackages = array();
     $packageUpdateList = new PackageUpdateList();
     $packageUpdateList->getConditionBuilder()->add("package_update.packageUpdateServerID = ? AND package_update.package IN (?)", array($packageUpdateServerID, array_keys($allNewPackages)));
     $packageUpdateList->sqlLimit = 0;
     $packageUpdateList->readObjects();
     $tmp = $packageUpdateList->getObjects();
     foreach ($tmp as $packageUpdate) {
         $existingPackages[$packageUpdate->package] = $packageUpdate;
     }
     // get existing versions
     $existingPackageVersions = array();
     if (count($existingPackages) > 0) {
         // get package update ids
         $packageUpdateIDs = array();
         foreach ($existingPackages as $packageUpdate) {
             $packageUpdateIDs[] = $packageUpdate->packageUpdateID;
         }
         // get version list
         $versionList = new PackageUpdateVersionList();
         $versionList->getConditionBuilder()->add("package_update_version.packageUpdateID IN (?)", array($packageUpdateIDs));
         $versionList->sqlLimit = 0;
         $versionList->readObjects();
         $tmp = $versionList->getObjects();
         foreach ($tmp as $version) {
             if (!isset($existingPackageVersions[$version->packageUpdateID])) {
                 $existingPackageVersions[$version->packageUpdateID] = array();
             }
             $existingPackageVersions[$version->packageUpdateID][$version->packageVersion] = $version;
         }
     }
     // insert updates
     $excludedPackagesParameters = $fromversionParameters = $insertParameters = array();
     foreach ($allNewPackages as $identifier => $packageData) {
         if (isset($existingPackages[$identifier])) {
             $packageUpdateID = $existingPackages[$identifier]->packageUpdateID;
             // update database entry
             $packageUpdateEditor = new PackageUpdateEditor($existingPackages[$identifier]);
             $packageUpdateEditor->update(array('packageName' => $packageData['packageName'], 'packageDescription' => $packageData['packageDescription'], 'author' => $packageData['author'], 'authorURL' => $packageData['authorURL'], 'isApplication' => $packageData['isApplication'], 'plugin' => $packageData['plugin']));
         } else {
             // create new database entry
             $packageUpdate = PackageUpdateEditor::create(array('packageUpdateServerID' => $packageUpdateServerID, 'package' => $identifier, 'packageName' => $packageData['packageName'], 'packageDescription' => $packageData['packageDescription'], 'author' => $packageData['author'], 'authorURL' => $packageData['authorURL'], 'isApplication' => $packageData['isapplication'], 'plugin' => $packageData['plugin']));
             $packageUpdateID = $packageUpdate->packageUpdateID;
         }
         // register version(s) of this update package.
         if (isset($packageData['versions'])) {
             foreach ($packageData['versions'] as $packageVersion => $versionData) {
                 if (isset($versionData['file'])) {
                     $packageFile = $versionData['file'];
                 } else {
                     $packageFile = '';
                 }
                 if (isset($existingPackageVersions[$packageUpdateID]) && isset($existingPackageVersions[$packageUpdateID][$packageVersion])) {
                     $packageUpdateVersionID = $existingPackageVersions[$packageUpdateID][$packageVersion]->packageUpdateVersionID;
                     // update database entry
                     $versionEditor = new PackageUpdateVersionEditor($existingPackageVersions[$packageUpdateID][$packageVersion]);
                     $versionEditor->update(array('updateType' => $versionData['updateType'], 'packageDate' => $versionData['packageDate'], 'filename' => $packageFile));
                 } else {
                     // create new database entry
                     $version = PackageUpdateVersionEditor::create(array('packageUpdateID' => $packageUpdateID, 'packageVersion' => $packageVersion, 'updateType' => $versionData['updateType'], 'packageDate' => $versionData['packageDate'], 'filename' => $packageFile));
                     $packageUpdateVersionID = $version->packageUpdateVersionID;
                 }
                 // register requirement(s) of this update package version.
                 if (isset($versionData['requiredPackages'])) {
                     foreach ($versionData['requiredPackages'] as $requiredIdentifier => $required) {
                         $requirementInserts[] = array('packageUpdateVersionID' => $packageUpdateVersionID, 'package' => $requiredIdentifier, 'minversion' => isset($required['minversion']) ? $required['minversion'] : '');
                     }
                 }
                 // register excluded packages of this update package version.
                 if (isset($versionData['excludedPackages'])) {
                     foreach ($versionData['excludedPackages'] as $excludedIdentifier => $exclusion) {
                         $excludedPackagesParameters[] = array('packageUpdateVersionID' => $packageUpdateVersionID, 'excludedPackage' => $excludedIdentifier, 'excludedPackageVersion' => isset($exclusion['version']) ? $exclusion['version'] : '');
                     }
                 }
                 // register fromversions of this update package version.
                 if (isset($versionData['fromversions'])) {
                     foreach ($versionData['fromversions'] as $fromversion) {
                         $fromversionInserts[] = array('packageUpdateVersionID' => $packageUpdateVersionID, 'fromversion' => $fromversion);
                     }
                 }
             }
         }
     }
     // save requirements, excluded packages and fromversions
     // use multiple inserts to save some queries
     if (!empty($requirementInserts)) {
         // clear records
         $sql = "DELETE pur FROM\twcf" . WCF_N . "_package_update_requirement pur\n\t\t\t\tLEFT JOIN\twcf" . WCF_N . "_package_update_version puv\n\t\t\t\tON\t\t(puv.packageUpdateVersionID = pur.packageUpdateVersionID)\n\t\t\t\tLEFT JOIN\twcf" . WCF_N . "_package_update pu\n\t\t\t\tON\t\t(pu.packageUpdateID = puv.packageUpdateID)\n\t\t\t\tWHERE\t\tpu.packageUpdateServerID = ?";
         $statement = WCF::getDB()->prepareStatement($sql);
         $statement->execute(array($packageUpdateServerID));
         // insert requirements
         $sql = "INSERT INTO\twcf" . WCF_N . "_package_update_requirement\n\t\t\t\t\t\t(packageUpdateVersionID, package, minversion)\n\t\t\t\tVALUES\t\t(?, ?, ?)";
         $statement = WCF::getDB()->prepareStatement($sql);
         foreach ($requirementInserts as $requirement) {
             $statement->execute(array($requirement['packageUpdateVersionID'], $requirement['package'], $requirement['minversion']));
         }
     }
     if (!empty($excludedPackagesParameters)) {
         // clear records
         $sql = "DELETE pue FROM\twcf" . WCF_N . "_package_update_exclusion pue\n\t\t\t\tLEFT JOIN\twcf" . WCF_N . "_package_update_version puv\n\t\t\t\tON\t\t(puv.packageUpdateVersionID = pue.packageUpdateVersionID)\n\t\t\t\tLEFT JOIN\twcf" . WCF_N . "_package_update pu\n\t\t\t\tON\t\t(pu.packageUpdateID = puv.packageUpdateID)\n\t\t\t\tWHERE\t\tpu.packageUpdateServerID = ?";
         $statement = WCF::getDB()->prepareStatement($sql);
         $statement->execute(array($packageUpdateServerID));
         // insert excludes
         $sql = "INSERT INTO\twcf" . WCF_N . "_package_update_exclusion\n\t\t\t\t\t\t(packageUpdateVersionID, excludedPackage, excludedPackageVersion)\n\t\t\t\tVALUES\t\t(?, ?, ?)";
         $statement = WCF::getDB()->prepareStatement($sql);
         foreach ($excludedPackagesParameters as $excludedPackage) {
             $statement->execute(array($excludedPackage['packageUpdateVersionID'], $excludedPackage['excludedPackage'], $excludedPackage['excludedPackageVersion']));
         }
     }
     if (!empty($fromversionInserts)) {
         // clear records
         $sql = "DELETE puf FROM\twcf" . WCF_N . "_package_update_fromversion puf\n\t\t\t\tLEFT JOIN\twcf" . WCF_N . "_package_update_version puv\n\t\t\t\tON\t\t(puv.packageUpdateVersionID = puf.packageUpdateVersionID)\n\t\t\t\tLEFT JOIN\twcf" . WCF_N . "_package_update pu\n\t\t\t\tON\t\t(pu.packageUpdateID = puv.packageUpdateID)\n\t\t\t\tWHERE\t\tpu.packageUpdateServerID = ?";
         $statement = WCF::getDB()->prepareStatement($sql);
         $statement->execute(array($packageUpdateServerID));
         // insert excludes
         $sql = "INSERT INTO\twcf" . WCF_N . "_package_update_fromversion\n\t\t\t\t\t\t(packageUpdateVersionID, fromversion)\n\t\t\t\tVALUES\t\t(?, ?)";
         $statement = WCF::getDB()->prepareStatement($sql);
         foreach ($fromversionInserts as $fromversion) {
             $statement->execute(array($fromversion['packageUpdateVersionID'], $fromversion['fromversion']));
         }
     }
 }
	/**
	 * Updates information parsed from a packages_update.xml into the database.
	 * 
	 * @param	array		$allNewPackages
	 * @param	integer		$packageUpdateServerID
	 */
	protected function savePackageUpdates(array &$allNewPackages, $packageUpdateServerID) {
		// find existing packages and delete them
		// get existing packages
		$existingPackages = array();
		$packageUpdateList = new PackageUpdateList();
		$packageUpdateList->getConditionBuilder()->add("package_update.packageUpdateServerID = ? AND package_update.package IN (?)", array($packageUpdateServerID, array_keys($allNewPackages)));
		$packageUpdateList->readObjects();
		$tmp = $packageUpdateList->getObjects();
		
		foreach ($tmp as $packageUpdate) {
			$existingPackages[$packageUpdate->package] = $packageUpdate;
		}
		
		// get existing versions
		$existingPackageVersions = array();
		if (!empty($existingPackages)) {
			// get package update ids
			$packageUpdateIDs = array();
			foreach ($existingPackages as $packageUpdate) {
				$packageUpdateIDs[] = $packageUpdate->packageUpdateID;
			}
			
			// get version list
			$versionList = new PackageUpdateVersionList();
			$versionList->getConditionBuilder()->add("package_update_version.packageUpdateID IN (?)", array($packageUpdateIDs));
			$versionList->readObjects();
			$tmp = $versionList->getObjects();
			
			foreach ($tmp as $version) {
				if (!isset($existingPackageVersions[$version->packageUpdateID])) $existingPackageVersions[$version->packageUpdateID] = array();
				$existingPackageVersions[$version->packageUpdateID][$version->packageVersion] = $version;
			}
		}
		
		// insert updates
		$excludedPackagesParameters = $fromversionParameters = $insertParameters = $optionalInserts = $requirementInserts = array();
		foreach ($allNewPackages as $identifier => $packageData) {
			if (isset($existingPackages[$identifier])) {
				$packageUpdateID = $existingPackages[$identifier]->packageUpdateID;
				
				// update database entry
				$packageUpdateEditor = new PackageUpdateEditor($existingPackages[$identifier]);
				$packageUpdateEditor->update(array(
					'packageName' => $packageData['packageName'],
					'packageDescription' => $packageData['packageDescription'],
					'author' => $packageData['author'],
					'authorURL' => $packageData['authorURL'],
					'isApplication' => $packageData['isApplication']
				));
			}
			else {
				// create new database entry
				$packageUpdate = PackageUpdateEditor::create(array(
					'packageUpdateServerID' => $packageUpdateServerID,
					'package' => $identifier,
					'packageName' => $packageData['packageName'],
					'packageDescription' => $packageData['packageDescription'],
					'author' => $packageData['author'],
					'authorURL' => $packageData['authorURL'],
					'isApplication' => $packageData['isApplication']
				));
				
				$packageUpdateID = $packageUpdate->packageUpdateID;
			}
			
			// register version(s) of this update package.
			if (isset($packageData['versions'])) {
				foreach ($packageData['versions'] as $packageVersion => $versionData) {
					if (isset($versionData['file'])) $packageFile = $versionData['file'];
					else $packageFile = '';
					
					if (isset($existingPackageVersions[$packageUpdateID]) && isset($existingPackageVersions[$packageUpdateID][$packageVersion])) {
						$packageUpdateVersionID = $existingPackageVersions[$packageUpdateID][$packageVersion]->packageUpdateVersionID;
						
						// update database entry
						$versionEditor = new PackageUpdateVersionEditor($existingPackageVersions[$packageUpdateID][$packageVersion]);
						$versionEditor->update(array(
							'filename' => $packageFile,
							'isAccessible' => ($versionData['isAccessible'] ? 1 : 0),
							'isCritical' => ($versionData['isCritical'] ? 1 : 0),
							'license' => (isset($versionData['license']['license']) ? $versionData['license']['license'] : ''),
							'licenseURL' => (isset($versionData['license']['license']) ? $versionData['license']['licenseURL'] : ''),
							'packageDate' => $versionData['packageDate']
						));
					}
					else {
						// create new database entry
						$version = PackageUpdateVersionEditor::create(array(
							'filename' => $packageFile,
							'license' => (isset($versionData['license']['license']) ? $versionData['license']['license'] : ''),
							'licenseURL' => (isset($versionData['license']['license']) ? $versionData['license']['licenseURL'] : ''),
							'isAccessible' => ($versionData['isAccessible'] ? 1 : 0),
							'isCritical' => ($versionData['isCritical'] ? 1 : 0),
							'packageDate' => $versionData['packageDate'],
							'packageUpdateID' => $packageUpdateID,
							'packageVersion' => $packageVersion
						));
						
						$packageUpdateVersionID = $version->packageUpdateVersionID;
					}
					
					// register requirement(s) of this update package version.
					if (isset($versionData['requiredPackages'])) {
						foreach ($versionData['requiredPackages'] as $requiredIdentifier => $required) {
							$requirementInserts[] = array(
								'packageUpdateVersionID' => $packageUpdateVersionID,
								'package' => $requiredIdentifier,
								'minversion' => (isset($required['minversion']) ? $required['minversion'] : '')
							);
						}
					}
					
					// register optional packages of this update package version
					if (isset($versionData['optionalPackages'])) {
						foreach ($versionData['optionalPackages'] as $optionalPackage) {
							$optionalInserts[] = array(
								'packageUpdateVersionID' => $packageUpdateVersionID,
								'package' => $optionalPackage
							);
						}
					}
					
					// register excluded packages of this update package version.
					if (isset($versionData['excludedPackages'])) {
						foreach ($versionData['excludedPackages'] as $excludedIdentifier => $exclusion) {
							$excludedPackagesParameters[] = array(
								'packageUpdateVersionID' => $packageUpdateVersionID,
								'excludedPackage' => $excludedIdentifier,
								'excludedPackageVersion' => (isset($exclusion['version']) ? $exclusion['version'] : '')
							);
						}
					}
					
					// register fromversions of this update package version.
					if (isset($versionData['fromversions'])) {
						foreach ($versionData['fromversions'] as $fromversion) {
							$fromversionInserts[] = array(
								'packageUpdateVersionID' => $packageUpdateVersionID,
								'fromversion' => $fromversion
							);
						}
					}
				}
			}
		}
		
		// save requirements, excluded packages and fromversions
		// use multiple inserts to save some queries
		if (!empty($requirementInserts)) {
			// clear records
			$sql = "DELETE pur FROM	wcf".WCF_N."_package_update_requirement pur
				LEFT JOIN	wcf".WCF_N."_package_update_version puv
				ON		(puv.packageUpdateVersionID = pur.packageUpdateVersionID)
				LEFT JOIN	wcf".WCF_N."_package_update pu
				ON		(pu.packageUpdateID = puv.packageUpdateID)
				WHERE		pu.packageUpdateServerID = ?";
			$statement = WCF::getDB()->prepareStatement($sql);
			$statement->execute(array($packageUpdateServerID));
			
			// insert requirements
			$sql = "INSERT INTO	wcf".WCF_N."_package_update_requirement
						(packageUpdateVersionID, package, minversion)
				VALUES		(?, ?, ?)";
			$statement = WCF::getDB()->prepareStatement($sql);
			foreach ($requirementInserts as $requirement) {
				$statement->execute(array(
					$requirement['packageUpdateVersionID'],
					$requirement['package'],
					$requirement['minversion']
				));
			}
		}
		
		if (!empty($optionalInserts)) {
			// clear records
			$sql = "DELETE puo FROM	wcf".WCF_N."_package_update_optional puo
				LEFT JOIN	wcf".WCF_N."_package_update_version puv
				ON		(puv.packageUpdateVersionID = puo.packageUpdateVersionID)
				LEFT JOIN	wcf".WCF_N."_package_update pu
				ON		(pu.packageUpdateID = puv.packageUpdateID)
				WHERE		pu.packageUpdateServerID = ?";
			$statement = WCF::getDB()->prepareStatement($sql);
			$statement->execute(array($packageUpdateServerID));
				
			// insert requirements
			$sql = "INSERT INTO	wcf".WCF_N."_package_update_optional
						(packageUpdateVersionID, package)
				VALUES		(?, ?)";
			$statement = WCF::getDB()->prepareStatement($sql);
			foreach ($optionalInserts as $requirement) {
				$statement->execute(array(
					$requirement['packageUpdateVersionID'],
					$requirement['package']
				));
			}
		}
		
		if (!empty($excludedPackagesParameters)) {
			// clear records
			$sql = "DELETE pue FROM	wcf".WCF_N."_package_update_exclusion pue
				LEFT JOIN	wcf".WCF_N."_package_update_version puv
				ON		(puv.packageUpdateVersionID = pue.packageUpdateVersionID)
				LEFT JOIN	wcf".WCF_N."_package_update pu
				ON		(pu.packageUpdateID = puv.packageUpdateID)
				WHERE		pu.packageUpdateServerID = ?";
			$statement = WCF::getDB()->prepareStatement($sql);
			$statement->execute(array($packageUpdateServerID));
			
			// insert excludes
			$sql = "INSERT INTO	wcf".WCF_N."_package_update_exclusion
						(packageUpdateVersionID, excludedPackage, excludedPackageVersion)
				VALUES		(?, ?, ?)";
			$statement = WCF::getDB()->prepareStatement($sql);
			foreach ($excludedPackagesParameters as $excludedPackage) {
				$statement->execute(array(
					$excludedPackage['packageUpdateVersionID'],
					$excludedPackage['excludedPackage'],
					$excludedPackage['excludedPackageVersion']
				));
			}
		}
		
		if (!empty($fromversionInserts)) {
			// clear records
			$sql = "DELETE puf FROM	wcf".WCF_N."_package_update_fromversion puf
				LEFT JOIN	wcf".WCF_N."_package_update_version puv
				ON		(puv.packageUpdateVersionID = puf.packageUpdateVersionID)
				LEFT JOIN	wcf".WCF_N."_package_update pu
				ON		(pu.packageUpdateID = puv.packageUpdateID)
				WHERE		pu.packageUpdateServerID = ?";
			$statement = WCF::getDB()->prepareStatement($sql);
			$statement->execute(array($packageUpdateServerID));
			
			// insert excludes
			$sql = "INSERT INTO	wcf".WCF_N."_package_update_fromversion
						(packageUpdateVersionID, fromversion)
				VALUES		(?, ?)";
			$statement = WCF::getDB()->prepareStatement($sql);
			foreach ($fromversionInserts as $fromversion) {
				$statement->execute(array(
					$fromversion['packageUpdateVersionID'],
					$fromversion['fromversion']
				));
			}
		}
	}