protected function setUp() { $this->dataMap = $this->getMock(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMap::class, array('getIsStatic', 'getRootLevel'), array('Vendor\\Ext\\Domain\\Model\\ClubMate', 'tx_ext_domain_model_clubmate')); $this->queryFactory = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Persistence\Generic\QueryFactory::class, array('dummy')); $this->queryFactory->_set('configurationManager', $this->getMock(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::class)); $this->dataMapper = $this->getMock(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper::class, array('getDataMap', 'convertClassNameToTableName')); $this->dataMapper->expects($this->any())->method('getDataMap')->will($this->returnValue($this->dataMap)); $this->queryFactory->_set('dataMapper', $this->dataMapper); }
/** * Returns cache tag parts for the given object if known. * * @param $object * @return array */ protected function identifyCacheTagForObject($object) { $cacheTags = []; if ($object instanceof \TYPO3\CMS\Extbase\DomainObject\AbstractDomainObject) { $tableName = $this->dataMapper->convertClassNameToTableName(get_class($object)); $recordUid = $object->getUid(); $cacheTags[] = $tableName; $cacheTags[] = $tableName . '_' . $recordUid; } elseif ($object instanceof \TYPO3\CMS\Extbase\Persistence\QueryResultInterface) { $cacheTags[] = $this->dataMapper->convertClassNameToTableName($object->getQuery()->getType()); } return $cacheTags; }
/** * Sets up this test case * * @return void */ protected function setUp() { $this->mockPersistenceManager = $this->getMock(\TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface::class); $this->mockPersistenceManager->expects($this->any())->method('getObjectDataByQuery')->will($this->returnValue(array('one', 'two'))); $this->mockPersistenceManager->expects($this->any())->method('getObjectCountByQuery')->will($this->returnValue(2)); $this->mockDataMapper = $this->getMock(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper::class); $this->mockQuery = $this->getMock(\TYPO3\CMS\Extbase\Persistence\QueryInterface::class); $this->queryResult = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Persistence\Generic\QueryResult::class, array('dummy'), array($this->mockQuery)); $this->queryResult->_set('persistenceManager', $this->mockPersistenceManager); $this->queryResult->_set('dataMapper', $this->mockDataMapper); $this->sampleResult = array(array('foo' => 'Foo1', 'bar' => 'Bar1'), array('foo' => 'Foo2', 'bar' => 'Bar2')); $this->mockDataMapper->expects($this->any())->method('map')->will($this->returnValue($this->sampleResult)); }
/** * Creates a query object working on the given class name * * @param string $className The class name * @return \TYPO3\CMS\Extbase\Persistence\QueryInterface * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception */ public function create($className) { $query = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\QueryInterface::class, $className); $querySettings = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface::class); $dataMap = $this->dataMapper->getDataMap($className); if ($dataMap->getIsStatic() || $dataMap->getRootLevel()) { $querySettings->setRespectStoragePage(false); } $frameworkConfiguration = $this->configurationManager->getConfiguration(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK); $querySettings->setStoragePageIds(\TYPO3\CMS\Core\Utility\GeneralUtility::intExplode(',', $frameworkConfiguration['persistence']['storagePid'])); $query->setQuerySettings($querySettings); return $query; }
/** * Populate this proxy by asking the $population closure. * * @return object The instance (hopefully) returned */ public function _loadRealInstance() { // this check safeguards against a proxy being activated multiple times // usually that does not happen, but if the proxy is held from outside // its parent ... the result would be weird. if ($this->parentObject->_getProperty($this->propertyName) instanceof \TYPO3\CMS\Extbase\Persistence\Generic\LazyLoadingProxy) { $objects = $this->dataMapper->fetchRelated($this->parentObject, $this->propertyName, $this->fieldValue, false, false); $propertyValue = $this->dataMapper->mapResultToPropertyValue($this->parentObject, $this->propertyName, $objects); $this->parentObject->_setProperty($this->propertyName, $propertyValue); $this->parentObject->_memorizeCleanState($this->propertyName); return $propertyValue; } else { return $this->parentObject->_getProperty($this->propertyName); } }
/** * 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); } }
/** * Gets the node-tuple source for this query. * * @return \TYPO3\CMS\Extbase\Persistence\Generic\Qom\SourceInterface the node-tuple source; non-null */ public function getSource() { if ($this->source === NULL) { $this->source = $this->qomFactory->selector($this->getType(), $this->dataMapper->convertClassNameToTableName($this->getType())); } return $this->source; }
/** * Find an extension by title, author name or extension key * This is the function used by the TER search. It is using a * scoring for the matches to sort the extension with an * exact key match on top * * @param string $searchString The string to search for extensions * @return mixed */ public function findByTitleOrAuthorNameOrExtensionKey($searchString) { $quotedSearchString = $GLOBALS['TYPO3_DB']->escapeStrForLike($GLOBALS['TYPO3_DB']->quoteStr($searchString, 'tx_extensionmanager_domain_model_extension'), 'tx_extensionmanager_domain_model_extension'); $quotedSearchStringForLike = '\'%' . $quotedSearchString . '%\''; $quotedSearchString = '\'' . $quotedSearchString . '\''; $select = 'tx_extensionmanager_domain_model_extension.*, ( (extension_key like ' . $quotedSearchString . ') * 8 + (extension_key like ' . $quotedSearchStringForLike . ') * 4 + (title like ' . $quotedSearchStringForLike . ') * 2 + (author_name like ' . $quotedSearchStringForLike . ') ) as position'; $from = 'tx_extensionmanager_domain_model_extension'; $where = '( extension_key = ' . $quotedSearchString . ' OR extension_key LIKE ' . $quotedSearchStringForLike . ' OR description LIKE ' . $quotedSearchStringForLike . ' OR title LIKE ' . $quotedSearchStringForLike . ' ) AND current_version=1 HAVING position > 0'; $order = 'position desc'; $result = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows($select, $from, $where, '', $order); return $this->dataMapper->map('TYPO3\\CMS\\Extensionmanager\\Domain\\Model\\Extension', $result); }
/** * Dump non-localized contents of the repository * * @return void */ public function sqlDumpNonLocalizedData() { // Get the information of the table and its fields $dataMap = $this->dataMapper->getDataMap($this->objectType); $tableName = $dataMap->getTableName(); // Class TYPO3\CMS\Install\Sql\SchemaMigrator was renamed in TYPO3 6.2 if (class_exists('TYPO3\\CMS\\Install\\Service\\SqlSchemaMigrationService')) { $installToolSqlParser = $this->objectManager->get('TYPO3\\CMS\\Install\\Service\\SqlSchemaMigrationService'); } else { $installToolSqlParser = $this->objectManager->get('TYPO3\\CMS\\Install\\Sql\\SchemaMigrator'); } $dbFieldDefinitions = $installToolSqlParser->getFieldDefinitions_database(); $dbFields = array(); $dbFields[$tableName] = $dbFieldDefinitions[$tableName]; $extensionKey = \TYPO3\CMS\Core\Utility\GeneralUtility::camelCaseToLowerCaseUnderscored($this->extensionName); $extensionPath = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath($extensionKey); $ext_tables = \TYPO3\CMS\Core\Utility\GeneralUtility::getUrl($extensionPath . 'ext_tables.sql'); $tableFields = array_keys($dbFields[$tableName]['fields']); foreach ($tableFields as $field) { // This is a very simple check if the field is from static_info_tables and not from a language pack $match = array(); if (!preg_match('#' . preg_quote($field) . '#m', $ext_tables, $match)) { unset($dbFields[$tableName]['fields'][$field]); } } $databaseUtility = $this->objectManager->get('SJBR\\StaticInfoTables\\Utility\\DatabaseUtility'); return $databaseUtility->dumpStaticTables($dbFields); }
/** * adds a union statement to the query, mostly for tables referenced in the where condition. * The property for which the union statement is generated will be appended. * * @param string &$className The name of the parent class, will be set to the child class after processing. * @param string &$tableName The name of the parent table, will be set to the table alias that is used in the union statement. * @param array &$propertyPath The remaining property path, will be cut of by one part during the process. * @param string $fullPropertyPath The full path the the current property, will be used to make table names unique. * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception * @throws InvalidRelationConfigurationException * @throws MissingColumnMapException */ protected function addUnionStatement(&$className, &$tableName, &$propertyPath, &$fullPropertyPath) { $explodedPropertyPath = explode('.', $propertyPath, 2); $propertyName = $explodedPropertyPath[0]; $columnName = $this->dataMapper->convertPropertyNameToColumnName($propertyName, $className); $realTableName = $this->dataMapper->convertClassNameToTableName($className); $tableName = isset($this->tablePropertyMap[$fullPropertyPath]) ? $this->tablePropertyMap[$fullPropertyPath] : $realTableName; $columnMap = $this->dataMapper->getDataMap($className)->getColumnMap($propertyName); if ($columnMap === null) { throw new MissingColumnMapException('The ColumnMap for property "' . $propertyName . '" of class "' . $className . '" is missing.', 1355142232); } $parentKeyFieldName = $columnMap->getParentKeyFieldName(); $childTableName = $columnMap->getChildTableName(); if ($childTableName === null) { throw new InvalidRelationConfigurationException('The relation information for property "' . $propertyName . '" of class "' . $className . '" is missing.', 1353170925); } $fullPropertyPath .= $fullPropertyPath === '' ? $propertyName : '.' . $propertyName; $childTableAlias = $this->getUniqueAlias($childTableName, $fullPropertyPath); // If there is already exists a union with the current identifier we do not need to build it again and exit early. if (in_array($childTableAlias, $this->unionTableAliasCache, true)) { return; } if ($columnMap->getTypeOfRelation() === ColumnMap::RELATION_HAS_ONE) { if (isset($parentKeyFieldName)) { // @todo: no test for this part yet $joinConditionExpression = $this->queryBuilder->expr()->eq($tableName . '.uid', $childTableAlias . '.' . $parentKeyFieldName); } else { $joinConditionExpression = $this->queryBuilder->expr()->eq($tableName . '.' . $columnName, $childTableAlias . '.uid'); } $this->queryBuilder->leftJoin($tableName, $childTableName, $childTableAlias, $joinConditionExpression); $this->unionTableAliasCache[] = $childTableAlias; $this->queryBuilder->andWhere($this->getAdditionalMatchFieldsStatement($this->queryBuilder->expr(), $columnMap, $childTableAlias, $realTableName)); } elseif ($columnMap->getTypeOfRelation() === ColumnMap::RELATION_HAS_MANY) { // @todo: no tests for this part yet if (isset($parentKeyFieldName)) { $joinConditionExpression = $this->queryBuilder->expr()->eq($tableName . '.uid', $childTableAlias . '.' . $parentKeyFieldName); } else { $joinConditionExpression = $this->queryBuilder->expr()->inSet($tableName . '.' . $columnName, $childTableAlias . '.uid'); } $this->queryBuilder->leftJoin($tableName, $childTableName, $childTableAlias, $joinConditionExpression); $this->unionTableAliasCache[] = $childTableAlias; $this->queryBuilder->andWhere($this->getAdditionalMatchFieldsStatement($this->queryBuilder->expr(), $columnMap, $childTableAlias, $realTableName)); } elseif ($columnMap->getTypeOfRelation() === ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) { $relationTableName = $columnMap->getRelationTableName(); $relationTableAlias = $relationTableAlias = $this->getUniqueAlias($relationTableName, $fullPropertyPath . '_mm'); $joinConditionExpression = $this->queryBuilder->expr()->eq($tableName . '.uid', $relationTableAlias . '.' . $columnMap->getParentKeyFieldName()); $this->queryBuilder->leftJoin($tableName, $relationTableName, $relationTableAlias, $joinConditionExpression); $joinConditionExpression = $this->queryBuilder->expr()->eq($relationTableAlias . '.' . $columnMap->getChildKeyFieldName(), $childTableAlias . '.uid'); $this->queryBuilder->leftJoin($relationTableAlias, $childTableName, $childTableAlias, $joinConditionExpression); $this->queryBuilder->andWhere($this->getAdditionalMatchFieldsStatement($this->queryBuilder->expr(), $columnMap, $relationTableAlias, $realTableName)); $this->unionTableAliasCache[] = $childTableAlias; $this->queryBuilder->addGroupBy($this->tableName . '.uid'); } else { throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception('Could not determine type of relation.', 1252502725); } $propertyPath = $explodedPropertyPath[1]; $tableName = $childTableAlias; $className = $this->dataMapper->getType($className, $propertyName); }
/** * Find an extension by title, author name or extension key * This is the function used by the TER search. It is using a * scoring for the matches to sort the extension with an * exact key match on top * * @param string $searchString The string to search for extensions * @return mixed */ public function findByTitleOrAuthorNameOrExtensionKey($searchString) { $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(self::TABLE_NAME); $searchPlaceholder = $queryBuilder->createNamedParameter($searchString); $searchPlaceholderForLike = '%' . $queryBuilder->escapeLikeWildcards($searchString) . '%'; $searchConstraints = ['extension_key' => $queryBuilder->expr()->eq('extension_key', $queryBuilder->createNamedParameter($searchPlaceholder, \PDO::PARAM_STR)), 'extension_key_like' => $queryBuilder->expr()->like('extension_key', $queryBuilder->createNamedParameter($searchPlaceholderForLike, \PDO::PARAM_STR)), 'title' => $queryBuilder->expr()->like('title', $queryBuilder->createNamedParameter($searchPlaceholderForLike, \PDO::PARAM_STR)), 'description' => $queryBuilder->expr()->like('description', $queryBuilder->createNamedParameter($searchPlaceholderForLike, \PDO::PARAM_STR)), 'author_name' => $queryBuilder->expr()->like('author_name', $queryBuilder->createNamedParameter($searchPlaceholderForLike, \PDO::PARAM_STR))]; $caseStatement = 'CASE ' . 'WHEN ' . $searchConstraints['extension_key'] . ' THEN 16 ' . 'WHEN ' . $searchConstraints['extension_key_like'] . ' THEN 8 ' . 'WHEN ' . $searchConstraints['title'] . ' THEN 4 ' . 'WHEN ' . $searchConstraints['description'] . ' THEN 2 ' . 'WHEN ' . $searchConstraints['author_name'] . ' THEN 1 ' . 'END AS ' . $queryBuilder->quoteIdentifier('position'); $result = $queryBuilder->select('*')->addSelectLiteral($caseStatement)->from(self::TABLE_NAME)->where($queryBuilder->expr()->orX(...array_values($searchConstraints)), $queryBuilder->expr()->eq('current_version', $queryBuilder->createNamedParameter(1, \PDO::PARAM_INT)), $queryBuilder->expr()->gte('review_state', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)))->orderBy('position', 'DESC')->execute()->fetchAll(); return $this->dataMapper->map(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension::class, $result); }
/** * Returns the identifier for an object * * @param \TYPO3\CMS\Extbase\DomainObject\AbstractDomainObject $object * @return string */ public function getObjectIdentifierForObject(\TYPO3\CMS\Extbase\DomainObject\AbstractDomainObject $object = NULL) { $objectIdentifier = false; if ($object) { $dataMap = $this->dataMapper->getDataMap(get_class($object)); $tableName = $dataMap->getTableName(); $objectIdentifier = 'r-' . $tableName . '_' . $object->getUid(); } return $objectIdentifier; }
/** * Tries to fetch the UID of the entity from the database that is related to * the given imported record UID. * * @param string $entityClass * @param int $importedUid * @return int|null */ protected function getEntityUidForImportedUid($entityClass, $importedUid) { $entityTableName = $this->dataMapper->getDataMap($entityClass)->getTableName(); $row = $this->getDatabaseConnection()->exec_SELECTgetSingleRow('uid', $entityTableName, 'tx_czsimplecalimportercal_imported_uid=' . (int) $importedUid); if (empty($row)) { return NULL; } else { return (int) $row['uid']; } }
/** * adds a union statement to the query, mostly for tables referenced in the where condition. * The property for which the union statement is generated will be appended. * * @param string &$className The name of the parent class, will be set to the child class after processing. * @param string &$tableName The name of the parent table, will be set to the table alias that is used in the union statement. * @param array &$propertyPath The remaining property path, will be cut of by one part during the process. * @param array &$sql The SQL statement parts, will be filled with the union statements. * @param string $fullPropertyPath The full path the the current property, will be used to make table names unique. * @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, &$fullPropertyPath) { $explodedPropertyPath = explode('.', $propertyPath, 2); $propertyName = $explodedPropertyPath[0]; $columnName = $this->dataMapper->convertPropertyNameToColumnName($propertyName, $className); $realTableName = $this->dataMapper->convertClassNameToTableName($className); $tableName = isset($this->tablePropertyMap[$fullPropertyPath]) ? $this->tablePropertyMap[$fullPropertyPath] : $realTableName; $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); } $parentKeyFieldName = $columnMap->getParentKeyFieldName(); $childTableName = $columnMap->getChildTableName(); if ($childTableName === null) { throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\InvalidRelationConfigurationException('The relation information for property "' . $propertyName . '" of class "' . $className . '" is missing.', 1353170925); } $fullPropertyPath .= $fullPropertyPath === '' ? $propertyName : '.' . $propertyName; $childTableAlias = $this->getUniqueAlias($sql, $childTableName, $fullPropertyPath); // If there is already exists a union with the current identifier we do not need to build it again and exit early. if (isset($sql['unions'][$childTableAlias])) { $propertyPath = $explodedPropertyPath[1]; $tableName = $childTableAlias; $className = $this->dataMapper->getType($className, $propertyName); return; } if ($columnMap->getTypeOfRelation() === ColumnMap::RELATION_HAS_ONE) { if (isset($parentKeyFieldName)) { $sql['unions'][$childTableAlias] = 'LEFT JOIN ' . $childTableName . ' AS ' . $childTableAlias . ' ON ' . $tableName . '.uid=' . $childTableAlias . '.' . $parentKeyFieldName; } else { $sql['unions'][$childTableAlias] = 'LEFT JOIN ' . $childTableName . ' AS ' . $childTableAlias . ' ON ' . $tableName . '.' . $columnName . '=' . $childTableAlias . '.uid'; } $sql['unions'][$childTableAlias] .= $this->getAdditionalMatchFieldsStatement($columnMap, $childTableName, $childTableAlias, $realTableName); } elseif ($columnMap->getTypeOfRelation() === ColumnMap::RELATION_HAS_MANY) { if (isset($parentKeyFieldName)) { $sql['unions'][$childTableAlias] = 'LEFT JOIN ' . $childTableName . ' AS ' . $childTableAlias . ' ON ' . $tableName . '.uid=' . $childTableAlias . '.' . $parentKeyFieldName; } else { $onStatement = '(FIND_IN_SET(' . $childTableAlias . '.uid, ' . $tableName . '.' . $columnName . '))'; $sql['unions'][$childTableAlias] = 'LEFT JOIN ' . $childTableName . ' AS ' . $childTableAlias . ' ON ' . $onStatement; } $sql['unions'][$childTableAlias] .= $this->getAdditionalMatchFieldsStatement($columnMap, $childTableName, $childTableAlias, $realTableName); } elseif ($columnMap->getTypeOfRelation() === ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) { $relationTableName = $columnMap->getRelationTableName(); $relationTableAlias = $relationTableAlias = $this->getUniqueAlias($sql, $relationTableName, $fullPropertyPath . '_mm'); $sql['unions'][$relationTableAlias] = 'LEFT JOIN ' . $relationTableName . ' AS ' . $relationTableAlias . ' ON ' . $tableName . '.uid=' . $relationTableAlias . '.' . $columnMap->getParentKeyFieldName(); $sql['unions'][$childTableAlias] = 'LEFT JOIN ' . $childTableName . ' AS ' . $childTableAlias . ' ON ' . $relationTableAlias . '.' . $columnMap->getChildKeyFieldName() . '=' . $childTableAlias . '.uid'; $sql['unions'][$childTableAlias] .= $this->getAdditionalMatchFieldsStatement($columnMap, $relationTableName, $relationTableAlias, $realTableName); } else { throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception('Could not determine type of relation.', 1252502725); } // @todo check if there is another solution for this $sql['keywords']['distinct'] = 'DISTINCT'; $propertyPath = $explodedPropertyPath[1]; $tableName = $childTableAlias; $className = $this->dataMapper->getType($className, $propertyName); }
/** * Since ExtBase isn't forcing the one to one relationships * for FileReferences, we're doing it here. * * ASSUMPTION: FileReference to File is one to one as well. * Meaning, deleting a FileReference will delete the File. * * NOTE: At this point, the FileReference object has not been saved * in the database. * * @param FileReference $fileReference * @param \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $object * @param string $fieldname * @param string $propertyPath */ public function saveOneToOne(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $object, $fieldname, FileReference $fileReference, $propertyPath = 'file') { // This is a new $object, unlikely to have any existing FileReferences for this field. if (!$object->getUid() || $fileReference->getUid()) { return $this->save($fileReference, $propertyPath); } // Remove all FileReferences for this field $datamap = $this->dataMapper->getDataMap(get_class($object)); $this->removeFileReferences($object->getUid(), $datamap->getTableName(), $fieldname); return $this->save($fileReference, $propertyPath); }
/** * Counts the elements in the storage array * * @throws Exception * @return integer The number of elements in the ObjectStorage */ public function count() { $columnMap = $this->dataMapper->getDataMap(get_class($this->parentObject))->getColumnMap($this->propertyName); $numberOfElements = NULL; if (!$this->isInitialized && $columnMap->getTypeOfRelation() === Mapper\ColumnMap::RELATION_HAS_MANY) { $numberOfElements = $this->dataMapper->countRelated($this->parentObject, $this->propertyName, $this->fieldValue); } else { $this->initialize(); $numberOfElements = count($this->storage); } if (is_null($numberOfElements)) { throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception('The number of elements could not be determined.', 1252514486); } return $numberOfElements; }
/** * Returns the first object in the result set * * @return object * @api */ public function getFirst() { if (is_array($this->queryResult)) { $queryResult = $this->queryResult; reset($queryResult); } else { $query = $this->getQuery(); $query->setLimit(1); $queryResult = $this->dataMapper->map($query->getType(), $this->persistenceManager->getObjectDataByQuery($query)); } $firstResult = current($queryResult); if ($firstResult === false) { $firstResult = null; } return $firstResult; }
/** * Find an extension by title, author name or extension key * This is the function used by the TER search. It is using a * scoring for the matches to sort the extension with an * exact key match on top * * @param string $searchString The string to search for extensions * @return mixed */ public function findByTitleOrAuthorNameOrExtensionKey($searchString) { $quotedSearchString = $this->databaseConnection->escapeStrForLike($this->databaseConnection->quoteStr($searchString, 'tx_extensionmanager_domain_model_extension'), 'tx_extensionmanager_domain_model_extension'); $quotedSearchStringForLike = '\'%' . $quotedSearchString . '%\''; $quotedSearchString = '\'' . $quotedSearchString . '\''; $select = self::TABLE_NAME . '.*, ' . 'CASE ' . 'WHEN extension_key = ' . $quotedSearchString . ' THEN 16 ' . 'WHEN extension_key LIKE ' . $quotedSearchStringForLike . ' THEN 8 ' . 'WHEN title LIKE ' . $quotedSearchStringForLike . ' THEN 4 ' . 'WHEN description LIKE ' . $quotedSearchStringForLike . ' THEN 2 ' . 'WHEN author_name LIKE ' . $quotedSearchStringForLike . ' THEN 1 ' . 'END AS position'; $where = '( extension_key = ' . $quotedSearchString . ' OR extension_key LIKE ' . $quotedSearchStringForLike . ' OR title LIKE ' . $quotedSearchStringForLike . ' OR description LIKE ' . $quotedSearchStringForLike . ' OR author_name LIKE ' . $quotedSearchStringForLike . ' ) AND current_version = 1 AND review_state >= 0'; $order = 'position DESC'; $result = $this->databaseConnection->exec_SELECTgetRows($select, self::TABLE_NAME, $where, '', $order); return $this->dataMapper->map(\TYPO3\CMS\Extensionmanager\Domain\Model\Extension::class, $result); }
/** * adds a union statement to the query, mostly for tables referenced in the where condition. * * @param string &$className * @param string &$tableName * @param array &$propertyPath * @param array &$sql * @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) { $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); } $parentKeyFieldName = $columnMap->getParentKeyFieldName(); $childTableName = $columnMap->getChildTableName(); 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() === ColumnMap::RELATION_HAS_ONE) { if (isset($parentKeyFieldName)) { $sql['unions'][$childTableName] = 'LEFT JOIN ' . $childTableName . ' ON ' . $tableName . '.uid=' . $childTableName . '.' . $parentKeyFieldName; } else { $sql['unions'][$childTableName] = 'LEFT JOIN ' . $childTableName . ' ON ' . $tableName . '.' . $columnName . '=' . $childTableName . '.uid'; } $className = $this->dataMapper->getType($className, $propertyName); } elseif ($columnMap->getTypeOfRelation() === ColumnMap::RELATION_HAS_MANY) { if (isset($parentKeyFieldName)) { $sql['unions'][$childTableName] = 'LEFT JOIN ' . $childTableName . ' ON ' . $tableName . '.uid=' . $childTableName . '.' . $parentKeyFieldName; } else { $onStatement = '(FIND_IN_SET(' . $childTableName . '.uid, ' . $tableName . '.' . $columnName . '))'; $sql['unions'][$childTableName] = 'LEFT JOIN ' . $childTableName . ' ON ' . $onStatement; } $className = $this->dataMapper->getType($className, $propertyName); } elseif ($columnMap->getTypeOfRelation() === ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) { $relationTableName = $columnMap->getRelationTableName(); $sql['unions'][$relationTableName] = 'LEFT JOIN ' . $relationTableName . ' ON ' . $tableName . '.uid=' . $relationTableName . '.' . $columnMap->getParentKeyFieldName(); $sql['unions'][$childTableName] = '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); } // TODO check if there is another solution for this $sql['keywords']['distinct'] = 'DISTINCT'; $propertyPath = $explodedPropertyPath[1]; $tableName = $childTableName; }
/** * Remove related objects * * @param \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $object The object to scanned for related objects * @return void */ protected function removeRelatedObjects(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $object) { $className = get_class($object); $dataMap = $this->dataMapper->getDataMap($className); $classSchema = $this->reflectionService->getClassSchema($className); $properties = $object->_getProperties(); foreach ($properties as $propertyName => $propertyValue) { $columnMap = $dataMap->getColumnMap($propertyName); $propertyMetaData = $classSchema->getProperty($propertyName); if ($propertyMetaData['cascade'] === 'remove') { if ($columnMap->getTypeOfRelation() === \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_MANY) { foreach ($propertyValue as $containedObject) { $this->removeEntity($containedObject); } } elseif ($propertyValue instanceof \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface) { $this->removeEntity($propertyValue); } } } }
/** * 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; } }
/** * @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)); }