diff --git a/typo3/sysext/extbase/Classes/DomainObject/AbstractDomainObject.php b/typo3/sysext/extbase/Classes/DomainObject/AbstractDomainObject.php index 7b9337ab3f0847e3f2391715a11f352c17ecdcdf..53130ecdc94aed0848757f35b511cfa1bc3d6b54 100644 --- a/typo3/sysext/extbase/Classes/DomainObject/AbstractDomainObject.php +++ b/typo3/sysext/extbase/Classes/DomainObject/AbstractDomainObject.php @@ -32,7 +32,7 @@ namespace TYPO3\CMS\Extbase\DomainObject; * * All Model domain objects need to inherit from either AbstractEntity or AbstractValueObject, as this provides important framework information. */ -abstract class AbstractDomainObject implements \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface, \TYPO3\CMS\Extbase\Persistence\ObjectMonitoringInterface { +abstract class AbstractDomainObject implements DomainObjectInterface, \TYPO3\CMS\Extbase\Persistence\ObjectMonitoringInterface { /** * @var int The uid of the record. The uid is only unique in the context of the database table. @@ -291,7 +291,7 @@ abstract class AbstractDomainObject implements \TYPO3\CMS\Extbase\DomainObject\D // In case it is an object and it implements the ObjectMonitoringInterface, we call _isDirty() instead of a simple comparison of objects. // We do this, because if the object itself contains a lazy loaded property, the comparison of the objects might fail even if the object didn't change if (is_object($currentValue)) { - if ($currentValue instanceof \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface) { + if ($currentValue instanceof DomainObjectInterface) { $result = !is_object($previousValue) || get_class($previousValue) !== get_class($currentValue) || $currentValue->getUid() !== $previousValue->getUid(); } elseif ($currentValue instanceof \TYPO3\CMS\Extbase\Persistence\ObjectMonitoringInterface) { $result = !is_object($previousValue) || $currentValue->_isDirty() || get_class($previousValue) !== get_class($currentValue); diff --git a/typo3/sysext/extbase/Classes/Persistence/Generic/Qom/LowerCase.php b/typo3/sysext/extbase/Classes/Persistence/Generic/Qom/LowerCase.php index a2384fd56230a1a54d1782a3742fd07ea3398645..357c0508546f7b7dc6e74d06e656a7feb34f9d1d 100644 --- a/typo3/sysext/extbase/Classes/Persistence/Generic/Qom/LowerCase.php +++ b/typo3/sysext/extbase/Classes/Persistence/Generic/Qom/LowerCase.php @@ -39,25 +39,43 @@ namespace TYPO3\CMS\Extbase\Persistence\Generic\Qom; class LowerCase implements LowerCaseInterface { /** - * @var DynamicOperandInterface + * @var PropertyValueInterface */ protected $operand; /** * Constructs this LowerCase instance * - * @param DynamicOperandInterface $operand + * @param PropertyValueInterface $operand */ - public function __construct(DynamicOperandInterface $operand) { + public function __construct(PropertyValueInterface $operand) { $this->operand = $operand; } /** * Gets the operand whose value is converted to a lower-case string. * - * @return DynamicOperandInterface the operand; non-null + * @return PropertyValueInterface the operand; non-null */ public function getOperand() { return $this->operand; } + + /** + * Gets the name of the selector against which to evaluate this operand. + * + * @return string the selector name; non-null + */ + public function getSelectorName() { + return $this->operand->getSelectorName(); + } + + /** + * Gets the name of the property. + * + * @return string the property name; non-null + */ + public function getPropertyName() { + return 'LOWER' . $this->operand->getPropertyName(); + } } diff --git a/typo3/sysext/extbase/Classes/Persistence/Generic/Qom/LowerCaseInterface.php b/typo3/sysext/extbase/Classes/Persistence/Generic/Qom/LowerCaseInterface.php index fdd9e8634fce7a119b60774e117107994f6c1171..2b19613d6c4dbbab4f2d4802142e80c445b70532 100644 --- a/typo3/sysext/extbase/Classes/Persistence/Generic/Qom/LowerCaseInterface.php +++ b/typo3/sysext/extbase/Classes/Persistence/Generic/Qom/LowerCaseInterface.php @@ -36,12 +36,12 @@ namespace TYPO3\CMS\Extbase\Persistence\Generic\Qom; * * If operand evaluates to null, the LowerCase operand also evaluates to null. */ -interface LowerCaseInterface extends DynamicOperandInterface { +interface LowerCaseInterface extends PropertyValueInterface { /** * Gets the operand whose value is converted to a lower-case string. * - * @return DynamicOperandInterface the operand; non-null + * @return PropertyValueInterface the operand; non-null */ public function getOperand(); } diff --git a/typo3/sysext/extbase/Classes/Persistence/Generic/Qom/QueryObjectModelFactory.php b/typo3/sysext/extbase/Classes/Persistence/Generic/Qom/QueryObjectModelFactory.php index 033de282e0487589d6e3d38d61735c33450ed57b..4449d0dde3850e8e20cfbefd1d1e964557729cd8 100644 --- a/typo3/sysext/extbase/Classes/Persistence/Generic/Qom/QueryObjectModelFactory.php +++ b/typo3/sysext/extbase/Classes/Persistence/Generic/Qom/QueryObjectModelFactory.php @@ -129,13 +129,13 @@ class QueryObjectModelFactory implements \TYPO3\CMS\Core\SingletonInterface { /** * Filters node-tuples based on the outcome of a binary operation. * - * @param DynamicOperandInterface $operand1 the first operand; non-null + * @param PropertyValueInterface $operand1 the first operand; non-null * @param string $operator the operator; one of QueryObjectModelConstants.JCR_OPERATOR_* * @param \TYPO3\CMS\Extbase\Persistence\Generic\Qom\StaticOperandInterface $operand2 the second operand; non-null * @return \TYPO3\CMS\Extbase\Persistence\Generic\Qom\ComparisonInterface the constraint; non-null * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception\RepositoryException if the operation otherwise fails */ - public function comparison(DynamicOperandInterface $operand1, $operator, $operand2) { + public function comparison(PropertyValueInterface $operand1, $operator, $operand2) { return $this->objectManager->get('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Qom\\Comparison', $operand1, $operator, $operand2); } @@ -154,7 +154,7 @@ class QueryObjectModelFactory implements \TYPO3\CMS\Core\SingletonInterface { /** * Evaluates to the lower-case string value (or values, if multi-valued) of an operand. * - * @param DynamicOperandInterface $operand the operand whose value is converted to a lower-case string; non-null + * @param PropertyValueInterface $operand the operand whose value is converted to a lower-case string; non-null * @return \TYPO3\CMS\Extbase\Persistence\Generic\Qom\LowerCaseInterface the operand; non-null * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception\RepositoryException if the operation otherwise fails */ @@ -165,7 +165,7 @@ class QueryObjectModelFactory implements \TYPO3\CMS\Core\SingletonInterface { /** * Evaluates to the upper-case string value (or values, if multi-valued) of an operand. * - * @param DynamicOperandInterface $operand the operand whose value is converted to a upper-case string; non-null + * @param PropertyValueInterface $operand the operand whose value is converted to a upper-case string; non-null * @return \TYPO3\CMS\Extbase\Persistence\Generic\Qom\UpperCaseInterface the operand; non-null * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception\RepositoryException if the operation otherwise fails */ diff --git a/typo3/sysext/extbase/Classes/Persistence/Generic/Qom/UpperCase.php b/typo3/sysext/extbase/Classes/Persistence/Generic/Qom/UpperCase.php index ca1aa55f26b9c0833fe2671a5a0092c9f9c0e728..4a94a0997ab1bdb5a101acb002de6bbfc86c4ce4 100644 --- a/typo3/sysext/extbase/Classes/Persistence/Generic/Qom/UpperCase.php +++ b/typo3/sysext/extbase/Classes/Persistence/Generic/Qom/UpperCase.php @@ -41,25 +41,43 @@ namespace TYPO3\CMS\Extbase\Persistence\Generic\Qom; class UpperCase implements UpperCaseInterface { /** - * @var DynamicOperandInterface + * @var PropertyValueInterface */ protected $operand; /** * Constructs this UpperCase instance * - * @param DynamicOperandInterface $operand + * @param PropertyValueInterface $operand */ - public function __construct(DynamicOperandInterface $operand) { + public function __construct(PropertyValueInterface $operand) { $this->operand = $operand; } /** * Gets the operand whose value is converted to a upper-case string. * - * @return DynamicOperandInterface the operand; non-null + * @return PropertyValueInterface the operand; non-null */ public function getOperand() { return $this->operand; } + + /** + * Gets the name of the selector against which to evaluate this operand. + * + * @return string the selector name; non-null + */ + public function getSelectorName() { + return $this->operand->getSelectorName(); + } + + /** + * Gets the name of the property. + * + * @return string the property name; non-null + */ + public function getPropertyName() { + return 'UPPER' . $this->operand->getPropertyName(); + } } diff --git a/typo3/sysext/extbase/Classes/Persistence/Generic/Qom/UpperCaseInterface.php b/typo3/sysext/extbase/Classes/Persistence/Generic/Qom/UpperCaseInterface.php index 2857dae61798287a0b2f9506ee53464bff71d16b..df5bb40a51714169a1a47c3002d9b041f68d0779 100644 --- a/typo3/sysext/extbase/Classes/Persistence/Generic/Qom/UpperCaseInterface.php +++ b/typo3/sysext/extbase/Classes/Persistence/Generic/Qom/UpperCaseInterface.php @@ -36,12 +36,12 @@ namespace TYPO3\CMS\Extbase\Persistence\Generic\Qom; * * If operand evaluates to null, the UpperCase operand also evaluates to null. */ -interface UpperCaseInterface extends DynamicOperandInterface { +interface UpperCaseInterface extends PropertyValueInterface { /** * Gets the operand whose value is converted to a upper-case string. * - * @return DynamicOperandInterface the operand; non-null + * @return PropertyValueInterface the operand; non-null */ public function getOperand(); } diff --git a/typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbQueryParser.php b/typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbQueryParser.php index 22af78c21fe23720eb93d97017dd03d691a5dd1a..1470fc95fc2b737affeb4871fbc638d2585578e2 100644 --- a/typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbQueryParser.php +++ b/typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbQueryParser.php @@ -345,7 +345,7 @@ class Typo3DbQueryParser { if ($hasValue === FALSE) { $sql['where'][] = '1<>1'; } else { - $this->parseDynamicOperand($comparison, $operator, $source, $sql); + $this->parseDynamicOperand($comparison, $source, $sql); } } elseif ($operator === QueryInterface::OPERATOR_CONTAINS) { if ($operand2 === NULL) { @@ -381,7 +381,7 @@ class Typo3DbQueryParser { } } } else { - $this->parseDynamicOperand($comparison, $operator, $source, $sql); + $this->parseDynamicOperand($comparison, $source, $sql); } } @@ -389,18 +389,37 @@ class Typo3DbQueryParser { * Parse a DynamicOperand into SQL and parameter arrays. * * @param Qom\ComparisonInterface $comparison - * @param string $operator One of the JCR_OPERATOR_* constants * @param Qom\SourceInterface $source The source * @param array &$sql The query parts - * @param string $valueFunction an optional SQL function to apply to the operand value * @return void */ - protected function parseDynamicOperand(Qom\ComparisonInterface $comparison, $operator, Qom\SourceInterface $source, array &$sql, $valueFunction = NULL) { + protected function parseDynamicOperand(Qom\ComparisonInterface $comparison, Qom\SourceInterface $source, array &$sql) { + $operator = $this->resolveOperator($comparison->getOperator()); $operand = $comparison->getOperand1(); + + $constraintSQL = $this->parseOperand($operand, $source, $sql) . ' ' . $operator . ' '; + + $parameterIdentifier = $this->normalizeParameterIdentifier($comparison->getParameterIdentifier()); + if ($operator === 'IN') { + $parameterIdentifier = '(' . $parameterIdentifier . ')'; + } + $constraintSQL .= $parameterIdentifier; + + $sql['where'][] = $constraintSQL; + } + + /** + * @param Qom\DynamicOperandInterface $operand + * @param Qom\SourceInterface $source The source + * @param array &$sql The query parts + * @return string + * @throws \InvalidArgumentException + */ + protected function parseOperand(Qom\DynamicOperandInterface $operand, Qom\SourceInterface $source, array &$sql) { if ($operand instanceof Qom\LowerCaseInterface) { - $this->parseDynamicOperand($operand->getOperand(), $operator, $source, $sql, 'LOWER'); + $constraintSQL = 'LOWER(' . $this->parseOperand($operand->getOperand(), $source, $sql) . ')'; } elseif ($operand instanceof Qom\UpperCaseInterface) { - $this->parseDynamicOperand($operand->getOperand(), $operator, $source, $sql, 'UPPER'); + $constraintSQL = 'UPPER(' . $this->parseOperand($operand->getOperand(), $source, $sql) . ')'; } elseif ($operand instanceof Qom\PropertyValueInterface) { $propertyName = $operand->getPropertyName(); $className = ''; @@ -415,22 +434,11 @@ class Typo3DbQueryParser { $tableName = $source->getJoinCondition()->getSelector1Name(); } $columnName = $this->dataMapper->convertPropertyNameToColumnName($propertyName, $className); - $operator = $this->resolveOperator($operator); - $constraintSQL = ''; - if ($valueFunction === NULL) { - $constraintSQL .= (!empty($tableName) ? $tableName . '.' : '') . $columnName . ' ' . $operator . ' '; - } else { - $constraintSQL .= $valueFunction . '(' . (!empty($tableName) ? $tableName . '.' : '') . $columnName . ') ' . $operator . ' '; - } - - if ($operator === 'LIKE' || $operator === 'IN') { - $constraintSQL .= '(' . $this->normalizeParameterIdentifier($comparison->getParameterIdentifier()) . ')'; - } else { - $constraintSQL .= $this->normalizeParameterIdentifier($comparison->getParameterIdentifier()); - } - - $sql['where'][] = $constraintSQL; + $constraintSQL = (!empty($tableName) ? $tableName . '.' : '') . $columnName; + } else { + throw new \InvalidArgumentException('Given operand has invalid type "' . get_class($operand) . '".', 1395710211); } + return $constraintSQL; } /** diff --git a/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/posts.xml b/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/posts.xml index ed86e29d01369e89023be7d60576a0147ec0a0e6..b00872a3026b8bc2f50182d28648fdb1f1af1c6b 100644 --- a/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/posts.xml +++ b/typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/posts.xml @@ -96,7 +96,7 @@ <pid>0</pid> <blog>2</blog> <tags>0</tags> - <title>Post11</title> + <title>post1</title> <sorting>11</sorting> <deleted>0</deleted> </tx_blogexample_domain_model_post> diff --git a/typo3/sysext/extbase/Tests/Functional/Persistence/OperatorTest.php b/typo3/sysext/extbase/Tests/Functional/Persistence/OperatorTest.php index 5d5d8b7b858502cafb33dcb15dd8f38a13df4224..b59d2b2edfaaa2bf1b5bbf9b7404064d9a4873c6 100644 --- a/typo3/sysext/extbase/Tests/Functional/Persistence/OperatorTest.php +++ b/typo3/sysext/extbase/Tests/Functional/Persistence/OperatorTest.php @@ -25,7 +25,6 @@ namespace TYPO3\CMS\Extbase\Tests\Functional\Persistence; ***************************************************************/ use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Extbase\Persistence\ObjectStorage; class OperatorTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase { @@ -84,4 +83,17 @@ class OperatorTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase { $this->assertSame(0, $query->count()); } + + /** + * @test + */ + public function equalsCorrectlyHandlesCaseSensivity() { + $query = $this->postRepository->createQuery(); + + $query->matching( + $query->equals('title', 'PoSt1', FALSE) + ); + + $this->assertSame(2, $query->count()); + } }