|
TYPO3 API
SVNRelease
|
00001 <?php 00002 /*************************************************************** 00003 * Copyright notice 00004 * 00005 * (c) 2010 Marcus Krause <marcus#exp2010@t3sec.info> 00006 * Steffen Kamper <info@sk-typo3.de> 00007 * All rights reserved 00008 * 00009 * This script is part of the TYPO3 project. The TYPO3 project is 00010 * free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. 00014 * 00015 * The GNU General Public License can be found at 00016 * http://www.gnu.org/copyleft/gpl.html. 00017 * 00018 * This script is distributed in the hope that it will be useful, 00019 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00020 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00021 * GNU General Public License for more details. 00022 * 00023 * This copyright notice MUST APPEAR in all copies of the script! 00024 ***************************************************************/ 00025 /** 00026 * class.tx_em_repository_utility.php 00027 * 00028 * Module: Extension manager - Central repository utility functions 00029 * 00030 * $Id: class.tx_em_repository_utility.php 2082 2010-03-21 17:19:42Z steffenk $ 00031 * 00032 * @author Marcus Krause <marcus#exp2010@t3sec.info> 00033 * @author Steffen Kamper <info@sk-typo3.de> 00034 */ 00035 00036 00037 /** 00038 * Central utility class for repository handling. 00039 * 00040 * @author Marcus Krause <marcus#exp2010@t3sec.info> 00041 * @author Steffen Kamper <info@sk-typo3.de> 00042 * 00043 * @since 2010-02-18 00044 * @package TYPO3 00045 * @subpackage EM 00046 */ 00047 class tx_em_Repository_Utility implements t3lib_Singleton { 00048 00049 00050 /** 00051 * ########################################## 00052 * Problem constants - to be used in bitmasks 00053 * ########################################## 00054 */ 00055 /** 00056 * Type of problem: extension file not existing in file system. 00057 * 00058 * @var integer 00059 */ 00060 const PROBLEM_EXTENSION_FILE_NOT_EXISTING = 1; 00061 00062 /** 00063 * Type of problem: wrong hash indicates outdated extension file. 00064 * 00065 * @var integer 00066 */ 00067 const PROBLEM_EXTENSION_HASH_CHANGED = 2; 00068 00069 /** 00070 * Type of problem: no version records in database. 00071 * 00072 * @var integer 00073 */ 00074 const PROBLEM_NO_VERSIONS_IN_DATABASE = 4; 00075 00076 00077 /** 00078 * Keeps instance of repository class. 00079 * 00080 * @var em_repository 00081 */ 00082 protected $repository = NULL; 00083 00084 00085 /** 00086 * Class constructor. 00087 * 00088 * @access public 00089 * @param object &$repository (optional) instance of {@link em_repository repository} class 00090 * @return void 00091 */ 00092 function __construct(&$repository = NULL) { 00093 if ($repository !== NULL && is_object($repository) 00094 && $repository instanceof tx_em_Repository) { 00095 $this->setRepository($repository); 00096 } 00097 } 00098 00099 /** 00100 * Method provides a wrapper for throwing an exception. 00101 * 00102 * @access protected 00103 * @see tx_em_ConnectionException 00104 * @param string $message the exception message to throw. 00105 * @param integer $code the exception code. 00106 * @return void 00107 */ 00108 protected function throwConnectionException($message = "", $code = 0) { 00109 throw new tx_em_ConnectionException(get_class($this) . ': ' . $message, $code); 00110 } 00111 00112 /** 00113 * Method registers required repository instance to work with. 00114 * 00115 * Repository instance is passed by reference. 00116 * 00117 * @access public 00118 * @param em_repository &$repository instance of {@link em_repository repository} class 00119 * @return void 00120 * @see $repository 00121 */ 00122 public function setRepository(tx_em_Repository &$repository) { 00123 $this->repository = $repository; 00124 } 00125 00126 /** 00127 * Method fetches extension list file from remote server. 00128 * 00129 * Delegates to {@link fetchFile()}. 00130 * 00131 * @access public 00132 * @return void 00133 * @see fetchFile() 00134 */ 00135 public function fetchExtListFile() { 00136 $this->fetchFile($this->getRemoteExtListFile(), $this->getLocalExtListFile()); 00137 } 00138 00139 /** 00140 * Method fetches mirror list file from remote server. 00141 * 00142 * Delegates to {@link fetchFile()}. 00143 * 00144 * @access public 00145 * @return void 00146 * @see fetchFile() 00147 */ 00148 public function fetchMirrorListFile() { 00149 $this->fetchFile($this->getRemoteMirrorListFile(), $this->getLocalMirrorListFile()); 00150 } 00151 00152 /** 00153 * Method fetches contents from remote server and 00154 * writes them into a file in the local file system. 00155 * 00156 * @access protected 00157 * @param string $remoteRessource remote ressource to read contents from 00158 * @param string $localRessource local ressource (absolute file path) to store retrieved contents to 00159 * @return void 00160 * @see t3lib_div::getURL(), t3lib_div::writeFile() 00161 * @throws tx_em_ConnectionException 00162 */ 00163 protected function fetchFile($remoteRessource, $localRessource) { 00164 if (is_string($remoteRessource) && is_string($localRessource) 00165 && !empty($remoteRessource) && !empty($localRessource)) { 00166 $fileContent = t3lib_div::getURL($remoteRessource, 0, array(TYPO3_user_agent)); 00167 if ($fileContent !== false) { 00168 t3lib_div::writeFile($localRessource, $fileContent) || $this->throwConnectionException(sprintf('Could not write to file %s.', htmlspecialchars($localRessource))); 00169 } else { 00170 $this->throwConnectionException(sprintf('Could not access remote ressource %s.', htmlspecialchars($remoteRessource))); 00171 } 00172 } 00173 } 00174 00175 /** 00176 * Method returns location of local extension list file. 00177 * 00178 * @access public 00179 * @return string local location of file 00180 * @see getRemoteExtListFile() 00181 */ 00182 public function getLocalExtListFile() { 00183 $absFilePath = PATH_site . 'typo3temp/' 00184 . intval($this->repository->getId()) 00185 . '.extensions.xml.gz'; 00186 return $absFilePath; 00187 } 00188 00189 /** 00190 * Method returns location of remote extension list file. 00191 * 00192 * @access public 00193 * @return string remote location of file 00194 * @see getLocalExtListFile() 00195 */ 00196 public function getRemoteExtListFile() { 00197 $mirror = $this->getMirrors(TRUE)->getMirror(); 00198 $filePath = 'http://' . $mirror['host'] . $mirror['path'] 00199 . 'extensions.xml.gz'; 00200 return $filePath; 00201 } 00202 00203 /** 00204 * Method returns location of remote file containing 00205 * the extension checksum hash. 00206 * 00207 * @access public 00208 * @return string remote location of file 00209 */ 00210 public function getRemoteExtHashFile() { 00211 $mirror = $this->getMirrors(TRUE)->getMirror(); 00212 $filePath = 'http://' . $mirror['host'] . $mirror['path'] 00213 . 'extensions.md5'; 00214 return $filePath; 00215 } 00216 00217 /** 00218 * Method returns location of local mirror list file. 00219 * 00220 * @access public 00221 * @return string local location of file 00222 * @see getRemoteMirrorListFile() 00223 */ 00224 public function getLocalMirrorListFile() { 00225 $absFilePath = PATH_site . 'typo3temp/' 00226 . intval($this->repository->getId()) 00227 . '.mirrors.xml.gz'; 00228 return $absFilePath; 00229 } 00230 00231 /** 00232 * Method returns location of remote mirror list file. 00233 * 00234 * @access public 00235 * @return string remote location of file 00236 * @see getLocalMirrorListFile() 00237 */ 00238 public function getRemoteMirrorListFile() { 00239 $filePath = $this->repository->getMirrorListUrl(); 00240 return $filePath; 00241 } 00242 00243 /** 00244 * Method returns available mirrors for registered repository. 00245 * 00246 * If there are no mirrors registered to the repository, 00247 * the method will retrieve them from file system or remote 00248 * server. 00249 * 00250 * @access public 00251 * @param boolean $forcedUpdateFromRemote if boolean true, mirror configuration will always retrieved from remote server 00252 * @return em_repository_mirrors instance of repository mirrors class 00253 */ 00254 public function getMirrors($forcedUpdateFromRemote = TRUE) { 00255 $assignedMirror = $this->repository->getMirrors(); 00256 if ($forcedUpdateFromRemote || is_null($assignedMirror) || !is_object($assignedMirror)) { 00257 if ($forcedUpdateFromRemote || !is_file($this->getLocalMirrorListFile())) { 00258 $this->fetchMirrorListFile(); 00259 } 00260 $objMirrorListImporter = t3lib_div::makeInstance('tx_em_Import_MirrorListImporter'); 00261 $this->repository->addMirrors($objMirrorListImporter->getMirrors($this->getLocalMirrorListFile())); 00262 } 00263 return $this->repository->getMirrors(); 00264 } 00265 00266 /** 00267 * Method returns information if currently available 00268 * extension list might be outdated. 00269 * 00270 * @access public 00271 * @see em_repository_utility::PROBLEM_NO_VERSIONS_IN_DATABASE, 00272 * em_repository_utility::PROBLEM_EXTENSION_FILE_NOT_EXISTING, 00273 * em_repository_utility::PROBLEM_EXTENSION_HASH_CHANGED 00274 * @return integer integer "0" if everything is perfect, otherwise bitmask with occured problems 00275 * @see updateExtList() 00276 */ 00277 public function isExtListUpdateNecessary() { 00278 $updateNecessity = 0; 00279 00280 if (tx_em_Database::getExtensionCountFromRepository($this->getRepositoryUID(TRUE)) <= 0) { 00281 $updateNecessity |= self::PROBLEM_NO_VERSIONS_IN_DATABASE; 00282 } 00283 00284 if (!is_file($this->getLocalExtListFile())) { 00285 $updateNecessity |= self::PROBLEM_EXTENSION_FILE_NOT_EXISTING; 00286 } else { 00287 $remotemd5 = t3lib_div::getURL($this->getRemoteExtHashFile(), 0, array(TYPO3_user_agent)); 00288 00289 if ($remotemd5 !== false) { 00290 $localmd5 = md5_file($this->getLocalExtListFile()); 00291 if ($remotemd5 !== $localmd5) { 00292 $updateNecessity |= self::PROBLEM_EXTENSION_HASH_CHANGED; 00293 } 00294 } else { 00295 $this->throwConnectionException('Could not retrieve extension hash file from remote server.'); 00296 } 00297 } 00298 return $updateNecessity; 00299 } 00300 00301 /** 00302 * Method returns UID of the current repository. 00303 * 00304 * @access public 00305 * @param boolean $insertIfMissing creates repository record in DB if set to TRUE 00306 * @return integer 00307 */ 00308 public function getRepositoryUID($insertIfMissing = FALSE) { 00309 $uid = $this->repository->getId(); 00310 $repository = tx_em_Database::getRepositoryByUID($uid); 00311 if (empty($repository) && $insertIfMissing) { 00312 $uid = tx_em_Database::insertRepository($this->repository); 00313 } else { 00314 $uid = intval($repository['uid']); 00315 } 00316 00317 return $uid; 00318 } 00319 00320 /** 00321 * Method updates TYPO3 database with up-to-date 00322 * extension version records. 00323 * 00324 * @access public 00325 * @param boolean $renderFlashMessage if method should return flashmessage or raw integer 00326 * @return mixed either sum of imported extensions or instance of t3lib_FlashMessage 00327 * @see isExtListUpdateNecessary() 00328 */ 00329 public function updateExtList($renderFlashMessage = FALSE) { 00330 00331 if ($renderFlashMessage) { 00332 /* @var $flashMessage t3lib_FlashMessage */ 00333 $flashMessage = t3lib_div::makeInstance('t3lib_FlashMessage', 00334 $GLOBALS['LANG']->getLL('ext_import_list_unchanged_header'), 00335 $GLOBALS['LANG']->getLL('ext_import_list_unchanged'), 00336 t3lib_FlashMessage::INFO 00337 ); 00338 } 00339 $sumRecords = 0; 00340 00341 $updateNecessity = $this->isExtListUpdateNecessary(); 00342 00343 if ($updateNecessity !== 0) { 00344 // retrieval of file necessary 00345 $tmpBitmask = (self::PROBLEM_EXTENSION_FILE_NOT_EXISTING | self::PROBLEM_EXTENSION_HASH_CHANGED); 00346 if (($tmpBitmask & $updateNecessity) > 0) { 00347 $this->fetchExtListFile(); 00348 $updateNecessity &= ~$tmpBitmask; 00349 } 00350 00351 // database table cleanup 00352 if (($updateNecessity & self::PROBLEM_NO_VERSIONS_IN_DATABASE)) { 00353 $updateNecessity &= ~self::PROBLEM_NO_VERSIONS_IN_DATABASE; 00354 } else { 00355 $GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_extensions', 'repository=' . $this->getRepositoryUID()); 00356 } 00357 00358 // no further problems - start of import process 00359 if ($updateNecessity === 0) { 00360 $uid = $this->getRepositoryUID(TRUE); 00361 /* @var $objExtListImporter tx_em_Import_ExtensionListImporter */ 00362 $objExtListImporter = t3lib_div::makeInstance('tx_em_Import_ExtensionListImporter'); 00363 $objExtListImporter->import($this->getLocalExtListFile(), $uid); 00364 $sumRecords = tx_em_Database::getExtensionCountFromRepository($uid); 00365 if ($renderFlashMessage) { 00366 $flashMessage->setTitle($GLOBALS['LANG']->getLL('ext_import_extlist_updated_header')); 00367 $flashMessage->setMessage(sprintf($GLOBALS['LANG']->getLL('ext_import_extlist_updated'), tx_em_Database::getExtensionCountFromRepository())); 00368 $flashMessage->setSeverity(t3lib_FlashMessage::OK); 00369 } 00370 } 00371 } 00372 return $renderFlashMessage ? $flashMessage : $sumRecords; 00373 } 00374 } 00375 00376 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['typo3/sysext/em/classes/repository/class.tx_em_repository_utility.php'])) { 00377 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['typo3/sysext/em/classes/repository/class.tx_em_repository_utility.php']); 00378 } 00379 00380 ?>
1.8.0