TYPO3 API  SVNRelease
class.tx_em_database.php
Go to the documentation of this file.
00001 <?php
00002 /***************************************************************
00003  *  Copyright notice
00004  *
00005  *  (c) 2010 Marcus Krause <marcus#exp2010@t3sec.info>
00006  *  (c) 2010 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_database.php
00027  *
00028  * Module: Extension manager - DB access
00029  *
00030  * $Id: class.tx_em_database.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  * DB access class for extension manager.
00038  *
00039  * Contains static methods for DB operations.
00040  *
00041  * @author    Marcus Krause <marcus#exp2010@t3sec.info>
00042  * @author    Steffen Kamper <info@sk-typo3.de>
00043  *
00044  * @since      2010-02-27
00045  * @package  TYPO3
00046  * @subpackage  EM
00047  */
00048 final class tx_em_Database {
00049 
00050     const MULTI_LINEBREAKS = "\n\n\n";
00051 
00052     const TABLE_REPOSITORY = 'sys_ter';
00053 
00054     const TABLE_EXTENSION = 'cache_extensions';
00055 
00056 
00057     /**
00058      * Get the count of extensions in cache_extensions from a repository.
00059      *
00060      * If $repository parameter is obmitted, sum of all extensions will be
00061      * returned.
00062      *
00063      * @access  public
00064      * @param   integer  $repository  (optional) repository uid of extensions to count
00065      * @return  integer  sum of extensions in database
00066      */
00067     public function getExtensionCountFromRepository($repository = NULL) {
00068         if (is_null($repository)) {
00069             return $GLOBALS['TYPO3_DB']->exec_SELECTcountRows(
00070                 'DISTINCT extkey',
00071                 self::TABLE_EXTENSION
00072             );
00073         } else {
00074             return $GLOBALS['TYPO3_DB']->exec_SELECTcountRows(
00075                 'DISTINCT extkey',
00076                 self::TABLE_EXTENSION,
00077                 'repository=' . intval($repository)
00078             );
00079         }
00080     }
00081 
00082     /**
00083      * Get extension list from cache_extensions
00084      *
00085      * @param int $repository
00086      * @param string $addFields
00087      * @param string $andWhere
00088      * @param string $order
00089      * @param string $limit
00090      * @return array
00091      */
00092     public function getExtensionListFromRepository($repository, $addFields = '', $andWhere = '', $order = '', $limit = '') {
00093         $ret = array();
00094         $temp = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
00095             'count(*) AS count',
00096             'cache_extensions',
00097             'repository=' . intval($repository) . $andWhere,
00098             'extkey'
00099         );
00100         $ret['count'] = count($temp);
00101 
00102         $ret['results'] = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
00103             'cache_extensions.*, count(*) AS versions, cache_extensions.intversion AS maxintversion' .
00104             ($addFields === '' ? '' : ',' . $addFields),
00105             'cache_extensions JOIN cache_extensions AS ce ON cache_extensions.extkey = ce.extkey',
00106             'cache_extensions.lastversion=1 AND cache_extensions.repository=' . intval($repository) . $andWhere,
00107             'ce.extkey',
00108             $order,
00109             $limit
00110         );
00111         //debug($GLOBALS['TYPO3_DB']->debug_lastBuiltQuery);
00112         return $ret;
00113     }
00114 
00115     /**
00116      * Get versions of extension
00117      *
00118      * @param int $repository
00119      * @param string $extKey
00120      * @return array $versions
00121      */
00122     public function getExtensionVersionsFromRepository($repository, $extKey) {
00123         $versions = array();
00124         //TODO: implement
00125         return $versions;
00126     }
00127 
00128     /**
00129      * Function inserts a repository object into database.
00130      *
00131      * @access  public
00132      * @param   tx_em_Repository $repository  repository object
00133      * @return  void
00134      */
00135     public function updateRepository(tx_em_Repository $repository) {
00136         $repositoryData = array(
00137             'title' => $repository->getTitle(),
00138             'description' => $repository->getDescription(),
00139             'wsdl_url' => $repository->getWsdlUrl(),
00140             'mirror_url' => $repository->getMirrorListUrl(),
00141             'lastUpdated' => $repository->getLastUpdate(),
00142             'extCount' => $repository->getExtensionCount(),
00143         );
00144         $GLOBALS['TYPO3_DB']->exec_UPDATEquery(
00145             self::TABLE_REPOSITORY,
00146             'uid=' . $repository->getId(),
00147             $repositoryData
00148         );
00149 
00150     }
00151 
00152 
00153     /**
00154      * Function inserts a repository object into database.
00155      *
00156      * @access  public
00157      * @param   tx_em_Repository $repository  repository object
00158      * @return  integer  UID of the newly inserted repository object
00159      */
00160     public function insertRepository(tx_em_Repository $repository) {
00161         $repositoryData = array(
00162             'title' => $repository->getTitle(),
00163             'description' => $repository->getDescription(),
00164             'wsdl_url' => $repository->getWsdlUrl(),
00165             'mirror_url' => $repository->getMirrorListUrl(),
00166             'lastUpdated' => $repository->getLastUpdate(),
00167             'extCount' => $repository->getExtensionCount(),
00168         );
00169         $GLOBALS['TYPO3_DB']->exec_INSERTquery(
00170             self::TABLE_REPOSITORY,
00171             $repositoryData
00172         );
00173         return $GLOBALS['TYPO3_DB']->sql_insert_id();
00174     }
00175 
00176     /**
00177      * Deletes given Repository
00178      *
00179      * @param  tx_em_Repository $repository  repository object
00180      * @return void
00181      */
00182     public function deleteRepository(tx_em_Repository $repository) {
00183         $GLOBALS['TYPO3_DB']->exec_DELETEquery(
00184              self::TABLE_REPOSITORY,
00185             'uid=' . $repository->getId()
00186          );
00187     }
00188 
00189     /**
00190      * Updates ExtCount and lastUpdated  in Repository eg after import
00191      * @param  int $extCount
00192      * @param int $uid
00193      * @return void
00194      */
00195     public function updateRepositoryCount($extCount, $uid = 1) {
00196         $GLOBALS['TYPO3_DB']->exec_UPDATEquery(
00197              self::TABLE_REPOSITORY,
00198              'uid=' . intval($uid),
00199              array (
00200                 'lastUpdated' => time(),
00201                 'extCount' => intval($extCount)
00202              ));
00203     }
00204 
00205     /**
00206      * Insert version
00207      *
00208      * @param  $arrFields
00209      * @return void
00210      */
00211     public function insertVersion(array $arrFields) {
00212         $GLOBALS['TYPO3_DB']->exec_INSERTquery(self::TABLE_EXTENSION, $arrFields);
00213     }
00214 
00215     /**
00216      * Update the lastversion field after update
00217      *
00218      * @param int $repositoryUid
00219      * @return void
00220      */
00221     public function insertLastVersion($repositoryUid = 1) {
00222         $groupedRows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
00223             'extkey, version, max(intversion) maxintversion',
00224             'cache_extensions',
00225             'repository=' . intval($repositoryUid),
00226             'extkey'
00227         );
00228         $extensions = count($groupedRows);
00229 
00230         if ($extensions > 0) {
00231             // set all to 0
00232             $GLOBALS['TYPO3_DB']->exec_UPDATEquery(
00233                 'cache_extensions',
00234                 'lastversion=1 AND repository=' . intval($repositoryUid),
00235                 array('lastversion' => 0)
00236             );
00237 
00238                 // Find latest version of extensions and set lastversion to 1 for these
00239             foreach ($groupedRows as $row) {
00240                 $GLOBALS['TYPO3_DB']->exec_UPDATEquery(
00241                     'cache_extensions',
00242                     'extkey="' . $row['extkey'] . '" AND intversion="' . $row['maxintversion'] . '" AND repository=' . intval($repositoryUid),
00243                     array('lastversion' => 1)
00244                 );
00245             }
00246         }
00247 
00248         return $extensions;
00249     }
00250 
00251 
00252     /**
00253      * Method finds and returns repository fields identified by its UID.
00254      *
00255      * @access  public
00256      * @param   int  $uid  repository UID
00257      */
00258     public function getRepositoryByUID($uid) {
00259         $row = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('*', self::TABLE_REPOSITORY, 'uid=' . intval($uid));
00260 
00261         return $row;
00262     }
00263 
00264     /**
00265      * Method finds and returns repository identified by its title
00266      *
00267      * @param  $title
00268      * @return
00269      */
00270     public function getRepositoryByTitle($title) {
00271         return $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
00272             '*',
00273             self::TABLE_REPOSITORY,
00274             'title=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($title,
00275             self::TABLE_REPOSITORY)
00276         );
00277     }
00278 
00279     /**
00280      * Get available repositories
00281      *
00282      * @param string $where
00283      * @return array
00284      */
00285     public function getRepositories($where = NULL) {
00286         return $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
00287             '*',
00288             self::TABLE_REPOSITORY,
00289             $where ? $where : ''
00290         );
00291     }
00292 
00293     /**
00294      * Dump table content
00295      * Is DBAL compliant, but the dump format is written as MySQL standard. If the INSERT statements should be imported in a DBMS using other quoting than MySQL they must first be translated. t3lib_sqlengine can parse these queries correctly and translate them somehow.
00296      *
00297      * @param   string      Table name
00298      * @param   array       Field structure
00299      * @return  string      SQL Content of dump (INSERT statements)
00300      */
00301     function dumpTableContent($table, $fieldStructure) {
00302 
00303         // Substitution of certain characters (borrowed from phpMySQL):
00304         $search = array('\\', '\'', "\x00", "\x0a", "\x0d", "\x1a");
00305         $replace = array('\\\\', '\\\'', '\0', '\n', '\r', '\Z');
00306 
00307         $lines = array();
00308 
00309         // Select all rows from the table:
00310         $result = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $table, '');
00311 
00312         // Traverse the selected rows and dump each row as a line in the file:
00313         while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) {
00314             $values = array();
00315             foreach ($fieldStructure as $field) {
00316                 $values[] = isset($row[$field]) ? "'" . str_replace($search, $replace, $row[$field]) . "'" : 'NULL';
00317             }
00318             $lines[] = 'INSERT INTO ' . $table . ' VALUES (' . implode(', ', $values) . ');';
00319         }
00320 
00321         // Free DB result:
00322         $GLOBALS['TYPO3_DB']->sql_free_result($result);
00323 
00324         // Implode lines and return:
00325         return implode(LF, $lines);
00326     }
00327 
00328     /**
00329      * Gets the table and field structure from database.
00330      * Which fields and which tables are determined from the ext_tables.sql file
00331      *
00332      * @param   string      Array with table.field values
00333      * @return  array       Array of tables and fields splitted.
00334      */
00335     function getTableAndFieldStructure($parts) {
00336         // Instance of install tool
00337         $instObj = new t3lib_install();
00338         $dbFields = $instObj->getFieldDefinitions_database(TYPO3_db);
00339 
00340         $outTables = array();
00341         foreach ($parts as $table) {
00342             $sub = explode('.', $table);
00343             if ($sub[0] && isset($dbFields[$sub[0]])) {
00344                 if ($sub[1]) {
00345                     $key = explode('KEY:', $sub[1], 2);
00346                     if (count($key) == 2 && !$key[0]) { // key:
00347                         if (isset($dbFields[$sub[0]]['keys'][$key[1]])) {
00348                             $outTables[$sub[0]]['keys'][$key[1]] = $dbFields[$sub[0]]['keys'][$key[1]];
00349                         }
00350                     } else {
00351                         if (isset($dbFields[$sub[0]]['fields'][$sub[1]])) {
00352                             $outTables[$sub[0]]['fields'][$sub[1]] = $dbFields[$sub[0]]['fields'][$sub[1]];
00353                         }
00354                     }
00355                 } else {
00356                     $outTables[$sub[0]] = $dbFields[$sub[0]];
00357                 }
00358             }
00359         }
00360 
00361         return $outTables;
00362     }
00363 
00364 
00365     /**
00366      * Makes a dump of the tables/fields definitions for an extension
00367      *
00368      * @param   array       Array with table => field/key definition arrays in
00369      * @return  string      SQL for the table definitions
00370      * @see dumpStaticTables()
00371      */
00372     function dumpTableAndFieldStructure($arr) {
00373         $tables = array();
00374 
00375         if (count($arr)) {
00376 
00377             // Get file header comment:
00378             $tables[] = self::dumpHeader();
00379 
00380             // Traverse tables, write each table/field definition:
00381             foreach ($arr as $table => $fieldKeyInfo) {
00382                 $tables[] = self::dumpTableHeader($table, $fieldKeyInfo);
00383             }
00384         }
00385 
00386         // Return result:
00387         return implode(LF . LF . LF, $tables);
00388     }
00389 
00390     /**
00391      * Link to dump of database tables
00392      *
00393      * @param   array  $tablesArray
00394      * @param   string $extKey
00395      * @param   array  $additionalLinkParameter
00396      * @return  string      HTML
00397      */
00398     function dumpDataTablesLine($tablesArray, $extKey, $additionalLinkParameter = array()) {
00399         $tables = array();
00400         $tablesNA = array();
00401         $allTables = array_keys($GLOBALS['TYPO3_DB']->admin_get_tables());
00402 
00403         foreach ($tablesArray as $tableName) {
00404             if (in_array($tableName, $allTables)) {
00405                 $count = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', $tableName);
00406                 $tables[$tableName] = '<tr><td>&nbsp;</td><td>
00407                     <a class="t3-link dumpLink" href="' .
00408                         htmlspecialchars(t3lib_div::linkThisScript(
00409                             array_merge(array(
00410                                 'CMD[dumpTables]' => $tableName,
00411                                 'CMD[showExt]' => $extKey,
00412                             ), $additionalLinkParameter)
00413                         )) .
00414                         '" title="' .
00415                         sprintf($GLOBALS['LANG']->sL('LLL:EXT:em/language/locallang.xml:extBackup_dump_table'),
00416                             $tableName) .
00417                         '">' . $tableName . '</a></td><td>&nbsp;&nbsp;&nbsp;</td><td>' .
00418                         sprintf($GLOBALS['LANG']->sL('LLL:EXT:em/language/locallang.xml:extBackup_number_of_records'),
00419                             $count) . '</td></tr>';
00420             } else {
00421                 $tablesNA[$tableName] = '<tr><td>&nbsp;</td><td>' . $tableName . '</td><td>&nbsp;</td><td>' .
00422                         $GLOBALS['LANG']->sL('LLL:EXT:em/language/locallang.xml:extBackup_table_not_there') . '</td></tr>';
00423             }
00424         }
00425         $label = '<table border="0" cellpadding="0" cellspacing="0">' .
00426                 implode('', array_merge($tables, $tablesNA)) .
00427                 '</table>';
00428         if (count($tables)) {
00429             $label = '<a class="t3-link dumpLink" href="' .
00430                     htmlspecialchars(t3lib_div::linkThisScript(
00431                         array_merge(array(
00432                             'CMD[dumpTables]' => implode(',', array_keys($tables)),
00433                             'CMD[showExt]' => $extKey
00434                         ), $additionalLinkParameter)
00435                     )) .
00436                     '" title="' . $GLOBALS['LANG']->sL('LLL:EXT:em/language/locallang.xml:extBackup_dump_all_tables') . '">' .
00437                     $GLOBALS['LANG']->sL('LLL:EXT:em/language/locallang.xml:extBackup_download_all_data') . '</a><br /><br />' . $label;
00438         }
00439         else {
00440             $label = $GLOBALS['LANG']->sL('LLL:EXT:em/language/locallang.xml:extBackup_nothing_to_dump') . '<br /><br />' . $label;
00441         }
00442         return $label;
00443     }
00444 
00445     /**
00446      * Dump content for static tables
00447      *
00448      * @param   string      Comma list of tables from which to dump content
00449      * @return  string      Returns the content
00450      * @see dumpTableAndFieldStructure()
00451      */
00452     function dumpStaticTables($tableList) {
00453         $instObj = t3lib_div::makeInstance('t3lib_install');
00454         $dbFields = $instObj->getFieldDefinitions_database(TYPO3_db);
00455 
00456         $out = '';
00457         $parts = t3lib_div::trimExplode(',', $tableList, TRUE);
00458 
00459         // Traverse the table list and dump each:
00460         foreach ($parts as $table) {
00461             if (is_array($dbFields[$table]['fields'])) {
00462                 $header = self::dumpHeader();
00463                 $tableHeader = self::dumpTableHeader($table, $dbFields[$table], TRUE);
00464                 $insertStatements = self::dumpTableContent($table, $dbFields[$table]['fields']);
00465                 $out .= $header . self::MULTI_LINEBREAKS .
00466                         $tableHeader . self::MULTI_LINEBREAKS .
00467                         $insertStatements . self::MULTI_LINEBREAKS;
00468             } else {
00469                 throw new RuntimeException(
00470                     'TYPO3 Fatal Error: ' . $GLOBALS['LANG']->getLL('dumpStaticTables_table_not_found'),
00471                     1270853983
00472                 );
00473             }
00474         }
00475         unset($instObj);
00476         return $out;
00477     }
00478 
00479     /**
00480      * Header comments of the SQL dump file
00481      *
00482      * @return  string      Table header
00483      */
00484     function dumpHeader() {
00485         return trim('
00486 # TYPO3 Extension Manager dump 1.1
00487 #
00488 # Host: ' . TYPO3_db_host . '    Database: ' . TYPO3_db . '
00489 #--------------------------------------------------------
00490 ');
00491     }
00492 
00493     /**
00494      * Dump CREATE TABLE definition
00495      *
00496      * @param   string      Table name
00497      * @param   array       Field and key information (as provided from Install Tool class!)
00498      * @param   boolean     If true, add "DROP TABLE IF EXISTS"
00499      * @return  string      Table definition SQL
00500      */
00501     function dumpTableHeader($table, $fieldKeyInfo, $dropTableIfExists = 0) {
00502         $lines = array();
00503         $dump = '';
00504 
00505         // Create field definitions
00506         if (is_array($fieldKeyInfo['fields'])) {
00507             foreach ($fieldKeyInfo['fields'] as $fieldN => $data) {
00508                 $lines[] = '  ' . $fieldN . ' ' . $data;
00509             }
00510         }
00511 
00512         // Create index key definitions
00513         if (is_array($fieldKeyInfo['keys'])) {
00514             foreach ($fieldKeyInfo['keys'] as $fieldN => $data) {
00515                 $lines[] = '  ' . $data;
00516             }
00517         }
00518 
00519         // Compile final output:
00520         if (count($lines)) {
00521             $dump = trim('
00522 #
00523 # Table structure for table "' . $table . '"
00524 #
00525 ' . ($dropTableIfExists ? 'DROP TABLE IF EXISTS ' . $table . ';
00526 ' : '') . 'CREATE TABLE ' . $table . ' (
00527 ' . implode(',' . LF, $lines) . '
00528 );');
00529         }
00530 
00531         return $dump;
00532     }
00533 
00534 }
00535 
00536 ?>