[+BUGFIX] Extbase (Persistence): Fixed typo in Exception class.
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / Persistence / Storage / Typo3DbBackend.php
index aa1dd59..6aecfd7 100644 (file)
@@ -142,17 +142,24 @@ class Tx_Extbase_Persistence_Storage_Typo3DbBackend implements Tx_Extbase_Persis
         * Deletes a row in the storage
         *
         * @param string $tableName The database table name
-        * @param array $uid The uid of the row to be deleted
+        * @param array $identifyer An array of identifyer array('fieldname' => value). This array will be transformed to a WHERE clause
         * @param boolean $isRelation TRUE if we are currently inserting into a relation table, FALSE by default
         * @return void
         */
-       public function removeRow($tableName, $uid, $isRelation = FALSE) {
-               $sqlString = 'DELETE FROM ' . $tableName . ' WHERE uid=?';
-               $this->replacePlaceholders($sqlString, array((int)$uid));
+       public function removeRow($tableName, array $identifyer, $isRelation = FALSE) {
+               $fieldNames = array_keys($identifyer);
+               $suffixedFieldNames = array();
+               foreach ($fieldNames as $fieldName) {
+                       $suffixedFieldNames[] = $fieldName . '=?';
+               }
+               $parameters = array_values($identifyer);
+               $statement = 'DELETE FROM ' . $tableName;
+               $statement .= ' WHERE ' . implode(' AND ', $suffixedFieldNames);
+               $this->replacePlaceholders($statement, $parameters);
                if (!$isRelation) {
                        $this->clearPageCache($tableName, $uid, $isRelation);
                }
-               $returnValue = $this->databaseHandle->sql_query($sqlString);
+               $returnValue = $this->databaseHandle->sql_query($statement);
                $this->checkSqlErrors();
                return $returnValue;
        }
@@ -165,6 +172,7 @@ class Tx_Extbase_Persistence_Storage_Typo3DbBackend implements Tx_Extbase_Persis
         */
        public function getRows(Tx_Extbase_Persistence_QOM_QueryObjectModelInterface $query) {
                $statement = $this->parseQuery($query);
+               // debug($statement, -2); // FIXME remove debug code
                $result = $this->databaseHandle->sql_query($statement);
                $this->checkSqlErrors();
                if ($result) {
@@ -206,7 +214,7 @@ class Tx_Extbase_Persistence_Storage_Typo3DbBackend implements Tx_Extbase_Persis
 
                        $statement = 'SELECT ' . implode(',', $sql['fields']) . ' FROM ' . implode(' ', $sql['tables']);
 
-                       $this->parseConstraint($query->getConstraint(), $source, $sql, $parameters, $query->getBoundVariableValues());
+                       $this->parseConstraint($constraint, $source, $sql, $parameters, $query->getBoundVariableValues());
 
                        if (!empty($sql['where'])) {
                                $statement .= ' WHERE ' . implode('', $sql['where']);
@@ -217,7 +225,7 @@ class Tx_Extbase_Persistence_Storage_Typo3DbBackend implements Tx_Extbase_Persis
                                $statement .= ' WHERE ' . implode(' AND ', $sql['additionalWhereClause']);
                        }
 
-                       $this->parseOrderings($query->getOrderings(), $source, $sql, $parameters, $query->getBoundVariableValues());
+                       $this->parseOrderings($query->getOrderings(), $source, $sql);
                        if (!empty($sql['orderings'])) {
                                $statement .= ' ORDER BY ' . implode(', ', $sql['orderings']);
                        }
@@ -227,9 +235,7 @@ class Tx_Extbase_Persistence_Storage_Typo3DbBackend implements Tx_Extbase_Persis
                                $statement .= ' LIMIT ' . $sql['limit'];
                        }
                }
-
                $this->replacePlaceholders($statement, $parameters);
-
                return $statement;
        }
 
@@ -238,23 +244,31 @@ class Tx_Extbase_Persistence_Storage_Typo3DbBackend implements Tx_Extbase_Persis
         *
         * @param array $properties The properties of the Value Object
         * @param Tx_Extbase_Persistence_Mapper_DataMap $dataMap The Data Map
-        * @return array The matching tuples
+        * @return array The matching uid
         */
        public function hasValueObject(array $properties, Tx_Extbase_Persistence_Mapper_DataMap $dataMap) {
                $fields = array();
                $parameters = array();
                foreach ($properties as $propertyName => $propertyValue) {
-                       if ($dataMap->isPersistableProperty($propertyName) && ($propertyName !== 'uid')) {
+                       // FIXME We couple the Backend to the Entity implementation (uid, isClone); changes there breaks this method
+                       if ($dataMap->isPersistableProperty($propertyName) && ($propertyName !== 'uid')  && ($propertyName !== 'pid') && ($propertyName !== 'isClone')) {
                                $fields[] = $dataMap->getColumnMap($propertyName)->getColumnName() . '=?';
                                $parameters[] = $dataMap->convertPropertyValueToFieldValue($propertyValue);
                        }
                }
-               $fields[] = 'deleted!=1';
-               $fields[] = 'hidden!=1';
-               
-               $sqlString = 'SELECT * FROM ' . $dataMap->getTableName() .  ' WHERE ' . implode(' AND ', $fields);
-               $this->replacePlaceholders($sqlString, $parameters);
-               $res = $this->databaseHandle->sql_query($sqlString);
+               $sql = array();
+               $sql['additionalWhereClause'] = array();
+
+               $tableName = $dataMap->getTableName();
+               $this->addEnableFieldsStatement($tableName, $sql);
+
+               $statement = 'SELECT * FROM ' . $tableName;
+               $statement .= ' WHERE ' . implode(' AND ', $fields);
+               if (!empty($sql['additionalWhereClause'])) {
+                       $statement .= ' AND ' . implode(' AND ', $sql['additionalWhereClause']);
+               }
+               $this->replacePlaceholders($statement, $parameters);
+               $res = $this->databaseHandle->sql_query($statement);
                $this->checkSqlErrors();
                $row = $this->databaseHandle->sql_fetch_assoc($res);
                if ($row !== FALSE) {
@@ -288,20 +302,19 @@ class Tx_Extbase_Persistence_Storage_Typo3DbBackend implements Tx_Extbase_Persis
                                }
                        }
                } elseif ($source instanceof Tx_Extbase_Persistence_QOM_JoinInterface) {
-                       $this->parseJoin($query, $source, $sql, $parameters);
+                       $this->parseJoin($query, $source, $sql);
                }
        }
 
        /**
         * Transforms a Join into SQL and parameter arrays
         *
-        * @param Tx_Extbase_Persistence_QOM_QueryObjectModel $query
-        * @param Tx_Extbase_Persistence_QOM_JoinInterface $join
-        * @param array &$sql
-        * @param array &$parameters
+        * @param Tx_Extbase_Persistence_QOM_QueryObjectModel $query The Query Object Model
+        * @param Tx_Extbase_Persistence_QOM_JoinInterface $join The join
+        * @param array &$sql The query parts
         * @return void
         */
-       protected function parseJoin(Tx_Extbase_Persistence_QOM_QueryObjectModelInterface $query, Tx_Extbase_Persistence_QOM_JoinInterface $join, array &$sql, array &$parameters) {
+       protected function parseJoin(Tx_Extbase_Persistence_QOM_QueryObjectModelInterface $query, Tx_Extbase_Persistence_QOM_JoinInterface $join, array &$sql) {
                $leftSource = $join->getLeft();
                $leftTableName = $leftSource->getSelectorName();
                $rightSource = $join->getRight();
@@ -316,6 +329,7 @@ class Tx_Extbase_Persistence_Storage_Typo3DbBackend implements Tx_Extbase_Persis
                $joinCondition = $join->getJoinCondition();
                // TODO Check the parsing of the join
                if ($joinCondition instanceof Tx_Extbase_Persistence_QOM_EquiJoinCondition) {
+                       // TODO Discuss, if we should use $leftSource instead of $selector1Name
                        $column1Name = $this->dataMapper->convertPropertyNameToColumnName($joinCondition->getProperty1Name(), $leftSource->getNodeTypeName());
                        $column2Name = $this->dataMapper->convertPropertyNameToColumnName($joinCondition->getProperty2Name(), $rightSource->getNodeTypeName());
                        $sql['tables'][] = 'ON ' . $joinCondition->getSelector1Name() . '.' . $column1Name . ' = ' . $joinCondition->getSelector2Name() . '.' . $column2Name;
@@ -338,14 +352,15 @@ class Tx_Extbase_Persistence_Storage_Typo3DbBackend implements Tx_Extbase_Persis
        /**
         * Transforms a constraint into SQL and parameter arrays
         *
-        * @param Tx_Extbase_Persistence_QOM_ConstraintInterface $constraint
+        * @param Tx_Extbase_Persistence_QOM_ConstraintInterface $constraint The constraint
         * @param Tx_Extbase_Persistence_QOM_SourceInterface $source The source
-        * @param array &$sql
-        * @param array &$parameters
-        * @param array $boundVariableValues
+        * @param array &$sql The query parts
+        * @param array &$parameters The parameters that will replace the markers
+        * @param array $boundVariableValues The bound variables in the query (key) and their values (value)
         * @return void
         */
        protected function parseConstraint(Tx_Extbase_Persistence_QOM_ConstraintInterface $constraint = NULL, Tx_Extbase_Persistence_QOM_SourceInterface $source, array &$sql, array &$parameters, array $boundVariableValues) {
+               if ($constraint === NULL) return;
                if ($constraint instanceof Tx_Extbase_Persistence_QOM_AndInterface) {
                        $sql['where'][] = '(';
                        $this->parseConstraint($constraint->getConstraint1(), $source, $sql, $parameters, $boundVariableValues);
@@ -404,21 +419,21 @@ class Tx_Extbase_Persistence_Storage_Typo3DbBackend implements Tx_Extbase_Persis
         * @param Tx_Extbase_Persistence_QOM_DynamicOperandInterface $operand
         * @param string $operator One of the JCR_OPERATOR_* constants
         * @param Tx_Extbase_Persistence_QOM_SourceInterface $source The source
-        * @param array &$sql SQL query parts to add to
-        * @param array &$parameters
-        * @param string $valueFunction an aoptional SQL function to apply to the operand value
+        * @param array &$sql The query parts
+        * @param array &$parameters The parameters that will replace the markers
+        * @param string $valueFunction an optional SQL function to apply to the operand value
         * @return void
         */
        protected function parseDynamicOperand(Tx_Extbase_Persistence_QOM_DynamicOperandInterface $operand, $operator, Tx_Extbase_Persistence_QOM_SourceInterface $source, array &$sql, array &$parameters, $valueFunction = NULL) {
                if ($operand instanceof Tx_Extbase_Persistence_QOM_LowerCaseInterface) {
-                       $this->parseDynamicOperand($operand->getOperand(), $operator, $sql, $parameters, 'LOWER');
+                       $this->parseDynamicOperand($operand->getOperand(), $operator, $source, $sql, $parameters, 'LOWER');
                } elseif ($operand instanceof Tx_Extbase_Persistence_QOM_UpperCaseInterface) {
-                       $this->parseDynamicOperand($operand->getOperand(), $operator, $sql, $parameters, 'UPPER');
+                       $this->parseDynamicOperand($operand->getOperand(), $operator, $source, $sql, $parameters, 'UPPER');
                } elseif ($operand instanceof Tx_Extbase_Persistence_QOM_PropertyValueInterface) {
                        $tableName = $operand->getSelectorName();
                        // FIXME Discuss the translation from propertyName to columnName
                        if ($source instanceof Tx_Extbase_Persistence_QOM_SelectorInterface) {
-                                $className = $source->getNodeTypeName();
+                               $className = $source->getNodeTypeName();
                        } else {
                                $className = '';
                        }
@@ -481,7 +496,7 @@ class Tx_Extbase_Persistence_Storage_Typo3DbBackend implements Tx_Extbase_Persis
         * Replace query placeholders in a query part by the given
         * parameters.
         *
-        * @param string $queryPart The query part with placeholders
+        * @param string $sqlString The query part with placeholders
         * @param array $parameters The parameters
         * @return string The query part with replaced placeholders
         */
@@ -512,11 +527,13 @@ class Tx_Extbase_Persistence_Storage_Typo3DbBackend implements Tx_Extbase_Persis
        protected function addEnableFieldsStatement($tableName, array &$sql) {
                if (is_array($GLOBALS['TCA'][$tableName]['ctrl'])) {
                        if (TYPO3_MODE === 'FE') {
-                               $statement = substr($GLOBALS['TSFE']->sys_page->enableFields($tableName), 5);
+                               $statement = $GLOBALS['TSFE']->sys_page->enableFields($tableName);
                        } else { // TYPO3_MODE === 'BE'
-                               $statement = substr(t3lib_BEfunc::BEenableFields($tableName), 5);
+                               $statement = t3lib_BEfunc::deleteClause($tableName);
+                               $statement .= t3lib_BEfunc::BEenableFields($tableName);
                        }
                        if(!empty($statement)) {
+                               $statement = substr($statement, 5);
                                $sql['additionalWhereClause'][] = $statement;
                        }
                }
@@ -530,22 +547,22 @@ class Tx_Extbase_Persistence_Storage_Typo3DbBackend implements Tx_Extbase_Persis
         * @return void
         */
        protected function addPageIdStatement($tableName, array &$sql) {
-               if (is_array($GLOBALS['TCA'][$tableName]['ctrl'])) {
+               $columns = $this->databaseHandle->admin_get_fields($tableName);         
+               if (is_array($GLOBALS['TCA'][$tableName]['ctrl']) && array_key_exists('pid', $columns)) {
                        $extbaseFrameworkConfiguration = Tx_Extbase_Dispatcher::getExtbaseFrameworkConfiguration();
                        $sql['additionalWhereClause'][] = $tableName . '.pid IN (' . implode(', ', t3lib_div::intExplode(',', $extbaseFrameworkConfiguration['persistence']['storagePid'])) . ')';
                }
        }
 
        /**
-        * Transforms orderings into SQL
+        * Transforms orderings into SQL.
         *
-        * @param array $orderings
-        * @param array &$sql
-        * @param array &$parameters
-        * @param array $boundVariableValues
+        * @param array $orderings Ann array of orderings (Tx_Extbase_Persistence_QOM_Ordering)
+        * @param Tx_Extbase_Persistence_QOM_SourceInterface $source The source
+        * @param array &$sql The query parts
         * @return void
         */
-       protected function parseOrderings(array $orderings, Tx_Extbase_Persistence_QOM_SourceInterface $source, array &$sql, array &$parameters, array $boundVariableValues) {
+       protected function parseOrderings(array $orderings, Tx_Extbase_Persistence_QOM_SourceInterface $source, array &$sql) {
                foreach ($orderings as $ordering) {
                        $operand = $ordering->getOperand();
                        $order = $ordering->getOrder();
@@ -558,10 +575,19 @@ class Tx_Extbase_Persistence_Storage_Typo3DbBackend implements Tx_Extbase_Persis
                                                $order = 'DESC';
                                                break;
                                        default:
-                                               throw new Tx_Extbase_Persistence_Exception('Unsupported order encountered.', 1242816074);
+                                               throw new Tx_Extbase_Persistence_Exception_UnsupportedOrder('Unsupported order encountered.', 1242816074);
+                               }
+                               $tableName = $operand->getSelectorName();
+                               $className = '';
+                               if ($source instanceof Tx_Extbase_Persistence_QOM_SelectorInterface) {
+                                       $className = $source->getNodeTypeName();
+                               }
+                               $columnName = $this->dataMapper->convertPropertyNameToColumnName($operand->getPropertyName(), $className);
+                               if (strlen($tableName) > 0) {
+                                       $sql['orderings'][] = $tableName . '.' . $columnName . ' ' . $order;
+                               } else {
+                                       $sql['orderings'][] = $columnName . ' ' . $order;
                                }
-                               $columnName = $this->dataMapper->convertPropertyNameToColumnName($ordering->getOperand()->getPropertyName(), $source->getNodeTypeName());
-                               $sql['orderings'][] = $columnName . ' ' . $order;
                        }
                }
        }
@@ -587,7 +613,7 @@ class Tx_Extbase_Persistence_Storage_Typo3DbBackend implements Tx_Extbase_Persis
         * workspace overlay before.
         *
         * @param Tx_Extbase_Persistence_QOM_SourceInterface $source The source (selector od join)
-        *
+        * @param resource &$sql The resource
         * @return array The result as an array of rows (tuples)
         */
        protected function getRowsFromResult(Tx_Extbase_Persistence_QOM_SourceInterface $source, $res) {
@@ -666,6 +692,9 @@ class Tx_Extbase_Persistence_Storage_Typo3DbBackend implements Tx_Extbase_Persis
 
        /**
         * Clear the TYPO3 page cache for the given record.
+        * If the record lies on a page, then we clear the cache of this page.
+        * If the record has no PID column, we clear the cache of the current page as best-effort.
+        *
         * Much of this functionality is taken from t3lib_tcemain::clear_cache() which unfortunately only works with logged-in BE user.
         *
         * @param $tableName Table name of the record
@@ -680,14 +709,24 @@ class Tx_Extbase_Persistence_Storage_Typo3DbBackend implements Tx_Extbase_Persis
                        return;
                }
 
-               $result = $this->databaseHandle->exec_SELECTquery('pid', $tableName, 'uid='.intval($uid));
-
                $pageIdsToClear = array();
-               if ($row = $this->databaseHandle->sql_fetch_assoc($result))     {
-                       $storagePage = $row['pid'];
+               $storagePage = NULL;
+
+               $columns = $this->databaseHandle->admin_get_fields($tableName);
+               if (array_key_exists('pid', $columns)) {
+                       $result = $this->databaseHandle->exec_SELECTquery('pid', $tableName, 'uid='.intval($uid));
+                       if ($row = $this->databaseHandle->sql_fetch_assoc($result))     {
+                               $storagePage = $row['pid'];
+                               $pageIdsToClear[] = $storagePage;
+                       }
+               } elseif (isset($GLOBALS['TSFE'])) {
+                       // No PID column - we can do a best-effort to clear the cache of the current page if in FE
+                       $storagePage = $GLOBALS['TSFE']->id;
                        $pageIdsToClear[] = $storagePage;
                }
-               if (!$storagePage) {
+
+
+               if ($storagePage === NULL) {
                        return;
                }