Beispiel #1
0
 /**
  * Checks if a Value Object equal to the given Object exists in the database
  *
  * @param AbstractValueObject $object The Value Object
  * @return mixed The matching uid if an object was found, else FALSE
  * @throws SqlErrorException
  */
 public function getUidOfAlreadyPersistedValueObject(AbstractValueObject $object)
 {
     $dataMap = $this->dataMapper->getDataMap(get_class($object));
     $tableName = $dataMap->getTableName();
     $queryBuilder = $this->connectionPool->getQueryBuilderForTable($tableName);
     if ($this->environmentService->isEnvironmentInFrontendMode()) {
         $queryBuilder->setRestrictions(GeneralUtility::makeInstance(FrontendRestrictionContainer::class));
     }
     $whereClause = [];
     // loop over all properties of the object to exactly set the values of each database field
     $properties = $object->_getProperties();
     foreach ($properties as $propertyName => $propertyValue) {
         // @todo 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') {
             $fieldName = $dataMap->getColumnMap($propertyName)->getColumnName();
             if ($propertyValue === null) {
                 $whereClause[] = $queryBuilder->expr()->isNull($fieldName);
             } else {
                 $whereClause[] = $queryBuilder->expr()->eq($fieldName, $queryBuilder->createNamedParameter($this->dataMapper->getPlainValue($propertyValue)));
             }
         }
     }
     $queryBuilder->select('uid')->from($tableName)->where(...$whereClause);
     try {
         $uid = (int) $queryBuilder->execute()->fetchColumn(0);
         if ($uid > 0) {
             return $uid;
         } else {
             return false;
         }
     } catch (DBALException $e) {
         throw new SqlErrorException($e->getPrevious()->getMessage(), 1470231748);
     }
 }
 /**
  * Parse a Comparison into SQL and parameter arrays.
  *
  * @param Qom\ComparisonInterface $comparison The comparison to parse
  * @param Qom\SourceInterface $source The source
  * @param array &$sql SQL query parts to add to
  * @throws \RuntimeException
  * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception\RepositoryException
  * @return void
  */
 protected function parseComparison(Qom\ComparisonInterface $comparison, Qom\SourceInterface $source, array &$sql)
 {
     $parameterIdentifier = $this->normalizeParameterIdentifier($comparison->getParameterIdentifier());
     $operator = $comparison->getOperator();
     $operand2 = $comparison->getOperand2();
     if ($operator === QueryInterface::OPERATOR_IN) {
         $hasValue = false;
         foreach ($operand2 as $value) {
             $value = $this->dataMapper->getPlainValue($value);
             if ($value !== null) {
                 $parameters[] = $value;
                 $hasValue = true;
             }
         }
         if ($hasValue === false) {
             $sql['where'][] = '1<>1';
         } else {
             $this->parseDynamicOperand($comparison, $source, $sql);
         }
     } elseif ($operator === QueryInterface::OPERATOR_CONTAINS) {
         if ($operand2 === null) {
             $sql['where'][] = '1<>1';
         } else {
             if (!$source instanceof Qom\SelectorInterface) {
                 throw new \RuntimeException('Source is not of type "SelectorInterface"', 1395362539);
             }
             $className = $source->getNodeTypeName();
             $tableName = $this->dataMapper->convertClassNameToTableName($className);
             $operand1 = $comparison->getOperand1();
             $propertyName = $operand1->getPropertyName();
             $fullPropertyPath = '';
             while (strpos($propertyName, '.') !== false) {
                 $this->addUnionStatement($className, $tableName, $propertyName, $sql, $fullPropertyPath);
             }
             $columnName = $this->dataMapper->convertPropertyNameToColumnName($propertyName, $className);
             $dataMap = $this->dataMapper->getDataMap($className);
             $columnMap = $dataMap->getColumnMap($propertyName);
             $typeOfRelation = $columnMap instanceof ColumnMap ? $columnMap->getTypeOfRelation() : null;
             if ($typeOfRelation === ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) {
                 $relationTableName = $columnMap->getRelationTableName();
                 $additionalWhereForMatchFields = $this->getAdditionalMatchFieldsStatement($columnMap, $relationTableName, $relationTableName);
                 $sql['where'][] = $tableName . '.uid IN (SELECT ' . $columnMap->getParentKeyFieldName() . ' FROM ' . $relationTableName . ' WHERE ' . $columnMap->getChildKeyFieldName() . '=' . $parameterIdentifier . $additionalWhereForMatchFields . ')';
             } elseif ($typeOfRelation === 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=' . $parameterIdentifier . ')';
                 } else {
                     $sql['where'][] = 'FIND_IN_SET(' . $parameterIdentifier . ', ' . $tableName . '.' . $columnName . ')';
                 }
             } else {
                 throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\RepositoryException('Unsupported or non-existing property name "' . $propertyName . '" used in relation matching.', 1327065745);
             }
         }
     } else {
         $this->parseDynamicOperand($comparison, $source, $sql);
     }
 }
Beispiel #3
0
 /**
  * Persists the given object.
  *
  * @param \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $object The object to be inserted
  * @return void
  */
 protected function persistObject(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $object)
 {
     if (isset($this->visitedDuringPersistence[$object])) {
         return;
     }
     $row = array();
     $queue = array();
     $dataMap = $this->dataMapper->getDataMap(get_class($object));
     $properties = $object->_getProperties();
     foreach ($properties as $propertyName => $propertyValue) {
         if (!$dataMap->isPersistableProperty($propertyName) || $this->propertyValueIsLazyLoaded($propertyValue)) {
             continue;
         }
         $columnMap = $dataMap->getColumnMap($propertyName);
         if ($propertyValue instanceof \TYPO3\CMS\Extbase\Persistence\ObjectStorage) {
             $cleanProperty = $object->_getCleanProperty($propertyName);
             // objectstorage needs to be persisted if the object is new, the objectstorge is dirty, meaning it has
             // been changed after initial build, or a empty objectstorge is present and the cleanstate objectstorage
             // has childelements, meaning all elements should been removed from the objectstorage
             if ($object->_isNew() || $propertyValue->_isDirty() || $propertyValue->count() == 0 && $cleanProperty && $cleanProperty->count() > 0) {
                 $this->persistObjectStorage($propertyValue, $object, $propertyName, $row);
                 $propertyValue->_memorizeCleanState();
             }
             foreach ($propertyValue as $containedObject) {
                 if ($containedObject instanceof \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface) {
                     $queue[] = $containedObject;
                 }
             }
         } elseif ($propertyValue instanceof \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface && $object instanceof ObjectMonitoringInterface) {
             if ($object->_isDirty($propertyName)) {
                 if ($propertyValue->_isNew()) {
                     $this->insertObject($propertyValue, $object, $propertyName);
                 }
                 // Check explicitly for NULL, as getPlainValue would convert this to 'NULL'
                 $row[$columnMap->getColumnName()] = $propertyValue !== NULL ? $this->dataMapper->getPlainValue($propertyValue) : NULL;
             }
             $queue[] = $propertyValue;
         } elseif ($object->_isNew() || $object->_isDirty($propertyName)) {
             $row[$columnMap->getColumnName()] = $this->dataMapper->getPlainValue($propertyValue, $columnMap);
         }
     }
     if (!empty($row)) {
         $this->updateObject($object, $row);
         $object->_memorizeCleanState();
     }
     $this->visitedDuringPersistence[$object] = $object->getUid();
     foreach ($queue as $queuedObject) {
         $this->persistObject($queuedObject);
     }
     $this->emitAfterPersistObjectSignal($object);
 }
Beispiel #4
0
 /**
  * Checks if a Value Object equal to the given Object exists in the data base
  *
  * @param \TYPO3\CMS\Extbase\DomainObject\AbstractValueObject $object The Value Object
  * @return mixed The matching uid if an object was found, else FALSE
  * @todo this is the last monster in this persistence series. refactor!
  */
 public function getUidOfAlreadyPersistedValueObject(\TYPO3\CMS\Extbase\DomainObject\AbstractValueObject $object)
 {
     $fields = array();
     $parameters = array();
     $dataMap = $this->dataMapper->getDataMap(get_class($object));
     $properties = $object->_getProperties();
     foreach ($properties as $propertyName => $propertyValue) {
         // @todo 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') {
             if ($propertyValue === NULL) {
                 $fields[] = $dataMap->getColumnMap($propertyName)->getColumnName() . ' IS NULL';
             } else {
                 $fields[] = $dataMap->getColumnMap($propertyName)->getColumnName() . '=?';
                 $parameters[] = $this->dataMapper->getPlainValue($propertyValue);
             }
         }
     }
     $sql = array();
     $sql['additionalWhereClause'] = array();
     $tableName = $dataMap->getTableName();
     $this->addVisibilityConstraintStatement(new \TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings(), $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, $tableName);
     // debug($statement,-2);
     $res = $this->databaseHandle->sql_query($statement);
     $this->checkSqlErrors($statement);
     $row = $this->databaseHandle->sql_fetch_assoc($res);
     if ($row !== FALSE) {
         return (int) $row['uid'];
     } else {
         return FALSE;
     }
 }
Beispiel #5
0
 /**
  * Inserts an object in the storage backend
  *
  * @param \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $object The object to be insterted in the storage
  * @param \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject The parentobject.
  * @param string $parentPropertyName
  * @return void
  */
 protected function insertObject(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $object, \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $parentObject = null, $parentPropertyName = '')
 {
     if ($object instanceof \TYPO3\CMS\Extbase\DomainObject\AbstractValueObject) {
         $result = $this->getUidOfAlreadyPersistedValueObject($object);
         if ($result !== false) {
             $object->_setProperty('uid', (int) $result);
             return;
         }
     }
     $dataMap = $this->dataMapper->getDataMap(get_class($object));
     $row = array();
     $properties = $object->_getProperties();
     foreach ($properties as $propertyName => $propertyValue) {
         if (!$dataMap->isPersistableProperty($propertyName) || $this->propertyValueIsLazyLoaded($propertyValue)) {
             continue;
         }
         $columnMap = $dataMap->getColumnMap($propertyName);
         if ($columnMap->getTypeOfRelation() === ColumnMap::RELATION_HAS_ONE) {
             $row[$columnMap->getColumnName()] = 0;
         } elseif ($columnMap->getTypeOfRelation() !== ColumnMap::RELATION_NONE) {
             if ($columnMap->getParentKeyFieldName() === null) {
                 // CSV type relation
                 $row[$columnMap->getColumnName()] = '';
             } else {
                 // MM type relation
                 $row[$columnMap->getColumnName()] = 0;
             }
         } elseif ($propertyValue !== null) {
             $row[$columnMap->getColumnName()] = $this->dataMapper->getPlainValue($propertyValue);
         }
     }
     $this->addCommonFieldsToRow($object, $row);
     if ($dataMap->getLanguageIdColumnName() !== null && $object->_getProperty('_languageUid') === null) {
         $row[$dataMap->getLanguageIdColumnName()] = 0;
         $object->_setProperty('_languageUid', 0);
     }
     if ($dataMap->getTranslationOriginColumnName() !== null) {
         $row[$dataMap->getTranslationOriginColumnName()] = 0;
     }
     if ($dataMap->getTranslationOriginDiffSourceName() !== null) {
         $row[$dataMap->getTranslationOriginDiffSourceName()] = '';
     }
     if ($parentObject !== null && $parentPropertyName) {
         $parentColumnDataMap = $this->dataMapper->getDataMap(get_class($parentObject))->getColumnMap($parentPropertyName);
         $relationTableMatchFields = $parentColumnDataMap->getRelationTableMatchFields();
         if (is_array($relationTableMatchFields)) {
             $row = array_merge($relationTableMatchFields, $row);
         }
         if ($parentColumnDataMap->getParentKeyFieldName() !== null) {
             $row[$parentColumnDataMap->getParentKeyFieldName()] = (int) $parentObject->getUid();
         }
     }
     $uid = $this->storageBackend->addRow($dataMap->getTableName(), $row);
     $object->_setProperty('uid', (int) $uid);
     $object->setPid((int) $row['pid']);
     if ((int) $uid >= 1) {
         $this->emitAfterInsertObjectSignal($object);
     }
     $frameworkConfiguration = $this->configurationManager->getConfiguration(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
     if ($frameworkConfiguration['persistence']['updateReferenceIndex'] === '1') {
         $this->referenceIndex->updateRefIndexTable($dataMap->getTableName(), $uid);
     }
     $this->session->registerObject($object, $uid);
     if ((int) $uid >= 1) {
         $this->emitEndInsertObjectSignal($object);
     }
 }
 /**
  * @test
  */
 public function getPlainValueCallsGetUidOnDomainObjectInterfaceInput()
 {
     $dataMapper = new DataMapper();
     $input = $this->getMock(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface::class, array(), array(), '', false);
     $input->expects($this->once())->method('getUid')->will($this->returnValue(23));
     $this->assertSame(23, $dataMapper->getPlainValue($input));
 }
Beispiel #7
0
 /**
  * Parse a DynamicOperand into SQL and parameter arrays.
  *
  * @param Qom\ComparisonInterface $comparison
  * @param Qom\SourceInterface $source The source
  * @return string
  * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception
  */
 protected function parseDynamicOperand(Qom\ComparisonInterface $comparison, Qom\SourceInterface $source)
 {
     $value = $comparison->getOperand2();
     $fieldName = $this->parseOperand($comparison->getOperand1(), $source);
     $expr = null;
     $exprBuilder = $this->queryBuilder->expr();
     switch ($comparison->getOperator()) {
         case QueryInterface::OPERATOR_IN:
             $hasValue = false;
             $plainValues = [];
             foreach ($value as $singleValue) {
                 $plainValue = $this->dataMapper->getPlainValue($singleValue);
                 if ($plainValue !== null) {
                     $hasValue = true;
                     $plainValues[] = $plainValue;
                 }
             }
             if ($hasValue) {
                 $expr = $exprBuilder->comparison($fieldName, 'IN', '(' . implode(', ', $plainValues) . ')');
             } else {
                 $expr = '1<>1';
             }
             break;
         case QueryInterface::OPERATOR_EQUAL_TO:
             if ($value === null) {
                 $expr = $fieldName . ' IS NULL';
             } else {
                 $value = $this->queryBuilder->createNamedParameter($this->dataMapper->getPlainValue($value));
                 $expr = $exprBuilder->comparison($fieldName, $exprBuilder::EQ, $value);
             }
             break;
         case QueryInterface::OPERATOR_EQUAL_TO_NULL:
             $expr = $fieldName . ' IS NULL';
             break;
         case QueryInterface::OPERATOR_NOT_EQUAL_TO:
             if ($value === null) {
                 $expr = $fieldName . ' IS NOT NULL';
             } else {
                 $value = $this->queryBuilder->createNamedParameter($this->dataMapper->getPlainValue($value));
                 $expr = $exprBuilder->comparison($fieldName, $exprBuilder::NEQ, $value);
             }
             break;
         case QueryInterface::OPERATOR_NOT_EQUAL_TO_NULL:
             $expr = $fieldName . ' IS NOT NULL';
             break;
         case QueryInterface::OPERATOR_LESS_THAN:
             $value = $this->queryBuilder->createNamedParameter($this->dataMapper->getPlainValue($value), \PDO::PARAM_INT);
             $expr = $exprBuilder->comparison($fieldName, $exprBuilder::LT, $value);
             break;
         case QueryInterface::OPERATOR_LESS_THAN_OR_EQUAL_TO:
             $value = $this->queryBuilder->createNamedParameter($this->dataMapper->getPlainValue($value), \PDO::PARAM_INT);
             $expr = $exprBuilder->comparison($fieldName, $exprBuilder::LTE, $value);
             break;
         case QueryInterface::OPERATOR_GREATER_THAN:
             $value = $this->queryBuilder->createNamedParameter($this->dataMapper->getPlainValue($value), \PDO::PARAM_INT);
             $expr = $exprBuilder->comparison($fieldName, $exprBuilder::GT, $value);
             break;
         case QueryInterface::OPERATOR_GREATER_THAN_OR_EQUAL_TO:
             $value = $this->queryBuilder->createNamedParameter($this->dataMapper->getPlainValue($value), \PDO::PARAM_INT);
             $expr = $exprBuilder->comparison($fieldName, $exprBuilder::GTE, $value);
             break;
         case QueryInterface::OPERATOR_LIKE:
             $value = $this->queryBuilder->createNamedParameter($this->dataMapper->getPlainValue($value));
             $expr = $exprBuilder->comparison($fieldName, 'LIKE', $value);
             break;
         default:
             throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception('Unsupported operator encountered.', 1242816073);
     }
     return $expr;
 }