Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- namespace Vendor\Extension\Persistence\Generic\Storage;
- /**
- * @author Philipp Wrann <[email protected]>
- * @package TYPO3.CMS
- */
- class PatchedTypo3DbBackend extends \TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbBackend {
- /**
- * Here we added the possibility of makeing joins on the same table,
- * This is important to filter regionalobjects for their location
- * as locations as well as regionalobjects are stored in the same table.
- *
- * @param string &$className
- * @param string &$tableName
- * @param array &$propertyPath
- * @param array &$sql
- * @param string &$parent
- * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception
- * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception\InvalidRelationConfigurationException
- * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception\MissingColumnMapException
- */
- protected function addUnionStatement(&$className, &$tableName, &$propertyPath, array &$sql, &$parent) {
- $explodedPropertyPath = explode('.', $propertyPath, 2);
- $propertyName = $explodedPropertyPath[0];
- $columnName = $this->dataMapper->convertPropertyNameToColumnName($propertyName, $className);
- $tableName = $this->dataMapper->convertClassNameToTableName($className);
- $columnMap = $this->dataMapper->getDataMap($className)->getColumnMap($propertyName);
- if ($columnMap === NULL) {
- throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\MissingColumnMapException('The ColumnMap for property "' . $propertyName . '" of class "' . $className . '" is missing.', 1355142232);
- }
- // MODIFICATION START
- $parentKeyFieldName = $columnMap->getParentKeyFieldName();
- $childTableName = $columnMap->getChildTableName();
- $realTableName = $childTableName;
- $alias = (isset($sql['unions'][$propertyName])) ? $propertyName.uniqid() : $propertyName;
- $parent = ($parent=='') ? $tableName : $parent;
- if ($childTableName === NULL) {
- throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\InvalidRelationConfigurationException('The relation information for property "' . $propertyName . '" of class "' . $className . '" is missing.', 1353170925);
- }
- if ($columnMap->getTypeOfRelation() === \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_ONE) {
- if (isset($parentKeyFieldName)) {
- $sql['unions'][$alias] = 'LEFT JOIN ' . $realTableName . ' AS ' . $alias . ' ON ' . $parent . '.uid=' . $alias . '.' . $parentKeyFieldName;
- } else {
- $sql['unions'][$alias] = 'LEFT JOIN ' . $realTableName . ' AS '. $alias . ' ON ' . $parent . '.' . $columnName . '=' . $alias . '.uid';
- }
- $className = $this->dataMapper->getType($className, $propertyName);
- } elseif ($columnMap->getTypeOfRelation() === \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_MANY) {
- if (isset($parentKeyFieldName)) {
- $sql['unions'][$alias] = 'LEFT JOIN ' . $realTableName . ' AS ' . $alias . ' ON ' . $parent . '.uid=' . $alias . '.' . $parentKeyFieldName;
- } else {
- // @todo !!!needs tesing!!!
- $onStatement = '(FIND_IN_SET(' . $childTableName . '.uid, ' . $tableName . '.' . $columnName . '))';
- $sql['unions'][$alias] = 'LEFT JOIN ' . $childTableName . ' ON ' . $onStatement;
- }
- $className = $this->dataMapper->getType($className, $propertyName);
- } elseif ($columnMap->getTypeOfRelation() === \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) {
- $relationTableName = $columnMap->getRelationTableName();
- // @todo !!!needs tesing!!!
- $sql['unions'][$relationTableName] = 'LEFT JOIN ' . $relationTableName . ' ON ' . $parent . '.uid=' . $relationTableName . '.' . $columnMap->getParentKeyFieldName();
- $sql['unions'][$alias] = 'LEFT JOIN ' . $childTableName . ' ON ' . $relationTableName . '.' . $columnMap->getChildKeyFieldName() . '=' . $childTableName . '.uid';
- $className = $this->dataMapper->getType($className, $propertyName);
- } else {
- throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception('Could not determine type of relation.', 1252502725);
- }
- $parent = $alias;
- $sql['keywords']['distinct'] = 'DISTINCT';
- $propertyPath = $explodedPropertyPath[1];
- $tableName = $alias;
- }
- /**
- * Parse a DynamicOperand into SQL and parameter arrays.
- *
- * @param \TYPO3\CMS\Extbase\Persistence\Generic\Qom\DynamicOperandInterface $operand
- * @param string $operator One of the JCR_OPERATOR_* constants
- * @param \TYPO3\CMS\Extbase\Persistence\Generic\Qom\SourceInterface $source The source
- * @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
- * @param null $operand2
- * @return void
- */
- protected function parseDynamicOperand(\TYPO3\CMS\Extbase\Persistence\Generic\Qom\DynamicOperandInterface $operand, $operator, \TYPO3\CMS\Extbase\Persistence\Generic\Qom\SourceInterface $source, array &$sql, array &$parameters, $valueFunction = NULL, $operand2 = NULL) {
- if ($operand instanceof \TYPO3\CMS\Extbase\Persistence\Generic\Qom\LowerCaseInterface) {
- $this->parseDynamicOperand($operand->getOperand(), $operator, $source, $sql, $parameters, 'LOWER');
- } elseif ($operand instanceof \TYPO3\CMS\Extbase\Persistence\Generic\Qom\UpperCaseInterface) {
- $this->parseDynamicOperand($operand->getOperand(), $operator, $source, $sql, $parameters, 'UPPER');
- } elseif ($operand instanceof \TYPO3\CMS\Extbase\Persistence\Generic\Qom\PropertyValueInterface) {
- $propertyName = $operand->getPropertyName();
- if ($source instanceof \TYPO3\CMS\Extbase\Persistence\Generic\Qom\SelectorInterface) {
- // FIXME Only necessary to differ from Join
- $className = $source->getNodeTypeName();
- $tableName = $this->dataMapper->convertClassNameToTableName($className);
- $parent = '';
- while (strpos($propertyName, '.') !== FALSE) {
- $this->addUnionStatement($className, $tableName, $propertyName, $sql, $parent);
- }
- } elseif ($source instanceof \TYPO3\CMS\Extbase\Persistence\Generic\Qom\JoinInterface) {
- $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 . ' ?';
- }
- $sql['where'][] = $constraintSQL;
- }
- }
- /**
- * Parse a Comparison into SQL and parameter arrays.
- *
- * @param \TYPO3\CMS\Extbase\Persistence\Generic\Qom\ComparisonInterface $comparison The comparison to parse
- * @param \TYPO3\CMS\Extbase\Persistence\Generic\Qom\SourceInterface $source The source
- * @param array &$sql SQL query parts to add to
- * @param array &$parameters Parameters to bind to the SQL
- * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception\RepositoryException
- * @return void
- */
- protected function parseComparison(\TYPO3\CMS\Extbase\Persistence\Generic\Qom\ComparisonInterface $comparison, \TYPO3\CMS\Extbase\Persistence\Generic\Qom\SourceInterface $source, array &$sql, array &$parameters) {
- $operand1 = $comparison->getOperand1();
- $operator = $comparison->getOperator();
- $operand2 = $comparison->getOperand2();
- if ($operator === \TYPO3\CMS\Extbase\Persistence\QueryInterface::OPERATOR_IN) {
- $items = array();
- $hasValue = FALSE;
- foreach ($operand2 as $value) {
- $value = $this->getPlainValue($value);
- if ($value !== NULL) {
- $items[] = $value;
- $hasValue = TRUE;
- }
- }
- if ($hasValue === FALSE) {
- $sql['where'][] = '1<>1';
- } else {
- $this->parseDynamicOperand($operand1, $operator, $source, $sql, $parameters, NULL, $operand2);
- $parameters[] = $items;
- }
- } elseif ($operator === \TYPO3\CMS\Extbase\Persistence\QueryInterface::OPERATOR_CONTAINS) {
- if ($operand2 === NULL) {
- $sql['where'][] = '1<>1';
- } else {
- $className = $source->getNodeTypeName();
- $tableName = $this->dataMapper->convertClassNameToTableName($className);
- $propertyName = $operand1->getPropertyName();
- $parent = '';
- while (strpos($propertyName, '.') !== FALSE) {
- $this->addUnionStatement($className, $tableName, $propertyName, $sql, $parent);
- }
- $columnName = $this->dataMapper->convertPropertyNameToColumnName($propertyName, $className);
- $dataMap = $this->dataMapper->getDataMap($className);
- $columnMap = $dataMap->getColumnMap($propertyName);
- $typeOfRelation = $columnMap instanceof \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap ? $columnMap->getTypeOfRelation() : NULL;
- if ($typeOfRelation === \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) {
- // $relationTableName = $columnMap->getRelationTableName();
- // $sql['where'][] = $tableName . '.uid IN (SELECT ' . $columnMap->getParentKeyFieldName() . ' FROM ' . $relationTableName . ' WHERE ' . $columnMap->getChildKeyFieldName() . '=?)';
- // MODIFICATION START
- $relationTableName = $columnMap->getRelationTableName();
- if($matchFields = $columnMap->getRelationTableMatchFields()) {
- $matchFieldsQuery = '';
- foreach ($matchFields as $matchField => $matchValue) {
- $matchFieldsQuery .= ' '.$matchField.' = \''.$matchValue.'\' AND ';
- }
- }
- $sql['where'][] = $tableName . '.uid IN (SELECT ' . $columnMap->getParentKeyFieldName() . ' FROM ' . $relationTableName . ' WHERE ' . $matchFieldsQuery . $columnMap->getChildKeyFieldName() . '=?)';
- $parameters[] = intval($this->getPlainValue($operand2));
- // MODIFICATION END
- } elseif ($typeOfRelation === \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_MANY) {
- $parentKeyFieldName = $columnMap->getParentKeyFieldName();
- if (isset($parentKeyFieldName)) {
- $childTableName = $columnMap->getChildTableName();
- $sql['where'][] = $tableName . '.uid=(SELECT ' . $childTableName . '.' . $parentKeyFieldName . ' FROM ' . $childTableName . ' WHERE ' . $childTableName . '.uid=?)';
- $parameters[] = intval($this->getPlainValue($operand2));
- } else {
- $sql['where'][] = 'FIND_IN_SET(?,' . $tableName . '.' . $columnName . ')';
- $parameters[] = intval($this->getPlainValue($operand2));
- }
- } else {
- throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\RepositoryException('Unsupported or non-existing property name "' . $propertyName . '" used in relation matching.', 1327065745);
- }
- }
- } else {
- if ($operand2 === NULL) {
- if ($operator === \TYPO3\CMS\Extbase\Persistence\QueryInterface::OPERATOR_EQUAL_TO) {
- $operator = self::OPERATOR_EQUAL_TO_NULL;
- } elseif ($operator === \TYPO3\CMS\Extbase\Persistence\QueryInterface::OPERATOR_NOT_EQUAL_TO) {
- $operator = self::OPERATOR_NOT_EQUAL_TO_NULL;
- }
- }
- $this->parseDynamicOperand($operand1, $operator, $source, $sql, $parameters);
- $parameters[] = $this->getPlainValue($operand2);
- }
- }
- /**
- * Transforms orderings into SQL.
- *
- * @param array $orderings An array of orderings (Tx_Extbase_Persistence_QOM_Ordering)
- * @param \TYPO3\CMS\Extbase\Persistence\Generic\Qom\SourceInterface $source The source
- * @param array &$sql The query parts
- * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnsupportedOrderException
- * @return void
- */
- protected function parseOrderings(array $orderings, \TYPO3\CMS\Extbase\Persistence\Generic\Qom\SourceInterface $source, array &$sql) {
- foreach ($orderings as $propertyName => $order) {
- switch ($order) {
- case \TYPO3\CMS\Extbase\Persistence\Generic\Qom\QueryObjectModelConstantsInterface::JCR_ORDER_ASCENDING:
- case \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING:
- $order = 'ASC';
- break;
- case \TYPO3\CMS\Extbase\Persistence\Generic\Qom\QueryObjectModelConstantsInterface::JCR_ORDER_DESCENDING:
- case \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING:
- $order = 'DESC';
- break;
- default:
- throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnsupportedOrderException('Unsupported order encountered.', 1242816074);
- }
- $className = '';
- $tableName = '';
- /**
- * MODIFICATION START
- * This way we enable the use of a function inside ordering
- * this is mysql specific but its needed for our listMode Priority feature
- * This way we can get a ordered list but put some specific objects on top of the list
- */
- if (stripos($propertyName,'FIELD(') !== FALSE) {
- $parts = explode(',',str_replace(')','',$propertyName));
- $property = str_ireplace('FIELD(','',array_shift($parts));
- $values = array_filter(array_filter($parts,function($value){
- return !preg_match_all("/[^\w]/",$value);
- }));
- $className = $source->getNodeTypeName();
- $tableName = $this->dataMapper->convertClassNameToTableName($className);
- $columnName = $this->dataMapper->convertPropertyNameToColumnName($property, $className);
- $fieldString = 'FIELD('.$tableName.'.'.$columnName.','.implode(',',$values).')';
- $sql['orderings'][] = $fieldString. ' ' . $order;
- } else {
- /**
- * MODIFICATION END
- */
- if ($source instanceof \TYPO3\CMS\Extbase\Persistence\Generic\Qom\SelectorInterface) {
- $className = $source->getNodeTypeName();
- $tableName = $this->dataMapper->convertClassNameToTableName($className);
- $parent = '';
- while (strpos($propertyName, '.') !== FALSE) {
- $this->addUnionStatement($className, $tableName, $propertyName, $sql, $parent);
- }
- } elseif ($source instanceof \TYPO3\CMS\Extbase\Persistence\Generic\Qom\JoinInterface) {
- $tableName = $source->getLeft()->getSelectorName();
- }
- $columnName = $this->dataMapper->convertPropertyNameToColumnName($propertyName, $className);
- if (strlen($tableName) > 0) {
- $sql['orderings'][] = $tableName . '.' . $columnName . ' ' . $order;
- } else {
- $sql['orderings'][] = $columnName . ' ' . $order;
- }
- }
- }
- }
- }
- ?>
Advertisement
Add Comment
Please, Sign In to add comment