|
TYPO3 API
SVNRelease
|
00001 <?php 00002 /*************************************************************** 00003 * Copyright notice 00004 * 00005 * (c) 2009 Jochen Rau <jochen.rau@typoplanet.de> 00006 * All rights reserved 00007 * 00008 * This script is part of the TYPO3 project. The TYPO3 project is 00009 * free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * The GNU General Public License can be found at 00015 * http://www.gnu.org/copyleft/gpl.html. 00016 * 00017 * This script is distributed in the hope that it will be useful, 00018 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00019 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00020 * GNU General Public License for more details. 00021 * 00022 * This copyright notice MUST APPEAR in all copies of the script! 00023 ***************************************************************/ 00024 00025 /** 00026 * A factory for a data map to map a single table configured in $TCA on a domain object. 00027 * 00028 * @package Extbase 00029 * @subpackage Persistence\Mapper 00030 * @version $ID:$ 00031 */ 00032 class Tx_Extbase_Persistence_Mapper_DataMapFactory implements t3lib_Singleton { 00033 00034 /** 00035 * @var Tx_Extbase_Reflection_Service 00036 */ 00037 protected $reflectionService; 00038 00039 /** 00040 * @var Tx_Extbase_Configuration_ConfigurationManagerInterface 00041 */ 00042 protected $configurationManager; 00043 00044 /** 00045 * Injects the reflection service 00046 * 00047 * @param Tx_Extbase_Reflection_Service $reflectionService 00048 * @return void 00049 */ 00050 public function injectReflectionService(Tx_Extbase_Reflection_Service $reflectionService) { 00051 $this->reflectionService = $reflectionService; 00052 } 00053 00054 /** 00055 * @param Tx_Extbase_Configuration_ConfigurationManagerInterface $configurationManager 00056 * @return void 00057 */ 00058 public function injectConfigurationManager(Tx_Extbase_Configuration_ConfigurationManagerInterface $configurationManager) { 00059 $this->configurationManager = $configurationManager; 00060 } 00061 00062 /** 00063 * Builds a data map by adding column maps for all the configured columns in the $TCA. 00064 * It also resolves the type of values the column is holding and the typo of relation the column 00065 * represents. 00066 * 00067 * @param string $className The class name you want to fetch the Data Map for 00068 * @return Tx_Extbase_Persistence_Mapper_DataMap The data map 00069 */ 00070 public function buildDataMap($className) { 00071 if (!class_exists($className)) { 00072 throw new Tx_Extbase_Persistence_Exception_InvalidClass('Could not find class definition for name "' . $className . '". This could be caused by a mis-spelling of the class name in the class definition.'); 00073 } 00074 00075 $recordType = NULL; 00076 $subclasses = array(); 00077 $tableName = strtolower($className); 00078 $columnMapping = array(); 00079 00080 $frameworkConfiguration = $this->configurationManager->getConfiguration(Tx_Extbase_Configuration_ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK); 00081 $classSettings = $frameworkConfiguration['persistence']['classes'][$className]; 00082 if ($classSettings !== NULL) { 00083 if (isset($classSettings['subclasses']) && is_array($classSettings['subclasses'])) { 00084 $subclasses = $classSettings['subclasses']; 00085 } 00086 if (isset($classSettings['mapping']['recordType']) && strlen($classSettings['mapping']['recordType']) > 0) { 00087 $recordType = $classSettings['mapping']['recordType']; 00088 } 00089 if (isset($classSettings['mapping']['tableName']) && strlen($classSettings['mapping']['tableName']) > 0) { 00090 $tableName = $classSettings['mapping']['tableName']; 00091 } 00092 $classHierachy = array_merge(array($className), class_parents($className)); 00093 foreach ($classHierachy as $currentClassName) { 00094 if (in_array($currentClassName, array('Tx_Extbase_DomainObject_AbstractEntity', 'Tx_Extbase_DomainObject_AbstractValueObject'))) { 00095 break; 00096 } 00097 $currentClassSettings = $frameworkConfiguration['persistence']['classes'][$currentClassName]; 00098 if ($currentClassSettings !== NULL) { 00099 if (isset($currentClassSettings['mapping']['columns']) && is_array($currentClassSettings['mapping']['columns'])) { 00100 $columnMapping = t3lib_div::array_merge_recursive_overrule($columnMapping, $currentClassSettings['mapping']['columns'], 0, FALSE); // FALSE means: do not include empty values form 2nd array 00101 } 00102 } 00103 } 00104 } 00105 00106 $dataMap = new Tx_Extbase_Persistence_Mapper_DataMap($className, $tableName, $recordType, $subclasses); 00107 $dataMap = $this->addMetaDataColumnNames($dataMap, $tableName); 00108 00109 // $classPropertyNames = $this->reflectionService->getClassPropertyNames($className); 00110 $tcaColumnsDefinition = $this->getColumnsDefinition($tableName); 00111 $tcaColumnsDefinition = t3lib_div::array_merge_recursive_overrule($tcaColumnsDefinition, $columnMapping); // TODO Is this is too powerful? 00112 foreach ($tcaColumnsDefinition as $columnName => $columnDefinition) { 00113 if (isset($columnDefinition['mapOnProperty'])) { 00114 $propertyName = $columnDefinition['mapOnProperty']; 00115 } else { 00116 $propertyName = t3lib_div::underscoredToLowerCamelCase($columnName); 00117 } 00118 // if (in_array($propertyName, $classPropertyNames)) { // TODO Enable check for property existance 00119 $columnMap = new Tx_Extbase_Persistence_Mapper_ColumnMap($columnName, $propertyName); 00120 $propertyMetaData = $this->reflectionService->getClassSchema($className)->getProperty($propertyName); 00121 $columnMap = $this->setRelations($columnMap, $columnDefinition['config'], $propertyMetaData); 00122 $dataMap->addColumnMap($columnMap); 00123 // } 00124 } 00125 // debug($dataMap); 00126 return $dataMap; 00127 } 00128 00129 /** 00130 * Returns the TCA ctrl section of the specified table; or NULL if not set 00131 * 00132 * @param string $tableName An optional table name to fetch the columns definition from 00133 * @return array The TCA columns definition 00134 */ 00135 protected function getControlSection($tableName) { 00136 $this->includeTca($tableName); 00137 return is_array($GLOBALS['TCA'][$tableName]['ctrl']) ? $GLOBALS['TCA'][$tableName]['ctrl'] : NULL; 00138 } 00139 00140 /** 00141 * Returns the TCA columns array of the specified table 00142 * 00143 * @param string $tableName An optional table name to fetch the columns definition from 00144 * @return array The TCA columns definition 00145 */ 00146 protected function getColumnsDefinition($tableName) { 00147 $this->includeTca($tableName); 00148 return is_array($GLOBALS['TCA'][$tableName]['columns']) ? $GLOBALS['TCA'][$tableName]['columns'] : array(); 00149 } 00150 00151 /** 00152 * Includes the TCA for the given table 00153 * 00154 * @param string $tableName An optional table name to fetch the columns definition from 00155 * @return void 00156 */ 00157 protected function includeTca($tableName) { 00158 if (TYPO3_MODE === 'FE') { 00159 $GLOBALS['TSFE']->includeTCA(); 00160 } 00161 t3lib_div::loadTCA($tableName); 00162 } 00163 00164 protected function addMetaDataColumnNames(Tx_Extbase_Persistence_Mapper_DataMap $dataMap, $tableName) { 00165 $controlSection = $GLOBALS['TCA'][$tableName]['ctrl']; 00166 $dataMap->setPageIdColumnName('pid'); 00167 if (isset($controlSection['tstamp'])) $dataMap->setModificationDateColumnName($controlSection['tstamp']); 00168 if (isset($controlSection['crdate'])) $dataMap->setCreationDateColumnName($controlSection['crdate']); 00169 if (isset($controlSection['cruser_id'])) $dataMap->setCreatorColumnName($controlSection['cruser_id']); 00170 if (isset($controlSection['delete'])) $dataMap->setDeletedFlagColumnName($controlSection['delete']); 00171 if (isset($controlSection['languageField'])) $dataMap->setLanguageIdColumnName($controlSection['languageField']); 00172 if (isset($controlSection['transOrigPointerField'])) $dataMap->setTranslationOriginColumnName($controlSection['transOrigPointerField']); 00173 if (isset($controlSection['type'])) $dataMap->setRecordTypeColumnName($controlSection['type']); 00174 if (isset($controlSection['enablecolumns']['disabled'])) $dataMap->setDisabledFlagColumnName($controlSection['enablecolumns']['disabled']); 00175 if (isset($controlSection['enablecolumns']['starttime'])) $dataMap->setStartTimeColumnName($controlSection['enablecolumns']['starttime']); 00176 if (isset($controlSection['enablecolumns']['endtime'])) $dataMap->setEndTimeColumnName($controlSection['enablecolumns']['endtime']); 00177 if (isset($controlSection['enablecolumns']['fe_group'])) $dataMap->setFrontEndUserGroupColumnName($controlSection['enablecolumns']['fe_group']); 00178 return $dataMap; 00179 } 00180 00181 /** 00182 * This method tries to determine the type of type of relation to other tables and sets it based on 00183 * the $TCA column configuration 00184 * 00185 * @param Tx_Extbase_Persistence_Mapper_ColumnMap $columnMap The column map 00186 * @param string $columnConfiguration The column configuration from $TCA 00187 * @param array $propertyMetaData The property metadata as delivered by the reflection service 00188 * @return void 00189 */ 00190 protected function setRelations(Tx_Extbase_Persistence_Mapper_ColumnMap $columnMap, $columnConfiguration, $propertyMetaData) { 00191 if (isset($columnConfiguration)) { 00192 if (isset($columnConfiguration['MM']) || isset($columnConfiguration['foreign_selector'])) { 00193 $columnMap = $this->setManyToManyRelation($columnMap, $columnConfiguration); 00194 } elseif (isset($propertyMetaData['elementType'])) { 00195 $columnMap = $this->setOneToManyRelation($columnMap, $columnConfiguration); 00196 } elseif (isset($propertyMetaData['type']) && strpos($propertyMetaData['type'], '_') !== FALSE) { 00197 $columnMap = $this->setOneToOneRelation($columnMap, $columnConfiguration); 00198 } else { 00199 $columnMap->setTypeOfRelation(Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_NONE); 00200 } 00201 } else { 00202 $columnMap->setTypeOfRelation(Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_NONE); 00203 } 00204 return $columnMap; 00205 } 00206 00207 /** 00208 * This method sets the configuration for a 1:1 relation based on 00209 * the $TCA column configuration 00210 * 00211 * @param string $columnMap The column map 00212 * @param string $columnConfiguration The column configuration from $TCA 00213 * @return void 00214 */ 00215 protected function setOneToOneRelation(Tx_Extbase_Persistence_Mapper_ColumnMap $columnMap, $columnConfiguration) { 00216 $columnMap->setTypeOfRelation(Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_ONE); 00217 $columnMap->setChildTableName($columnConfiguration['foreign_table']); 00218 $columnMap->setChildTableWhereStatement($columnConfiguration['foreign_table_where']); 00219 $columnMap->setChildSortbyFieldName($columnConfiguration['foreign_sortby']); 00220 $columnMap->setParentKeyFieldName($columnConfiguration['foreign_field']); 00221 $columnMap->setParentTableFieldName($columnConfiguration['foreign_table_field']); 00222 return $columnMap; 00223 } 00224 00225 /** 00226 * This method sets the configuration for a 1:n relation based on 00227 * the $TCA column configuration 00228 * 00229 * @param string $columnMap The column map 00230 * @param string $columnConfiguration The column configuration from $TCA 00231 * @return void 00232 */ 00233 protected function setOneToManyRelation(Tx_Extbase_Persistence_Mapper_ColumnMap $columnMap, $columnConfiguration) { 00234 $columnMap->setTypeOfRelation(Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_MANY); 00235 $columnMap->setChildTableName($columnConfiguration['foreign_table']); 00236 $columnMap->setChildTableWhereStatement($columnConfiguration['foreign_table_where']); 00237 $columnMap->setChildSortbyFieldName($columnConfiguration['foreign_sortby']); 00238 $columnMap->setParentKeyFieldName($columnConfiguration['foreign_field']); 00239 $columnMap->setParentTableFieldName($columnConfiguration['foreign_table_field']); 00240 return $columnMap; 00241 } 00242 00243 /** 00244 * This method sets the configuration for a m:n relation based on 00245 * the $TCA column configuration 00246 * 00247 * @param string $columnMap The column map 00248 * @param string $columnConfiguration The column configuration from $TCA 00249 * @return void 00250 */ 00251 protected function setManyToManyRelation(Tx_Extbase_Persistence_Mapper_ColumnMap $columnMap, $columnConfiguration) { 00252 $columnMap->setTypeOfRelation(Tx_Extbase_Persistence_Mapper_ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY); 00253 if (isset($columnConfiguration['MM'])) { 00254 $columnMap->setChildTableName($columnConfiguration['foreign_table']); 00255 $columnMap->setChildTableWhereStatement($columnConfiguration['foreign_table_where']); 00256 $columnMap->setRelationTableName($columnConfiguration['MM']); 00257 if (is_array($columnConfiguration['MM_match_fields'])) { 00258 $columnMap->setRelationTableMatchFields($columnConfiguration['MM_match_fields']); 00259 } 00260 if (is_array($columnConfiguration['MM_insert_fields'])) { 00261 $columnMap->setRelationTableInsertFields($columnConfiguration['MM_insert_fields']); 00262 } 00263 $columnMap->setRelationTableWhereStatement($columnConfiguration['MM_table_where']); 00264 if (!empty($columnConfiguration['MM_opposite_field'])) { 00265 $columnMap->setParentKeyFieldName('uid_foreign'); 00266 $columnMap->setChildKeyFieldName('uid_local'); 00267 $columnMap->setChildSortByFieldName('sorting_foreign'); 00268 } else { 00269 $columnMap->setParentKeyFieldName('uid_local'); 00270 $columnMap->setChildKeyFieldName('uid_foreign'); 00271 $columnMap->setChildSortByFieldName('sorting'); 00272 } 00273 } elseif (isset($columnConfiguration['foreign_selector'])) { 00274 $columns = $this->getColumnsDefinition($columnConfiguration['foreign_table']); 00275 $childKeyFieldName = $columnConfiguration['foreign_selector']; 00276 $columnMap->setChildTableName($columns[$childKeyFieldName]['config']['foreign_table']); 00277 $columnMap->setRelationTableName($columnConfiguration['foreign_table']); 00278 $columnMap->setParentKeyFieldName($columnConfiguration['foreign_field']); 00279 $columnMap->setChildKeyFieldName($childKeyFieldName); 00280 $columnMap->setChildSortByFieldName($columnConfiguration['foreign_sortby']); 00281 } else { 00282 throw new Tx_Extbase_Persistence_Exception_UnsupportedRelation('The given information to build a many-to-many-relation was not sufficient. Check your TCA definitions. mm-relations with IRRE must have at least a defined "MM" or "foreign_selector".', 1268817963); 00283 } 00284 if ($this->getControlSection($columnMap->getRelationTableName()) !== NULL) { 00285 $columnMap->setRelationTablePageIdColumnName('pid'); 00286 } 00287 return $columnMap; 00288 } 00289 00290 }
1.8.0