EXTMVC:
[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 extmvc
30 * @version $ID:$
31 */
32 class TX_EXTMVC_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_EXTMVC_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_EXTMVC_Persistence_Mapper_ColumnMap::TYPE_INTEGER);
105 $this->addColumn('pid', TX_EXTMVC_Persistence_Mapper_ColumnMap::TYPE_INTEGER);
106 $this->addColumn('tstamp', TX_EXTMVC_Persistence_Mapper_ColumnMap::TYPE_DATE);
107 $this->addColumn('crdate', TX_EXTMVC_Persistence_Mapper_ColumnMap::TYPE_DATE);
108 $this->addColumn('cruser_id', TX_EXTMVC_Persistence_Mapper_ColumnMap::TYPE_INTEGER);
109 if ($this->getDeletedColumnName() !== NULL) {
110 $this->addColumn($this->getDeletedColumnName(), TX_EXTMVC_Persistence_Mapper_ColumnMap::TYPE_BOOLEAN);
111 }
112 if ($this->getHiddenColumnName() !== NULL) {
113 $this->addColumn($this->getHiddenColumnName(), TX_EXTMVC_Persistence_Mapper_ColumnMap::TYPE_BOOLEAN);
114 }
115 }
116
117 protected function setTypeOfValue(TX_EXTMVC_Persistence_Mapper_ColumnMap &$columnMap, $columnConfiguration) {
118 if (strpos($columnConfiguration['config']['eval'], 'date') !== FALSE
119 || strpos($columnConfiguration['config']['eval'], 'datetime') !== FALSE) {
120 $columnMap->setTypeOfValue(TX_EXTMVC_Persistence_Mapper_ColumnMap::TYPE_DATE);
121 } elseif ($columnConfiguration['config']['type'] === 'check' && empty($columnConfiguration['config']['items'])) {
122 $columnMap->setTypeOfValue(TX_EXTMVC_Persistence_Mapper_ColumnMap::TYPE_BOOLEAN);
123 } elseif (strpos($columnConfiguration['config']['eval'], 'int') !== FALSE) {
124 $columnMap->setTypeOfValue(TX_EXTMVC_Persistence_Mapper_ColumnMap::TYPE_INTEGER);
125 } elseif (strpos($columnConfiguration['config']['eval'], 'double2') !== FALSE) {
126 $columnMap->setTypeOfValue(TX_EXTMVC_Persistence_Mapper_ColumnMap::TYPE_FLOAT);
127 } else {
128 $columnMap->setTypeOfValue(TX_EXTMVC_Persistence_Mapper_ColumnMap::TYPE_STRING);
129 }
130 }
131
132 protected function setRelations(TX_EXTMVC_Persistence_Mapper_ColumnMap &$columnMap, $columnConfiguration) {
133 if (array_key_exists('foreign_table', $columnConfiguration['config']) && !array_key_exists('MM', $columnConfiguration['config'])) {
134 $columnMap->setTypeOfRelation(TX_EXTMVC_Persistence_Mapper_ColumnMap::RELATION_HAS_MANY);
135 $columnMap->setChildClassName($columnConfiguration['config']['foreign_class']);
136 $columnMap->setChildTableName($columnConfiguration['config']['foreign_table']);
137 $columnMap->setChildTableWhere($columnConfiguration['config']['foreign_table_where']);
138 $columnMap->setChildSortbyFieldName($columnConfiguration['config']['foreign_sortby']);
139 $columnMap->setParentKeyFieldName($columnConfiguration['config']['foreign_field']);
140 $columnMap->setParentTableFieldName($columnConfiguration['config']['foreign_table_field']);
141 } elseif (array_key_exists('MM', $columnConfiguration['config'])) {
142 $columnMap->setTypeOfRelation(TX_EXTMVC_Persistence_Mapper_ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY);
143 $columnMap->setChildClassName($columnConfiguration['config']['foreign_class']);
144 $columnMap->setChildTableName($columnConfiguration['config']['foreign_table']);
145 $columnMap->setRelationTableName($columnConfiguration['config']['MM']);
146 } else {
147 $columnMap->setTypeOfRelation(TX_EXTMVC_Persistence_Mapper_ColumnMap::RELATION_NONE);
148 }
149 }
150
151 public function setColumnMaps(array $columnMaps) {
152 $this->columnMaps = $columnMaps;
153 }
154
155 public function addColumnMap(TX_EXTMVC_Persistence_Mapper_ColumnMap $columnMap) {
156 $this->columnMaps[$columnMap->getPropertyName()] = $columnMap;
157 }
158
159 public function addColumn($columnName, $typeOfValue = TX_EXTMVC_Persistence_Mapper_ColumnMap::TYPE_STRING, $typeOfRelation = TX_EXTMVC_Persistence_Mapper_ColumnMap::RELATION_NONE) {
160 $columnMap = new TX_EXTMVC_Persistence_Mapper_ColumnMap($columnName);
161 $columnMap->setTypeOfValue($typeOfValue);
162 $columnMap->setTypeOfRelation($typeOfRelation);
163 $this->addColumnMap($columnMap);
164 return $this;
165 }
166
167 public function getColumnMaps() {
168 return $this->columnMaps;
169 }
170
171 public function getColumnMap($propertyName) {
172 return $this->columnMaps[$propertyName];
173 }
174
175 public function getColumnList() {
176 $columnList = '';
177 foreach ($this->columnMaps as $columnMap) {
178 if ($columnList !== '') {
179 $columnList .= ',';
180 }
181 $columnList .= $columnMap->getColumnName();
182 }
183 return $columnList;
184 }
185
186 /**
187 * Returns TRUE if the property is persistable (configured in $TCA)
188 *
189 * @param string $propertyName The property name
190 * @return boolean TRUE if the property is persistable (configured in $TCA)
191 */
192 public function isPersistableProperty($propertyName) {
193 return isset($this->columnMaps[$propertyName]);
194 }
195
196 /**
197 * Returns the name of a column indicating the 'deleted' state of the row
198 *
199 * @return string The class name
200 */
201 public function getDeletedColumnName() {
202 return $GLOBALS['TCA'][$this->getTableName()]['ctrl']['delete'];
203 }
204
205 /**
206 * Returns the name of a column indicating the 'hidden' state of the row
207 *
208 */
209 public function getHiddenColumnName() {;
210 return $GLOBALS['TCA'][$this->getTableName()]['ctrl']['enablecolumns']['disabled'];
211 }
212
213 /**
214 * Converts a value from a database field type to a property type
215 *
216 * @param string $className The class name
217 * @param string $propertyName The property name
218 * @param mixed $fieldValue The field value
219 * @return mixed The converted value
220 */
221 // TODO convertion has to be revised
222 public function convertFieldValueToPropertyValue($propertyName, $fieldValue) {
223 $columnMap = $this->getColumnMap($propertyName);
224 if ($columnMap->getTypeOfValue() === TX_EXTMVC_Persistence_Mapper_ColumnMap::TYPE_DATE) {
225 $convertedValue = new DateTime(strftime('%Y-%m-%d %H:%M', $fieldValue));
226 } elseif ($columnMap->getTypeOfValue() === TX_EXTMVC_Persistence_Mapper_ColumnMap::TYPE_BOOLEAN) {
227 if ($fieldValue === '0') {
228 $convertedValue = FALSE;
229 } else {
230 $convertedValue = TRUE;
231 }
232 } else {
233 $convertedValue = $fieldValue;
234 }
235 return $convertedValue;
236 }
237
238 /**
239 * Converts a value from a property type to a database field type
240 *
241 * @param mixed $propertyValue The property value
242 * @return mixed The converted value
243 */
244 public function convertPropertyValueToFieldValue($propertyValue) {
245 if ($propertyValue instanceof DateTime) {
246 $convertedValue = $propertyValue->format('U');
247 } elseif (is_bool($propertyValue)) {
248 $convertedValue = $propertyValue ? 1 : 0;
249 } else {
250 $convertedValue = $propertyValue;
251 }
252 return $convertedValue;
253 }
254
255 }
256 ?>