|
TYPO3 API
SVNRelease
|
00001 <?php 00002 /*************************************************************** 00003 * Copyright notice 00004 * 00005 * (c) 2009 Jochen Rau <jochen.rau@typoplanet.de> 00006 * All rights reserved 00007 * 00008 * This class is a backport of the corresponding class of FLOW3. 00009 * All credits go to the v5 team. 00010 * 00011 * This script is part of the TYPO3 project. The TYPO3 project is 00012 * free software; you can redistribute it and/or modify 00013 * it under the terms of the GNU General Public License as published by 00014 * the Free Software Foundation; either version 2 of the License, or 00015 * (at your option) any later version. 00016 * 00017 * The GNU General Public License can be found at 00018 * http://www.gnu.org/copyleft/gpl.html. 00019 * 00020 * This script is distributed in the hope that it will be useful, 00021 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00023 * GNU General Public License for more details. 00024 * 00025 * This copyright notice MUST APPEAR in all copies of the script! 00026 ***************************************************************/ 00027 00028 /** 00029 * A Storage backend 00030 * 00031 * @package Extbase 00032 * @subpackage Persistence\Storage 00033 * @version $Id: Typo3DbBackend.php 2297 2010-05-25 15:52:18Z jocrau $ 00034 */ 00035 class Tx_Extbase_Persistence_Storage_Typo3DbBackend implements Tx_Extbase_Persistence_Storage_BackendInterface, t3lib_Singleton { 00036 00037 const OPERATOR_EQUAL_TO_NULL = 'operatorEqualToNull'; 00038 const OPERATOR_NOT_EQUAL_TO_NULL = 'operatorNotEqualToNull'; 00039 00040 /** 00041 * The TYPO3 database object 00042 * 00043 * @var t3lib_db 00044 */ 00045 protected $databaseHandle; 00046 00047 /** 00048 * @var Tx_Extbase_Persistence_DataMapper 00049 */ 00050 protected $dataMapper; 00051 00052 /** 00053 * The TYPO3 page select object. Used for language and workspace overlay 00054 * 00055 * @var t3lib_pageSelect 00056 */ 00057 protected $pageSelectObject; 00058 00059 /** 00060 * A first-level TypoScript configuration cache 00061 * 00062 * @var array 00063 */ 00064 protected $pageTSConfigCache = array(); 00065 00066 /** 00067 * Caches information about tables (esp. the existing column names) 00068 * 00069 * @var array 00070 */ 00071 protected $tableInformationCache = array(); 00072 00073 /** 00074 * @var Tx_Extbase_Configuration_ConfigurationManagerInterface 00075 */ 00076 protected $configurationManager; 00077 00078 /** 00079 * Constructor. takes the database handle from $GLOBALS['TYPO3_DB'] 00080 */ 00081 public function __construct() { 00082 $this->databaseHandle = $GLOBALS['TYPO3_DB']; 00083 } 00084 00085 /** 00086 * @param Tx_Extbase_Configuration_ConfigurationManagerInterface $configurationManager 00087 * @return void 00088 */ 00089 public function injectConfigurationManager(Tx_Extbase_Configuration_ConfigurationManagerInterface $configurationManager) { 00090 $this->configurationManager = $configurationManager; 00091 } 00092 00093 /** 00094 * Injects the DataMapper to map nodes to objects 00095 * 00096 * @param Tx_Extbase_Persistence_Mapper_DataMapper $dataMapper 00097 * @return void 00098 */ 00099 public function injectDataMapper(Tx_Extbase_Persistence_Mapper_DataMapper $dataMapper) { 00100 $this->dataMapper = $dataMapper; 00101 } 00102 00103 /** 00104 * Adds a row to the storage 00105 * 00106 * @param string $tableName The database table name 00107 * @param array $row The row to be inserted 00108 * @param boolean $isRelation TRUE if we are currently inserting into a relation table, FALSE by default 00109 * @return int The uid of the inserted row 00110 */ 00111 public function addRow($tableName, array $row, $isRelation = FALSE) { 00112 $fields = array(); 00113 $values = array(); 00114 $parameters = array(); 00115 if (isset($row['uid'])) { 00116 unset($row['uid']); 00117 } 00118 foreach ($row as $columnName => $value) { 00119 $fields[] = $columnName; 00120 $values[] = '?'; 00121 $parameters[] = $value; 00122 } 00123 00124 $sqlString = 'INSERT INTO ' . $tableName . ' (' . implode(', ', $fields) . ') VALUES (' . implode(', ', $values) . ')'; 00125 $this->replacePlaceholders($sqlString, $parameters); 00126 // debug($sqlString,-2); 00127 $this->databaseHandle->sql_query($sqlString); 00128 $this->checkSqlErrors($sqlString); 00129 $uid = $this->databaseHandle->sql_insert_id(); 00130 if (!$isRelation) { 00131 $this->clearPageCache($tableName, $uid); 00132 } 00133 return (int)$uid; 00134 } 00135 00136 /** 00137 * Updates a row in the storage 00138 * 00139 * @param string $tableName The database table name 00140 * @param array $row The row to be updated 00141 * @param boolean $isRelation TRUE if we are currently inserting into a relation table, FALSE by default 00142 * @return void 00143 */ 00144 public function updateRow($tableName, array $row, $isRelation = FALSE) { 00145 if (!isset($row['uid'])) throw new InvalidArgumentException('The given row must contain a value for "uid".'); 00146 $uid = (int)$row['uid']; 00147 unset($row['uid']); 00148 $fields = array(); 00149 $parameters = array(); 00150 foreach ($row as $columnName => $value) { 00151 $fields[] = $columnName . '=?'; 00152 $parameters[] = $value; 00153 } 00154 $parameters[] = $uid; 00155 00156 $sqlString = 'UPDATE ' . $tableName . ' SET ' . implode(', ', $fields) . ' WHERE uid=?'; 00157 $this->replacePlaceholders($sqlString, $parameters); 00158 // debug($sqlString,-2); 00159 $returnValue = $this->databaseHandle->sql_query($sqlString); 00160 $this->checkSqlErrors($sqlString); 00161 if (!$isRelation) { 00162 $this->clearPageCache($tableName, $uid); 00163 } 00164 return $returnValue; 00165 } 00166 00167 /** 00168 * Deletes a row in the storage 00169 * 00170 * @param string $tableName The database table name 00171 * @param array $identifier An array of identifier array('fieldname' => value). This array will be transformed to a WHERE clause 00172 * @param boolean $isRelation TRUE if we are currently manipulating a relation table, FALSE by default 00173 * @return void 00174 */ 00175 public function removeRow($tableName, array $identifier, $isRelation = FALSE) { 00176 $statement = 'DELETE FROM ' . $tableName . ' WHERE ' . $this->parseIdentifier($identifier); 00177 $this->replacePlaceholders($statement, $identifier); 00178 if (!$isRelation && isset($identifier['uid'])) { 00179 $this->clearPageCache($tableName, $identifier['uid'], $isRelation); 00180 } 00181 // debug($statement, -2); 00182 $returnValue = $this->databaseHandle->sql_query($statement); 00183 $this->checkSqlErrors($statement); 00184 return $returnValue; 00185 } 00186 00187 /** 00188 * Fetches row data from the database 00189 * 00190 * @param string $identifier The Identifier of the row to fetch 00191 * @param Tx_Extbase_Persistence_Mapper_DataMap $dataMap The Data Map 00192 * @return array|FALSE 00193 */ 00194 public function getRowByIdentifier($tableName, array $identifier) { 00195 $statement = 'SELECT * FROM ' . $tableName . ' WHERE ' . $this->parseIdentifier($identifier); 00196 $this->replacePlaceholders($statement, $identifier); 00197 // debug($statement,-2); 00198 $res = $this->databaseHandle->sql_query($statement); 00199 $this->checkSqlErrors($statement); 00200 $row = $this->databaseHandle->sql_fetch_assoc($res); 00201 if ($row !== FALSE) { 00202 return $row; 00203 } else { 00204 return FALSE; 00205 } 00206 } 00207 00208 protected function parseIdentifier(array $identifier) { 00209 $fieldNames = array_keys($identifier); 00210 $suffixedFieldNames = array(); 00211 foreach ($fieldNames as $fieldName) { 00212 $suffixedFieldNames[] = $fieldName . '=?'; 00213 } 00214 return implode(' AND ', $suffixedFieldNames); 00215 } 00216 00217 /** 00218 * Returns the object data matching the $query. 00219 * 00220 * @param Tx_Extbase_Persistence_QueryInterface $query 00221 * @return array 00222 * @author Karsten Dambekalns <karsten@typo3.org> 00223 */ 00224 public function getObjectDataByQuery(Tx_Extbase_Persistence_QueryInterface $query) { 00225 $parameters = array(); 00226 00227 $statement = $query->getStatement(); 00228 if($statement instanceof Tx_Extbase_Persistence_QOM_Statement) { 00229 $sql = $statement->getStatement(); 00230 $parameters = $statement->getBoundVariables(); 00231 } else { 00232 $parameters = array(); 00233 $statementParts = $this->parseQuery($query, $parameters); 00234 $sql = $this->buildQuery($statementParts, $parameters); 00235 } 00236 $this->replacePlaceholders($sql, $parameters); 00237 // debug($sql,-2); 00238 $result = $this->databaseHandle->sql_query($sql); 00239 $this->checkSqlErrors($sql); 00240 $rows = $this->getRowsFromResult($query->getSource(), $result); 00241 $this->databaseHandle->sql_free_result($result); 00242 $rows = $this->doLanguageAndWorkspaceOverlay($query->getSource(), $rows); 00243 // TODO: implement $objectData = $this->processObjectRecords($statementHandle); 00244 return $rows; 00245 } 00246 00247 /** 00248 * Returns the number of tuples matching the query. 00249 * 00250 * @param Tx_Extbase_Persistence_QOM_QueryObjectModelInterface $query 00251 * @return integer The number of matching tuples 00252 */ 00253 public function getObjectCountByQuery(Tx_Extbase_Persistence_QueryInterface $query) { 00254 $constraint = $query->getConstraint(); 00255 if($constraint instanceof Tx_Extbase_Persistence_QOM_StatementInterface) { 00256 throw new Tx_Extbase_Persistence_Storage_Exception_BadConstraint('Could not execute count on queries with a constraint of type Tx_Extbase_Persistence_QOM_StatementInterface', 1256661045); 00257 } 00258 $parameters = array(); 00259 $statementParts = $this->parseQuery($query, $parameters); 00260 // if limit is set, we need to count the rows "manually" as COUNT(*) ignores LIMIT constraints 00261 if (!empty($statementParts['limit'])) { 00262 $statement = $this->buildQuery($statementParts, $parameters); 00263 $this->replacePlaceholders($statement, $parameters); 00264 $result = $this->databaseHandle->sql_query($statement); 00265 $this->checkSqlErrors($statement); 00266 $count = $this->databaseHandle->sql_num_rows($result); 00267 } else { 00268 $statementParts['fields'] = array('COUNT(*)'); 00269 $statement = $this->buildQuery($statementParts, $parameters); 00270 $this->replacePlaceholders($statement, $parameters); 00271 $result = $this->databaseHandle->sql_query($statement); 00272 $this->checkSqlErrors($statement); 00273 $rows = $this->getRowsFromResult($query->getSource(), $result); 00274 $count = current(current($rows)); 00275 } 00276 $this->databaseHandle->sql_free_result($result); 00277 return $count; 00278 } 00279 00280 /** 00281 * Parses the query and returns the SQL statement parts. 00282 * 00283 * @param Tx_Extbase_Persistence_QueryInterface $query The query 00284 * @return array The SQL statement parts 00285 */ 00286 public function parseQuery(Tx_Extbase_Persistence_QueryInterface $query, array &$parameters) { 00287 $sql = array(); 00288 $sql['keywords'] = array(); 00289 $sql['tables'] = array(); 00290 $sql['unions'] = array(); 00291 $sql['fields'] = array(); 00292 $sql['where'] = array(); 00293 $sql['additionalWhereClause'] = array(); 00294 $sql['orderings'] = array(); 00295 $sql['limit'] = array(); 00296 00297 $source = $query->getSource(); 00298 00299 $this->parseSource($source, $sql, $parameters); 00300 $this->parseConstraint($query->getConstraint(), $source, $sql, $parameters); 00301 $this->parseOrderings($query->getOrderings(), $source, $sql); 00302 $this->parseLimitAndOffset($query->getLimit(), $query->getOffset(), $sql); 00303 00304 $tableNames = array_unique(array_keys($sql['tables'] + $sql['unions'])); 00305 foreach ($tableNames as $tableName) { 00306 if (is_string($tableName) && strlen($tableName) > 0) { 00307 $this->addAdditionalWhereClause($query->getQuerySettings(), $tableName, $sql); 00308 } 00309 } 00310 00311 return $sql; 00312 } 00313 00314 /** 00315 * Returns the statement, ready to be executed. 00316 * 00317 * @param array $sql The SQL statement parts 00318 * @return string The SQL statement 00319 */ 00320 public function buildQuery(array $sql) { 00321 $statement = 'SELECT ' . implode(' ', $sql['keywords']) . ' '. implode(',', $sql['fields']) . ' FROM ' . implode(' ', $sql['tables']) . ' '. implode(' ', $sql['unions']); 00322 if (!empty($sql['where'])) { 00323 $statement .= ' WHERE ' . implode('', $sql['where']); 00324 if (!empty($sql['additionalWhereClause'])) { 00325 $statement .= ' AND ' . implode(' AND ', $sql['additionalWhereClause']); 00326 } 00327 } elseif (!empty($sql['additionalWhereClause'])) { 00328 $statement .= ' WHERE ' . implode(' AND ', $sql['additionalWhereClause']); 00329 } 00330 if (!empty($sql['orderings'])) { 00331 $statement .= ' ORDER BY ' . implode(', ', $sql['orderings']); 00332 } 00333 if (!empty($sql['limit'])) { 00334 $statement .= ' LIMIT ' . $sql['limit']; 00335 } 00336 return $statement; 00337 } 00338 00339 /** 00340 * Checks if a Value Object equal to the given Object exists in the data base 00341 * 00342 * @param Tx_Extbase_DomainObject_AbstractValueObject $object The Value Object 00343 * @return array The matching uid 00344 */ 00345 public function getUidOfAlreadyPersistedValueObject(Tx_Extbase_DomainObject_AbstractValueObject $object) { 00346 $fields = array(); 00347 $parameters = array(); 00348 $dataMap = $this->dataMapper->getDataMap(get_class($object)); 00349 $properties = $object->_getProperties(); 00350 foreach ($properties as $propertyName => $propertyValue) { 00351 // FIXME We couple the Backend to the Entity implementation (uid, isClone); changes there breaks this method 00352 if ($dataMap->isPersistableProperty($propertyName) && ($propertyName !== 'uid') && ($propertyName !== 'pid') && ($propertyName !== 'isClone')) { 00353 if ($propertyValue === NULL) { 00354 $fields[] = $dataMap->getColumnMap($propertyName)->getColumnName() . ' IS NULL'; 00355 } else { 00356 $fields[] = $dataMap->getColumnMap($propertyName)->getColumnName() . '=?'; 00357 $parameters[] = $this->getPlainValue($propertyValue); 00358 } 00359 } 00360 } 00361 $sql = array(); 00362 $sql['additionalWhereClause'] = array(); 00363 00364 $tableName = $dataMap->getTableName(); 00365 $this->addEnableFieldsStatement($tableName, $sql); 00366 00367 $statement = 'SELECT * FROM ' . $tableName; 00368 $statement .= ' WHERE ' . implode(' AND ', $fields); 00369 if (!empty($sql['additionalWhereClause'])) { 00370 $statement .= ' AND ' . implode(' AND ', $sql['additionalWhereClause']); 00371 } 00372 $this->replacePlaceholders($statement, $parameters); 00373 // debug($statement,-2); 00374 $res = $this->databaseHandle->sql_query($statement); 00375 $this->checkSqlErrors($statement); 00376 $row = $this->databaseHandle->sql_fetch_assoc($res); 00377 if ($row !== FALSE) { 00378 return (int)$row['uid']; 00379 } else { 00380 return FALSE; 00381 } 00382 } 00383 00384 /** 00385 * Transforms a Query Source into SQL and parameter arrays 00386 * 00387 * @param Tx_Extbase_Persistence_QOM_SourceInterface $source The source 00388 * @param array &$sql 00389 * @param array &$parameters 00390 * @return void 00391 */ 00392 protected function parseSource(Tx_Extbase_Persistence_QOM_SourceInterface $source, array &$sql) { 00393 if ($source instanceof Tx_Extbase_Persistence_QOM_SelectorInterface) { 00394 $className = $source->getNodeTypeName(); 00395 $tableName = $this->dataMapper->getDataMap($className)->getTableName(); 00396 $this->addRecordTypeConstraint($className, $sql); 00397 $sql['fields'][$tableName] = $tableName . '.*'; 00398 $sql['tables'][$tableName] = $tableName; 00399 } elseif ($source instanceof Tx_Extbase_Persistence_QOM_JoinInterface) { 00400 $this->parseJoin($source, $sql); 00401 } 00402 } 00403 00404 /** 00405 * Adda a constrint to ensure that the record type of the returned tuples is matching the data type of the repository. 00406 * 00407 * @param string $className The class name 00408 * @param array &$sql The query parts 00409 * @return void 00410 */ 00411 protected function addRecordTypeConstraint($className, &$sql) { 00412 if ($className !== NULL) { 00413 $dataMap = $this->dataMapper->getDataMap($className); 00414 if ($dataMap->getRecordTypeColumnName() !== NULL) { 00415 $recordTypes = array(); 00416 if ($dataMap->getRecordType() !== NULL) { 00417 $recordTypes[] = $dataMap->getRecordType(); 00418 } 00419 foreach ($dataMap->getSubclasses() as $subclassName) { 00420 $subclassDataMap = $this->dataMapper->getDataMap($subclassName); 00421 if ($subclassDataMap->getRecordType() !== NULL) { 00422 $recordTypes[] = $subclassDataMap->getRecordType(); 00423 } 00424 } 00425 if (count($recordTypes) > 0) { 00426 $recordTypeStatements = array(); 00427 foreach ($recordTypes as $recordType) { 00428 $recordTypeStatements[] = $dataMap->getTableName() . '.' . $dataMap->getRecordTypeColumnName() . '=' . $this->databaseHandle->fullQuoteStr($recordType, 'foo'); 00429 } 00430 $sql['additionalWhereClause'][] = '(' . implode(' OR ', $recordTypeStatements) . ')'; 00431 } 00432 } 00433 } 00434 } 00435 00436 /** 00437 * Transforms a Join into SQL and parameter arrays 00438 * 00439 * @param Tx_Extbase_Persistence_QOM_JoinInterface $join The join 00440 * @param array &$sql The query parts 00441 * @return void 00442 */ 00443 protected function parseJoin(Tx_Extbase_Persistence_QOM_JoinInterface $join, array &$sql) { 00444 $leftSource = $join->getLeft(); 00445 $leftClassName = $leftSource->getNodeTypeName(); 00446 $this->addRecordTypeConstraint($leftClassName, $sql); 00447 $leftTableName = $leftSource->getSelectorName(); 00448 // $sql['fields'][$leftTableName] = $leftTableName . '.*'; 00449 $rightSource = $join->getRight(); 00450 if ($rightSource instanceof Tx_Extbase_Persistence_QOM_JoinInterface) { 00451 $rightClassName = $rightSource->getLeft()->getNodeTypeName(); 00452 $rightTableName = $rightSource->getLeft()->getSelectorName(); 00453 } else { 00454 $rightClassName = $rightSource->getNodeTypeName(); 00455 $rightTableName = $rightSource->getSelectorName(); 00456 $sql['fields'][$leftTableName] = $rightTableName . '.*'; 00457 } 00458 $this->addRecordTypeConstraint($rightClassName, $sql); 00459 00460 $sql['tables'][$leftTableName] = $leftTableName; 00461 $sql['unions'][$rightTableName] = 'LEFT JOIN ' . $rightTableName; 00462 00463 $joinCondition = $join->getJoinCondition(); 00464 if ($joinCondition instanceof Tx_Extbase_Persistence_QOM_EquiJoinCondition) { 00465 $column1Name = $this->dataMapper->convertPropertyNameToColumnName($joinCondition->getProperty1Name(), $leftClassName); 00466 $column2Name = $this->dataMapper->convertPropertyNameToColumnName($joinCondition->getProperty2Name(), $rightClassName); 00467 $sql['unions'][$rightTableName] .= ' ON ' . $joinCondition->getSelector1Name() . '.' . $column1Name . ' = ' . $joinCondition->getSelector2Name() . '.' . $column2Name; 00468 } 00469 if ($rightSource instanceof Tx_Extbase_Persistence_QOM_JoinInterface) { 00470 $this->parseJoin($rightSource, $sql); 00471 } 00472 } 00473 00474 /** 00475 * Transforms a constraint into SQL and parameter arrays 00476 * 00477 * @param Tx_Extbase_Persistence_QOM_ConstraintInterface $constraint The constraint 00478 * @param Tx_Extbase_Persistence_QOM_SourceInterface $source The source 00479 * @param array &$sql The query parts 00480 * @param array &$parameters The parameters that will replace the markers 00481 * @param array $boundVariableValues The bound variables in the query (key) and their values (value) 00482 * @return void 00483 */ 00484 protected function parseConstraint(Tx_Extbase_Persistence_QOM_ConstraintInterface $constraint = NULL, Tx_Extbase_Persistence_QOM_SourceInterface $source, array &$sql, array &$parameters) { 00485 if ($constraint instanceof Tx_Extbase_Persistence_QOM_AndInterface) { 00486 $sql['where'][] = '('; 00487 $this->parseConstraint($constraint->getConstraint1(), $source, $sql, $parameters); 00488 $sql['where'][] = ' AND '; 00489 $this->parseConstraint($constraint->getConstraint2(), $source, $sql, $parameters); 00490 $sql['where'][] = ')'; 00491 } elseif ($constraint instanceof Tx_Extbase_Persistence_QOM_OrInterface) { 00492 $sql['where'][] = '('; 00493 $this->parseConstraint($constraint->getConstraint1(), $source, $sql, $parameters); 00494 $sql['where'][] = ' OR '; 00495 $this->parseConstraint($constraint->getConstraint2(), $source, $sql, $parameters); 00496 $sql['where'][] = ')'; 00497 } elseif ($constraint instanceof Tx_Extbase_Persistence_QOM_NotInterface) { 00498 $sql['where'][] = 'NOT ('; 00499 $this->parseConstraint($constraint->getConstraint(), $source, $sql, $parameters); 00500 $sql['where'][] = ')'; 00501 } elseif ($constraint instanceof Tx_Extbase_Persistence_QOM_ComparisonInterface) { 00502 $this->parseComparison($constraint, $source, $sql, $parameters); 00503 } 00504 } 00505 00506 /** 00507 * Parse a Comparison into SQL and parameter arrays. 00508 * 00509 * @param Tx_Extbase_Persistence_QOM_ComparisonInterface $comparison The comparison to parse 00510 * @param Tx_Extbase_Persistence_QOM_SourceInterface $source The source 00511 * @param array &$sql SQL query parts to add to 00512 * @param array &$parameters Parameters to bind to the SQL 00513 * @param array $boundVariableValues The bound variables in the query and their values 00514 * @return void 00515 */ 00516 protected function parseComparison(Tx_Extbase_Persistence_QOM_ComparisonInterface $comparison, Tx_Extbase_Persistence_QOM_SourceInterface $source, array &$sql, array &$parameters) { 00517 $operand1 = $comparison->getOperand1(); 00518 $operator = $comparison->getOperator(); 00519 $operand2 = $comparison->getOperand2(); 00520 if (($operator === Tx_Extbase_Persistence_QueryInterface::OPERATOR_EQUAL_TO) && (is_array($operand2) || ($operand2 instanceof ArrayAccess) || ($operand2 instanceof Traversable))) { 00521 // this else branch enables equals() to behave like in(). This behavior is deprecated and will be removed in future. Use in() instead. 00522 $operator = Tx_Extbase_Persistence_QueryInterface::OPERATOR_IN; 00523 } 00524 00525 if ($operator === Tx_Extbase_Persistence_QueryInterface::OPERATOR_IN) { 00526 $items = array(); 00527 $hasValue = FALSE; 00528 foreach ($operand2 as $value) { 00529 $value = $this->getPlainValue($value); 00530 if ($value !== NULL) { 00531 $items[] = $value; 00532 $hasValue = TRUE; 00533 } 00534 } 00535 if ($hasValue === FALSE) { 00536 $sql['where'][] = '1<>1'; 00537 } else { 00538 $this->parseDynamicOperand($operand1, $operator, $source, $sql, $parameters, NULL, $operand2); 00539 $parameters[] = $items; 00540 } 00541 } elseif ($operator === Tx_Extbase_Persistence_QueryInterface::OPERATOR_CONTAINS) { 00542 if ($operand2 === NULL) { 00543 $sql['where'][] = '1<>1'; 00544 } else { 00545 $className = $source->getNodeTypeName(); 00546 $tableName = $this->dataMapper->convertClassNameToTableName($className); 00547 $propertyName = $operand1->getPropertyName(); 00548 while (strpos($propertyName, '.') !== FALSE) { 00549 $this->addUnionStatement($className, $tableName, $propertyName, $sql); 00550 } 00551 $columnName = $this->dataMapper->convertPropertyNameToColumnName($propertyName, $className); 00552 $dataMap = $this->dataMapper->getDataMap($className); 00553 $columnMap = $dataMap->getColumnMap($propertyName); 00554 $typeOfRelation = $columnMap->getTypeOfRelation(); 00555 if ($typeOfRelation === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) { 00556 $relationTableName = $columnMap->getRelationTableName(); 00557 $sql['where'][] = $tableName . '.uid IN (SELECT ' . $columnMap->getParentKeyFieldName() . ' FROM ' . $relationTableName . ' WHERE ' . $columnMap->getChildKeyFieldName() . '=' . $this->getPlainValue($operand2) . ')'; 00558 } elseif ($typeOfRelation === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_MANY) { 00559 $parentKeyFieldName = $columnMap->getParentKeyFieldName(); 00560 if (isset($parentKeyFieldName)) { 00561 $childTableName = $columnMap->getChildTableName(); 00562 $sql['where'][] = $tableName . '.uid=(SELECT ' . $childTableName . '.' . $parentKeyFieldName . ' FROM ' . $childTableName . ' WHERE ' . $childTableName . '.uid=' . $this->getPlainValue($operand2) . ')'; 00563 } else { 00564 $statement = 'FIND_IN_SET(' . $this->getPlainValue($operand2) . ',' . $tableName . '.' . $columnName . ')'; 00565 $sql['where'][] = $statement; 00566 } 00567 } else { 00568 throw new Tx_Extbase_Persistence_Exception_RepositoryException('Unsupported relation for contains().', 1267832524); 00569 } 00570 } 00571 } else { 00572 if ($operand2 === NULL) { 00573 if ($operator === Tx_Extbase_Persistence_QueryInterface::OPERATOR_EQUAL_TO) { 00574 $operator = self::OPERATOR_EQUAL_TO_NULL; 00575 } elseif ($operator === Tx_Extbase_Persistence_QueryInterface::OPERATOR_NOT_EQUAL_TO) { 00576 $operator = self::OPERATOR_NOT_EQUAL_TO_NULL; 00577 } 00578 } 00579 $this->parseDynamicOperand($operand1, $operator, $source, $sql, $parameters); 00580 $parameters[] = $this->getPlainValue($operand2); 00581 } 00582 } 00583 00584 /** 00585 * Returns a plain value, i.e. objects are flattened out if possible. 00586 * 00587 * @param mixed $input 00588 * @return mixed 00589 */ 00590 protected function getPlainValue($input) { 00591 if (is_array($input)) { 00592 throw new Tx_Extbase_Persistence_Exception_UnexpectedTypeException('An array could not be converted to a plain value.', 1274799932); 00593 } 00594 if ($input instanceof DateTime) { 00595 return $input->format('U'); 00596 } elseif (is_object($input)) { 00597 if ($input instanceof Tx_Extbase_DomainObject_DomainObjectInterface) { 00598 return $input->getUid(); 00599 } else { 00600 throw new Tx_Extbase_Persistence_Exception_UnexpectedTypeException('An object of class "' . get_class($input) . '" could not be converted to a plain value.', 1274799934); 00601 } 00602 } elseif (is_bool($input)) { 00603 return $input === TRUE ? 1 : 0; 00604 } else { 00605 return $input; 00606 } 00607 } 00608 00609 /** 00610 * Parse a DynamicOperand into SQL and parameter arrays. 00611 * 00612 * @param Tx_Extbase_Persistence_QOM_DynamicOperandInterface $operand 00613 * @param string $operator One of the JCR_OPERATOR_* constants 00614 * @param Tx_Extbase_Persistence_QOM_SourceInterface $source The source 00615 * @param array &$sql The query parts 00616 * @param array &$parameters The parameters that will replace the markers 00617 * @param string $valueFunction an optional SQL function to apply to the operand value 00618 * @return void 00619 */ 00620 protected function parseDynamicOperand(Tx_Extbase_Persistence_QOM_DynamicOperandInterface $operand, $operator, Tx_Extbase_Persistence_QOM_SourceInterface $source, array &$sql, array &$parameters, $valueFunction = NULL, $operand2 = NULL) { 00621 if ($operand instanceof Tx_Extbase_Persistence_QOM_LowerCaseInterface) { 00622 $this->parseDynamicOperand($operand->getOperand(), $operator, $source, $sql, $parameters, 'LOWER'); 00623 } elseif ($operand instanceof Tx_Extbase_Persistence_QOM_UpperCaseInterface) { 00624 $this->parseDynamicOperand($operand->getOperand(), $operator, $source, $sql, $parameters, 'UPPER'); 00625 } elseif ($operand instanceof Tx_Extbase_Persistence_QOM_PropertyValueInterface) { 00626 $propertyName = $operand->getPropertyName(); 00627 if ($source instanceof Tx_Extbase_Persistence_QOM_SelectorInterface) { // FIXME Only necessary to differ from Join 00628 $className = $source->getNodeTypeName(); 00629 $tableName = $this->dataMapper->convertClassNameToTableName($className); 00630 while (strpos($propertyName, '.') !== FALSE) { 00631 $this->addUnionStatement($className, $tableName, $propertyName, $sql); 00632 } 00633 } elseif ($source instanceof Tx_Extbase_Persistence_QOM_JoinInterface) { 00634 $tableName = $source->getJoinCondition()->getSelector1Name(); 00635 } 00636 $columnName = $this->dataMapper->convertPropertyNameToColumnName($propertyName, $className); 00637 $operator = $this->resolveOperator($operator); 00638 if ($valueFunction === NULL) { 00639 $constraintSQL .= (!empty($tableName) ? $tableName . '.' : '') . $columnName . ' ' . $operator . ' ?'; 00640 } else { 00641 $constraintSQL .= $valueFunction . '(' . (!empty($tableName) ? $tableName . '.' : '') . $columnName . ') ' . $operator . ' ?'; 00642 } 00643 00644 $sql['where'][] = $constraintSQL; 00645 } 00646 } 00647 00648 protected function addUnionStatement(&$className, &$tableName, &$propertyPath, array &$sql) { 00649 $explodedPropertyPath = explode('.', $propertyPath, 2); 00650 $propertyName = $explodedPropertyPath[0]; 00651 $columnName = $this->dataMapper->convertPropertyNameToColumnName($propertyName, $className); 00652 $tableName = $this->dataMapper->convertClassNameToTableName($className); 00653 $columnMap = $this->dataMapper->getDataMap($className)->getColumnMap($propertyName); 00654 $parentKeyFieldName = $columnMap->getParentKeyFieldName(); 00655 $childTableName = $columnMap->getChildTableName(); 00656 if ($columnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_ONE) { 00657 if (isset($parentKeyFieldName)) { 00658 $sql['unions'][$childTableName] = 'LEFT JOIN ' . $childTableName . ' ON ' . $tableName . '.uid=' . $childTableName . '.' . $parentKeyFieldName; 00659 } else { 00660 $sql['unions'][$childTableName] = 'LEFT JOIN ' . $childTableName . ' ON ' . $tableName . '.' . $columnName . '=' . $childTableName . '.uid'; 00661 } 00662 $className = $this->dataMapper->getType($className, $propertyName); 00663 } elseif ($columnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_MANY) { 00664 if (isset($parentKeyFieldName)) { 00665 $sql['unions'][$childTableName] = 'LEFT JOIN ' . $childTableName . ' ON ' . $tableName . '.uid=' . $childTableName . '.' . $parentKeyFieldName; 00666 } else { 00667 $onStatement = '(FIND_IN_SET(' . $childTableName . '.uid, ' . $tableName . '.' . $columnName . '))'; 00668 $sql['unions'][$childTableName] = 'LEFT JOIN ' . $childTableName . ' ON ' . $onStatement; 00669 } 00670 $className = $this->dataMapper->getType($className, $propertyName); 00671 } elseif ($columnMap->getTypeOfRelation() === Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) { 00672 $relationTableName = $columnMap->getRelationTableName(); 00673 $sql['unions'][$relationTableName] = 'LEFT JOIN ' . $relationTableName . ' ON ' . $tableName . '.uid=' . $relationTableName . '.uid_local'; 00674 $sql['unions'][$childTableName] = 'LEFT JOIN ' . $childTableName . ' ON ' . $relationTableName . '.uid_foreign=' . $childTableName . '.uid'; 00675 $className = $this->dataMapper->getType($className, $propertyName); 00676 } else { 00677 throw new Tx_Extbase_Persistence_Exception('Could not determine type of relation.', 1252502725); 00678 } 00679 // TODO check if there is another solution for this 00680 $sql['keywords']['distinct'] = 'DISTINCT'; 00681 $propertyPath = $explodedPropertyPath[1]; 00682 $tableName = $childTableName; 00683 } 00684 00685 /** 00686 * Returns the SQL operator for the given JCR operator type. 00687 * 00688 * @param string $operator One of the JCR_OPERATOR_* constants 00689 * @return string an SQL operator 00690 */ 00691 protected function resolveOperator($operator) { 00692 switch ($operator) { 00693 case self::OPERATOR_EQUAL_TO_NULL: 00694 $operator = 'IS'; 00695 break; 00696 case self::OPERATOR_NOT_EQUAL_TO_NULL: 00697 $operator = 'IS NOT'; 00698 break; 00699 case Tx_Extbase_Persistence_QueryInterface::OPERATOR_IN: 00700 $operator = 'IN'; 00701 break; 00702 case Tx_Extbase_Persistence_QueryInterface::OPERATOR_EQUAL_TO: 00703 $operator = '='; 00704 break; 00705 case Tx_Extbase_Persistence_QueryInterface::OPERATOR_NOT_EQUAL_TO: 00706 $operator = '!='; 00707 break; 00708 case Tx_Extbase_Persistence_QueryInterface::OPERATOR_LESS_THAN: 00709 $operator = '<'; 00710 break; 00711 case Tx_Extbase_Persistence_QueryInterface::OPERATOR_LESS_THAN_OR_EQUAL_TO: 00712 $operator = '<='; 00713 break; 00714 case Tx_Extbase_Persistence_QueryInterface::OPERATOR_GREATER_THAN: 00715 $operator = '>'; 00716 break; 00717 case Tx_Extbase_Persistence_QueryInterface::OPERATOR_GREATER_THAN_OR_EQUAL_TO: 00718 $operator = '>='; 00719 break; 00720 case Tx_Extbase_Persistence_QueryInterface::OPERATOR_LIKE: 00721 $operator = 'LIKE'; 00722 break; 00723 default: 00724 throw new Tx_Extbase_Persistence_Exception('Unsupported operator encountered.', 1242816073); 00725 } 00726 00727 return $operator; 00728 } 00729 00730 /** 00731 * Replace query placeholders in a query part by the given 00732 * parameters. 00733 * 00734 * @param string $sqlString The query part with placeholders 00735 * @param array $parameters The parameters 00736 * @return string The query part with replaced placeholders 00737 */ 00738 protected function replacePlaceholders(&$sqlString, array $parameters) { 00739 // TODO profile this method again 00740 if (substr_count($sqlString, '?') !== count($parameters)) throw new Tx_Extbase_Persistence_Exception('The number of question marks to replace must be equal to the number of parameters.', 1242816074); 00741 $offset = 0; 00742 foreach ($parameters as $parameter) { 00743 $markPosition = strpos($sqlString, '?', $offset); 00744 if ($markPosition !== FALSE) { 00745 if ($parameter === NULL) { 00746 $parameter = 'NULL'; 00747 } elseif (is_array($parameter) || ($parameter instanceof ArrayAccess) || ($parameter instanceof Traversable)) { 00748 $items = array(); 00749 foreach ($parameter as $item) { 00750 $items[] = $this->databaseHandle->fullQuoteStr($item, 'foo'); 00751 } 00752 $parameter = '(' . implode(',', $items) . ')'; 00753 } else { 00754 $parameter = $this->databaseHandle->fullQuoteStr($parameter, 'foo'); // FIXME This may not work with DBAL; check this 00755 } 00756 $sqlString = substr($sqlString, 0, $markPosition) . $parameter . substr($sqlString, $markPosition + 1); 00757 } 00758 $offset = $markPosition + strlen($parameter); 00759 } 00760 } 00761 00762 /** 00763 * Adds additional WHERE statements according to the query settings. 00764 * 00765 * @param Tx_Extbase_Persistence_QuerySettingsInterface $querySettings The TYPO3 4.x specific query settings 00766 * @param string $tableName The table name to add the additional where clause for 00767 * @param string $sql 00768 * @return void 00769 */ 00770 protected function addAdditionalWhereClause(Tx_Extbase_Persistence_QuerySettingsInterface $querySettings, $tableName, &$sql) { 00771 if ($querySettings instanceof Tx_Extbase_Persistence_Typo3QuerySettings) { 00772 if ($querySettings->getRespectEnableFields()) { 00773 $this->addEnableFieldsStatement($tableName, $sql); 00774 } 00775 if ($querySettings->getRespectSysLanguage()) { 00776 $this->addSysLanguageStatement($tableName, $sql); 00777 } 00778 if ($querySettings->getRespectStoragePage()) { 00779 $this->addPageIdStatement($tableName, $sql, $querySettings->getStoragePageIds()); 00780 } 00781 } 00782 } 00783 00784 /** 00785 * Builds the enable fields statement 00786 * 00787 * @param string $tableName The database table name 00788 * @param array &$sql The query parts 00789 * @return void 00790 */ 00791 protected function addEnableFieldsStatement($tableName, array &$sql) { 00792 if (is_array($GLOBALS['TCA'][$tableName]['ctrl'])) { 00793 if (TYPO3_MODE === 'FE') { 00794 $statement = $GLOBALS['TSFE']->sys_page->enableFields($tableName); 00795 } else { // TYPO3_MODE === 'BE' 00796 $statement = t3lib_BEfunc::deleteClause($tableName); 00797 $statement .= t3lib_BEfunc::BEenableFields($tableName); 00798 } 00799 if(!empty($statement)) { 00800 $statement = substr($statement, 5); 00801 $sql['additionalWhereClause'][] = $statement; 00802 } 00803 } 00804 } 00805 00806 /** 00807 * Builds the language field statement 00808 * 00809 * @param string $tableName The database table name 00810 * @param array &$sql The query parts 00811 * @return void 00812 */ 00813 protected function addSysLanguageStatement($tableName, array &$sql) { 00814 if (is_array($GLOBALS['TCA'][$tableName]['ctrl'])) { 00815 if(isset($GLOBALS['TCA'][$tableName]['ctrl']['languageField']) && $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] !== NULL) { 00816 $sql['additionalWhereClause'][] = $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . ' IN (0,-1)'; 00817 } 00818 } 00819 } 00820 00821 /** 00822 * Builds the page ID checking statement 00823 * 00824 * @param string $tableName The database table name 00825 * @param array &$sql The query parts 00826 * @param array $storagePageIds list of storage page ids 00827 * @return void 00828 */ 00829 protected function addPageIdStatement($tableName, array &$sql, array $storagePageIds) { 00830 if (empty($this->tableInformationCache[$tableName]['columnNames'])) { 00831 $this->tableInformationCache[$tableName]['columnNames'] = $this->databaseHandle->admin_get_fields($tableName); 00832 } 00833 if (is_array($GLOBALS['TCA'][$tableName]['ctrl']) && array_key_exists('pid', $this->tableInformationCache[$tableName]['columnNames'])) { 00834 $sql['additionalWhereClause'][] = $tableName . '.pid IN (' . implode(', ', $storagePageIds) . ')'; 00835 } 00836 } 00837 00838 /** 00839 * Transforms orderings into SQL. 00840 * 00841 * @param array $orderings An array of orderings (Tx_Extbase_Persistence_QOM_Ordering) 00842 * @param Tx_Extbase_Persistence_QOM_SourceInterface $source The source 00843 * @param array &$sql The query parts 00844 * @return void 00845 */ 00846 protected function parseOrderings(array $orderings, Tx_Extbase_Persistence_QOM_SourceInterface $source, array &$sql) { 00847 foreach ($orderings as $propertyName => $order) { 00848 switch ($order) { 00849 case Tx_Extbase_Persistence_QOM_QueryObjectModelConstantsInterface::JCR_ORDER_ASCENDING: // Deprecated since Extbase 1.1 00850 case Tx_Extbase_Persistence_QueryInterface::ORDER_ASCENDING: 00851 $order = 'ASC'; 00852 break; 00853 case Tx_Extbase_Persistence_QOM_QueryObjectModelConstantsInterface::JCR_ORDER_DESCENDING: // Deprecated since Extbase 1.1 00854 case Tx_Extbase_Persistence_QueryInterface::ORDER_DESCENDING: 00855 $order = 'DESC'; 00856 break; 00857 default: 00858 throw new Tx_Extbase_Persistence_Exception_UnsupportedOrder('Unsupported order encountered.', 1242816074); 00859 } 00860 if ($source instanceof Tx_Extbase_Persistence_QOM_SelectorInterface) { 00861 $className = $source->getNodeTypeName(); 00862 $tableName = $this->dataMapper->convertClassNameToTableName($className); 00863 while (strpos($propertyName, '.') !== FALSE) { 00864 $this->addUnionStatement($className, $tableName, $propertyName, $sql); 00865 } 00866 } elseif ($source instanceof Tx_Extbase_Persistence_QOM_JoinInterface) { 00867 $tableName = $source->getLeft()->getSelectorName(); 00868 } 00869 $columnName = $this->dataMapper->convertPropertyNameToColumnName($propertyName, $className); 00870 if (strlen($tableName) > 0) { 00871 $sql['orderings'][] = $tableName . '.' . $columnName . ' ' . $order; 00872 } else { 00873 $sql['orderings'][] = $columnName . ' ' . $order; 00874 } 00875 } 00876 } 00877 00878 /** 00879 * Transforms limit and offset into SQL 00880 * 00881 * @param int $limit 00882 * @param int $offset 00883 * @param array &$sql 00884 * @return void 00885 */ 00886 protected function parseLimitAndOffset($limit, $offset, array &$sql) { 00887 if ($limit !== NULL && $offset !== NULL) { 00888 $sql['limit'] = $offset . ', ' . $limit; 00889 } elseif ($limit !== NULL) { 00890 $sql['limit'] = $limit; 00891 } 00892 } 00893 00894 /** 00895 * Transforms a Resource from a database query to an array of rows. 00896 * 00897 * @param Tx_Extbase_Persistence_QOM_SourceInterface $source The source (selector od join) 00898 * @param resource $result The result 00899 * @return array The result as an array of rows (tuples) 00900 */ 00901 protected function getRowsFromResult(Tx_Extbase_Persistence_QOM_SourceInterface $source, $result) { 00902 $rows = array(); 00903 while ($row = $this->databaseHandle->sql_fetch_assoc($result)) { 00904 if (is_array($row)) { 00905 // TODO Check if this is necessary, maybe the last line is enough 00906 $arrayKeys = range(0, count($row)); 00907 array_fill_keys($arrayKeys, $row); 00908 $rows[] = $row; 00909 } 00910 } 00911 return $rows; 00912 } 00913 00914 /** 00915 * Performs workspace and language overlay on the given row array. The language and workspace id is automatically 00916 * detected (depending on FE or BE context). You can also explicitly set the language/workspace id. 00917 * 00918 * @param Tx_Extbase_Persistence_QOM_SourceInterface $source The source (selector od join) 00919 * @param array $row The row array (as reference) 00920 * @param string $languageUid The language id 00921 * @param string $workspaceUidUid The workspace id 00922 * @return void 00923 */ 00924 protected function doLanguageAndWorkspaceOverlay(Tx_Extbase_Persistence_QOM_SourceInterface $source, array $rows, $languageUid = NULL, $workspaceUid = NULL) { 00925 $overlayedRows = array(); 00926 foreach ($rows as $row) { 00927 if (!($this->pageSelectObject instanceof t3lib_pageSelect)) { 00928 if (TYPO3_MODE == 'FE') { 00929 if (is_object($GLOBALS['TSFE'])) { 00930 $this->pageSelectObject = $GLOBALS['TSFE']->sys_page; 00931 } else { 00932 $this->pageSelectObject = t3lib_div::makeInstance('t3lib_pageSelect'); 00933 } 00934 } else { 00935 $this->pageSelectObject = t3lib_div::makeInstance( 't3lib_pageSelect' ); 00936 } 00937 } 00938 if (is_object($GLOBALS['TSFE'])) { 00939 if ($languageUid === NULL) { 00940 $languageUid = $GLOBALS['TSFE']->sys_language_uid; 00941 $languageMode = $GLOBALS['TSFE']->sys_language_mode; 00942 } 00943 if ($workspaceUid !== NULL) { 00944 $this->pageSelectObject->versioningWorkspaceId = $workspaceUid; 00945 } 00946 } else { 00947 if ($languageUid === NULL) { 00948 $languageUid = intval(t3lib_div::_GP('L')); 00949 } 00950 if ($workspaceUid === NULL) { 00951 $workspaceUid = $GLOBALS['BE_USER']->workspace; 00952 } 00953 $this->pageSelectObject->versioningWorkspaceId = $workspaceUid; 00954 } 00955 if ($source instanceof Tx_Extbase_Persistence_QOM_SelectorInterface) { 00956 $tableName = $source->getSelectorName(); 00957 } elseif ($source instanceof Tx_Extbase_Persistence_QOM_JoinInterface) { 00958 $tableName = $source->getRight()->getSelectorName(); 00959 } 00960 $this->pageSelectObject->versionOL($tableName, $row, TRUE); 00961 if($tableName == 'pages') { 00962 $row = $this->pageSelectObject->getPageOverlay($row, $languageUid); 00963 } elseif(isset($GLOBALS['TCA'][$tableName]['ctrl']['languageField']) && $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] !== '') { 00964 if (in_array($row[$GLOBALS['TCA'][$tableName]['ctrl']['languageField']], array(-1,0))) { 00965 $overlayMode = ($languageMode === 'strict') ? 'hideNonTranslated' : ''; 00966 $row = $this->pageSelectObject->getRecordOverlay($tableName, $row, $languageUid, $overlayMode); 00967 } 00968 } 00969 if ($row !== NULL && is_array($row)) { 00970 $overlayedRows[] = $row; 00971 } 00972 } 00973 return $overlayedRows; 00974 } 00975 00976 /** 00977 * Checks if there are SQL errors in the last query, and if yes, throw an exception. 00978 * 00979 * @return void 00980 * @param string $sql The SQL statement 00981 * @throws Tx_Extbase_Persistence_Storage_Exception_SqlError 00982 */ 00983 protected function checkSqlErrors($sql='') { 00984 $error = $this->databaseHandle->sql_error(); 00985 if ($error !== '') { 00986 $error .= $sql ? ': ' . $sql : ''; 00987 throw new Tx_Extbase_Persistence_Storage_Exception_SqlError($error, 1247602160); 00988 } 00989 } 00990 00991 /** 00992 * Clear the TYPO3 page cache for the given record. 00993 * If the record lies on a page, then we clear the cache of this page. 00994 * If the record has no PID column, we clear the cache of the current page as best-effort. 00995 * 00996 * Much of this functionality is taken from t3lib_tcemain::clear_cache() which unfortunately only works with logged-in BE user. 00997 * 00998 * @param $tableName Table name of the record 00999 * @param $uid UID of the record 01000 * @return void 01001 */ 01002 protected function clearPageCache($tableName, $uid) { 01003 $frameworkConfiguration = $this->configurationManager->getConfiguration(Tx_Extbase_Configuration_ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK); 01004 if (isset($frameworkConfiguration['persistence']['enableAutomaticCacheClearing']) && $frameworkConfiguration['persistence']['enableAutomaticCacheClearing'] === '1') { 01005 } else { 01006 // if disabled, return 01007 return; 01008 } 01009 01010 $pageIdsToClear = array(); 01011 $storagePage = NULL; 01012 01013 $columns = $this->databaseHandle->admin_get_fields($tableName); 01014 if (array_key_exists('pid', $columns)) { 01015 $result = $this->databaseHandle->exec_SELECTquery('pid', $tableName, 'uid='.intval($uid)); 01016 if ($row = $this->databaseHandle->sql_fetch_assoc($result)) { 01017 $storagePage = $row['pid']; 01018 $pageIdsToClear[] = $storagePage; 01019 } 01020 } elseif (isset($GLOBALS['TSFE'])) { 01021 // No PID column - we can do a best-effort to clear the cache of the current page if in FE 01022 $storagePage = $GLOBALS['TSFE']->id; 01023 $pageIdsToClear[] = $storagePage; 01024 } 01025 01026 if ($storagePage === NULL) { 01027 return; 01028 } 01029 if (!isset($this->pageTSConfigCache[$storagePage])) { 01030 $this->pageTSConfigCache[$storagePage] = t3lib_BEfunc::getPagesTSconfig($storagePage); 01031 } 01032 if (isset($this->pageTSConfigCache[$storagePage]['TCEMAIN.']['clearCacheCmd'])) { 01033 $clearCacheCommands = t3lib_div::trimExplode(',',strtolower($this->pageTSConfigCache[$storagePage]['TCEMAIN.']['clearCacheCmd']),1); 01034 $clearCacheCommands = array_unique($clearCacheCommands); 01035 foreach ($clearCacheCommands as $clearCacheCommand) { 01036 if (t3lib_div::testInt($clearCacheCommand)) { 01037 $pageIdsToClear[] = $clearCacheCommand; 01038 } 01039 } 01040 } 01041 01042 // TODO check if we can hand this over to the Dispatcher to clear the page only once, this will save around 10% time while inserting and updating 01043 Tx_Extbase_Utility_Cache::clearPageCache($pageIdsToClear); 01044 } 01045 } 01046 01047 ?>
1.8.0