83d05eccdc4a41299e1b5eb81679350ee8ff66bc
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / Persistence / Mapper / DataMap.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2009 Jochen Rau <jochen.rau@typoplanet.de>
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 *
17 * This script is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * This copyright notice MUST APPEAR in all copies of the script!
23 ***************************************************************/
24
25 /**
26 * A data map to map a single table configured in $TCA on a domain object.
27 *
28 * @package TYPO3
29 * @subpackage extbase
30 * @version $ID:$
31 */
32 class Tx_ExtBase_Persistence_Mapper_DataMap {
33 // SK: PHPDoc (even for getters and setters, sorry ;-) )
34 // SK: I did not do an in-depth check of this class
35 /**
36 * The domain class name
37 *
38 * @var string
39 **/
40 protected $className;
41
42 /**
43 * The table name corresponding to the domain class configured in $TCA
44 *
45 * @var string
46 **/
47 protected $tableName;
48
49 /**
50 * An array of column maps configured in $TCA
51 *
52 * @var array
53 **/
54 protected $columnMaps;
55
56 /**
57 * Constructs this DataMap
58 *
59 * @param string $className The class name. This determines the table to fetch the configuration for
60 */
61 public function __construct($className) {
62 $this->setClassName($className);
63 // SK: strtolower(..) is the wrong conversion for the class name. See the notice in the dispatcher (tt_news ->tx_ttnews)
64 $this->setTableName(strtolower($this->className));
65 t3lib_div::loadTCA($this->getTableName());
66 }
67
68 public function setClassName($className) {
69 $this->className = $className;
70 }
71
72 public function getClassName() {
73 return $this->className;
74 }
75
76 public function setTableName($tableName) {
77 $this->tableName = $tableName;
78 }
79
80 public function getTableName() {
81 return $this->tableName;
82 }
83
84 // SK: Why is initialize() not called in the constructor? Without initialize(), the object cannot do anything - or am I wrong here?
85 public function initialize() {
86 $columns = $GLOBALS['TCA'][$this->getTableName()]['columns'];
87 if (is_array($columns)) {
88 $this->addCommonColumns();
89 foreach ($columns as $columnName => $columnConfiguration) {
90 $columnMap = new Tx_ExtBase_Persistence_Mapper_ColumnMap($columnName, $this);
91 $this->setTypeOfValue($columnMap, $columnConfiguration);
92 // TODO support for IRRE
93 // TODO support for MM_insert_fields and MM_match_fields
94 // SK: Discuss the above things
95 $this->setRelations($columnMap, $columnConfiguration);
96 $this->addColumnMap($columnMap);
97 }
98 } else {
99 // TODO Throw exception
100 }
101 }
102
103 protected function addCommonColumns() {
104 $this->addColumn('uid', Tx_ExtBase_Persistence_Mapper_ColumnMap::TYPE_INTEGER);
105 $this->addColumn('pid', Tx_ExtBase_Persistence_Mapper_ColumnMap::TYPE_INTEGER);
106 $this->addColumn('tstamp', Tx_ExtBase_Persistence_Mapper_ColumnMap::TYPE_DATE);
107 $this->addColumn('crdate', Tx_ExtBase_Persistence_Mapper_ColumnMap::TYPE_DATE);
108 $this->addColumn('cruser_id', Tx_ExtBase_Persistence_Mapper_ColumnMap::TYPE_INTEGER);
109 if ($this->getDeletedColumnName() !== NULL) {
110 $this->addColumn($this->getDeletedColumnName(), Tx_ExtBase_Persistence_Mapper_ColumnMap::TYPE_BOOLEAN);
111 }
112 if ($this->getHiddenColumnName() !== NULL) {
113 $this->addColumn($this->getHiddenColumnName(), Tx_ExtBase_Persistence_Mapper_ColumnMap::TYPE_BOOLEAN);
114 }
115 }
116
117 protected function setTypeOfValue(Tx_ExtBase_Persistence_Mapper_ColumnMap &$columnMap, $columnConfiguration) {
118 $evalConfiguration = t3lib_div::trimExplode(',', $columnConfiguration['config']['eval']);
119 if (in_array('date', $evalConfiguration) || in_array('datetime', $evalConfiguration)) {
120 $columnMap->setTypeOfValue(Tx_ExtBase_Persistence_Mapper_ColumnMap::TYPE_DATE);
121 } elseif ($columnConfiguration['config']['type'] === 'check' && empty($columnConfiguration['config']['items'])) {
122 $columnMap->setTypeOfValue(Tx_ExtBase_Persistence_Mapper_ColumnMap::TYPE_BOOLEAN);
123 } elseif (in_array('int', $evalConfiguration)) {
124 $columnMap->setTypeOfValue(Tx_ExtBase_Persistence_Mapper_ColumnMap::TYPE_INTEGER);
125 } elseif (in_array('double2', $evalConfiguration)) {
126 $columnMap->setTypeOfValue(Tx_ExtBase_Persistence_Mapper_ColumnMap::TYPE_FLOAT);
127 } else {
128 $columnMap->setTypeOfValue(Tx_ExtBase_Persistence_Mapper_ColumnMap::TYPE_STRING);
129 }
130 }
131
132 protected function setRelations(Tx_ExtBase_Persistence_Mapper_ColumnMap &$columnMap, $columnConfiguration) {
133 if (isset($columnConfiguration['config']['foreign_table']) && !isset($columnConfiguration['config']['MM'])) {
134 if ($columnConfiguration['config']['maxitems'] == 1) {
135 $columnMap->setTypeOfRelation(Tx_ExtBase_Persistence_Mapper_ColumnMap::RELATION_HAS_ONE);
136 $columnMap->setChildClassName($columnConfiguration['config']['foreign_class']);
137 $columnMap->setChildTableName($columnConfiguration['config']['foreign_table']);
138 $columnMap->setChildTableWhere($columnConfiguration['config']['foreign_table_where']);
139 $columnMap->setChildSortbyFieldName($columnConfiguration['config']['foreign_sortby']);
140 $columnMap->setParentKeyFieldName($columnConfiguration['config']['foreign_field']);
141 $columnMap->setParentTableFieldName($columnConfiguration['config']['foreign_table_field']);
142 } else {
143 $columnMap->setTypeOfRelation(Tx_ExtBase_Persistence_Mapper_ColumnMap::RELATION_HAS_MANY);
144 $columnMap->setChildClassName($columnConfiguration['config']['foreign_class']);
145 $columnMap->setChildTableName($columnConfiguration['config']['foreign_table']);
146 $columnMap->setChildTableWhere($columnConfiguration['config']['foreign_table_where']);
147 $columnMap->setChildSortbyFieldName($columnConfiguration['config']['foreign_sortby']);
148 $columnMap->setParentKeyFieldName($columnConfiguration['config']['foreign_field']);
149 $columnMap->setParentTableFieldName($columnConfiguration['config']['foreign_table_field']);
150 }
151 } elseif (array_key_exists('MM', $columnConfiguration['config'])) {
152 $columnMap->setTypeOfRelation(Tx_ExtBase_Persistence_Mapper_ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY);
153 $columnMap->setChildClassName($columnConfiguration['config']['foreign_class']);
154 $columnMap->setChildTableName($columnConfiguration['config']['foreign_table']);
155 $columnMap->setRelationTableName($columnConfiguration['config']['MM']);
156 } else {
157 $columnMap->setTypeOfRelation(Tx_ExtBase_Persistence_Mapper_ColumnMap::RELATION_NONE);
158 }
159 }
160
161 public function setColumnMaps(array $columnMaps) {
162 $this->columnMaps = $columnMaps;
163 }
164
165 public function addColumnMap(Tx_ExtBase_Persistence_Mapper_ColumnMap $columnMap) {
166 $this->columnMaps[$columnMap->getPropertyName()] = $columnMap;
167 }
168
169 public function addColumn($columnName, $typeOfValue = Tx_ExtBase_Persistence_Mapper_ColumnMap::TYPE_STRING, $typeOfRelation = Tx_ExtBase_Persistence_Mapper_ColumnMap::RELATION_NONE) {
170 $columnMap = new Tx_ExtBase_Persistence_Mapper_ColumnMap($columnName);
171 $columnMap->setTypeOfValue($typeOfValue);
172 $columnMap->setTypeOfRelation($typeOfRelation);
173 $this->addColumnMap($columnMap);
174 return $this;
175 }
176
177 public function getColumnMaps() {
178 return $this->columnMaps;
179 }
180
181 public function getColumnMap($propertyName) {
182 return $this->columnMaps[$propertyName];
183 }
184
185 public function getColumnList() {
186 $columnList = '';
187 foreach ($this->columnMaps as $columnMap) {
188 if ($columnList !== '') {
189 $columnList .= ',';
190 }
191 $columnList .= $columnMap->getColumnName();
192 }
193 return $columnList;
194 }
195
196 /**
197 * Returns TRUE if the property is persistable (configured in $TCA)
198 *
199 * @param string $propertyName The property name
200 * @return boolean TRUE if the property is persistable (configured in $TCA)
201 */
202 public function isPersistableProperty($propertyName) {
203 return isset($this->columnMaps[$propertyName]);
204 }
205
206 /**
207 * Returns the name of a column indicating the 'deleted' state of the row
208 *
209 * @return string The class name
210 */
211 public function getDeletedColumnName() {
212 return $GLOBALS['TCA'][$this->getTableName()]['ctrl']['delete'];
213 }
214
215 /**
216 * Returns the name of a column indicating the 'hidden' state of the row
217 *
218 */
219 public function getHiddenColumnName() {
220 return $GLOBALS['TCA'][$this->getTableName()]['ctrl']['enablecolumns']['disabled'];
221 }
222
223 /**
224 * Converts a value from a database field type to a property type
225 *
226 * @param string $className The class name
227 * @param string $propertyName The property name
228 * @param mixed $fieldValue The field value
229 * @return mixed The converted value
230 */
231 // TODO convertion has to be revised
232 public function convertFieldValueToPropertyValue($propertyName, $fieldValue) {
233 $columnMap = $this->getColumnMap($propertyName);
234 if ($columnMap->getTypeOfValue() === Tx_ExtBase_Persistence_Mapper_ColumnMap::TYPE_DATE) {
235 $convertedValue = new DateTime(strftime('%Y-%m-%d %H:%M', $fieldValue));
236 } elseif ($columnMap->getTypeOfValue() === Tx_ExtBase_Persistence_Mapper_ColumnMap::TYPE_BOOLEAN) {
237 if ($fieldValue === '0') {
238 $convertedValue = FALSE;
239 } else {
240 $convertedValue = TRUE;
241 }
242 } else {
243 $convertedValue = $fieldValue;
244 }
245 return $convertedValue;
246 }
247
248 /**
249 * Converts a value from a property type to a database field type
250 *
251 * @param mixed $propertyValue The property value
252 * @param boolean $fullQuoteString TRUE if a field value of type string should be full quoted via $GLOBALS['TYPO3_DB']->fullQuoteStr()
253 * @return mixed The converted value
254 */
255 public function convertPropertyValueToFieldValue($propertyValue, $fullQuoteString = TRUE) {
256 if (is_bool($value)) {
257 $convertedValue = $propertyValue ? 1 : 0;
258 } elseif ($value instanceof Tx_ExtBase_DomainObject_AbstractDomainObject) {
259 $convertedValue = $propertyValue->getUid();
260 } elseif ($propertyValue instanceof DateTime) {
261 $convertedValue = $propertyValue->format('U');
262 } elseif (is_int($propertyValue)) {
263 $convertedValue = $propertyValue;
264 } else {
265 $convertedValue = $fullQuoteString === TRUE ? $GLOBALS['TYPO3_DB']->fullQuoteStr((string)$propertyValue, '') : $propertyValue;
266 }
267 return $convertedValue;
268 }
269
270 }
271 ?>