Commit | Line | Data |
---|---|---|
5e434adf ARW |
1 | <?php |
2 | ||
3 | /** | |
4 | * Read the schema specification and parse into internal data structures | |
5 | */ | |
6 | class CRM_Core_CodeGen_Specification { | |
7 | public $tables; | |
8 | public $database; | |
9 | ||
10 | protected $classNames; | |
11 | ||
12 | /** | |
13 | * Read and parse. | |
14 | * | |
15 | * @param string $buildVersion which version of the schema to build | |
16 | */ | |
17 | function parse($schemaPath, $buildVersion) { | |
18 | $this->buildVersion = $buildVersion; | |
19 | ||
20 | echo "Parsing schema description ".$schemaPath."\n"; | |
21 | $dbXML = CRM_Core_CodeGen_Util_Xml::parse($schemaPath); | |
22 | // print_r( $dbXML ); | |
23 | ||
24 | echo "Extracting database information\n"; | |
25 | $this->database = &$this->getDatabase($dbXML); | |
26 | // print_r( $this->database ); | |
27 | ||
28 | $this->classNames = array(); | |
29 | ||
30 | # TODO: peel DAO-specific stuff out of getTables, and spec reading into its own class | |
31 | echo "Extracting table information\n"; | |
32 | $this->tables = $this->getTables($dbXML, $this->database); | |
33 | ||
34 | $this->resolveForeignKeys($this->tables, $this->classNames); | |
35 | $this->tables = $this->orderTables($this->tables); | |
36 | ||
37 | // add archive tables here | |
38 | $archiveTables = array( ); | |
39 | foreach ($this->tables as $name => $table ) { | |
40 | if ( $table['archive'] == 'true' ) { | |
41 | $name = 'archive_' . $table['name']; | |
42 | $table['name'] = $name; | |
43 | $table['archive'] = 'false'; | |
44 | if ( isset($table['foreignKey']) ) { | |
45 | foreach ($table['foreignKey'] as $fkName => $fkValue) { | |
46 | if ($this->tables[$fkValue['table']]['archive'] == 'true') { | |
47 | $table['foreignKey'][$fkName]['table'] = 'archive_' . $table['foreignKey'][$fkName]['table']; | |
48 | $table['foreignKey'][$fkName]['uniqName'] = | |
49 | str_replace( 'FK_', 'FK_archive_', $table['foreignKey'][$fkName]['uniqName'] ); | |
50 | } | |
51 | } | |
52 | $archiveTables[$name] = $table; | |
53 | } | |
54 | } | |
55 | } | |
56 | } | |
57 | ||
58 | function &getDatabase(&$dbXML) { | |
59 | $database = array('name' => trim((string ) $dbXML->name)); | |
60 | ||
61 | $attributes = ''; | |
62 | $this->checkAndAppend($attributes, $dbXML, 'character_set', 'DEFAULT CHARACTER SET ', ''); | |
63 | $this->checkAndAppend($attributes, $dbXML, 'collate', 'COLLATE ', ''); | |
64 | $database['attributes'] = $attributes; | |
65 | ||
66 | $tableAttributes_modern = $tableAttributes_simple = ''; | |
67 | $this->checkAndAppend($tableAttributes_modern, $dbXML, 'table_type', 'ENGINE=', ''); | |
68 | $this->checkAndAppend($tableAttributes_simple, $dbXML, 'table_type', 'TYPE=', ''); | |
69 | $database['tableAttributes_modern'] = trim($tableAttributes_modern . ' ' . $attributes); | |
70 | $database['tableAttributes_simple'] = trim($tableAttributes_simple); | |
71 | ||
72 | $database['comment'] = $this->value('comment', $dbXML, ''); | |
73 | ||
74 | return $database; | |
75 | } | |
76 | ||
77 | function getTables($dbXML, &$database) { | |
78 | $tables = array(); | |
79 | foreach ($dbXML->tables as $tablesXML) { | |
80 | foreach ($tablesXML->table as $tableXML) { | |
81 | if ($this->value('drop', $tableXML, 0) > 0 and $this->value('drop', $tableXML, 0) <= $this->buildVersion) { | |
82 | continue; | |
83 | } | |
84 | ||
85 | if ($this->value('add', $tableXML, 0) <= $this->buildVersion) { | |
86 | $this->getTable($tableXML, $database, $tables); | |
87 | } | |
88 | } | |
89 | } | |
90 | ||
91 | return $tables; | |
92 | } | |
93 | ||
94 | function resolveForeignKeys(&$tables, &$classNames) { | |
95 | foreach (array_keys($tables) as $name) { | |
96 | $this->resolveForeignKey($tables, $classNames, $name); | |
97 | } | |
98 | } | |
99 | ||
100 | function resolveForeignKey(&$tables, &$classNames, $name) { | |
101 | if (!array_key_exists('foreignKey', $tables[$name])) { | |
102 | return; | |
103 | } | |
104 | ||
105 | foreach (array_keys($tables[$name]['foreignKey']) as $fkey) { | |
106 | $ftable = $tables[$name]['foreignKey'][$fkey]['table']; | |
107 | if (!array_key_exists($ftable, $classNames)) { | |
108 | echo "$ftable is not a valid foreign key table in $name\n"; | |
109 | continue; | |
110 | } | |
111 | $tables[$name]['foreignKey'][$fkey]['className'] = $classNames[$ftable]; | |
112 | $tables[$name]['foreignKey'][$fkey]['fileName'] = str_replace('_', '/', $classNames[$ftable]) . '.php'; | |
113 | $tables[$name]['fields'][$fkey]['FKClassName'] = $classNames[$ftable]; | |
114 | } | |
115 | } | |
116 | ||
117 | function orderTables(&$tables) { | |
118 | $ordered = array(); | |
119 | ||
120 | while (!empty($tables)) { | |
121 | foreach (array_keys($tables) as $name) { | |
122 | if ($this->validTable($tables, $ordered, $name)) { | |
123 | $ordered[$name] = $tables[$name]; | |
124 | unset($tables[$name]); | |
125 | } | |
126 | } | |
127 | } | |
128 | return $ordered; | |
129 | } | |
130 | ||
131 | function validTable(&$tables, &$valid, $name) { | |
132 | if (!array_key_exists('foreignKey', $tables[$name])) { | |
133 | return TRUE; | |
134 | } | |
135 | ||
136 | foreach (array_keys($tables[$name]['foreignKey']) as $fkey) { | |
137 | $ftable = $tables[$name]['foreignKey'][$fkey]['table']; | |
138 | if (!array_key_exists($ftable, $valid) && $ftable !== $name) { | |
139 | return FALSE; | |
140 | } | |
141 | } | |
142 | return TRUE; | |
143 | } | |
144 | ||
145 | function getTable($tableXML, &$database, &$tables) { | |
146 | $name = trim((string ) $tableXML->name); | |
147 | $klass = trim((string ) $tableXML->class); | |
148 | $base = $this->value('base', $tableXML); | |
149 | $sourceFile = "xml/schema/{$base}/{$klass}.xml"; | |
150 | $daoPath = "{$base}/DAO/"; | |
151 | $pre = str_replace('/', '_', $daoPath); | |
152 | $this->classNames[$name] = $pre . $klass; | |
153 | ||
154 | $localizable = FALSE; | |
155 | foreach ($tableXML->field as $fieldXML) { | |
156 | if ($fieldXML->localizable) { | |
157 | $localizable = TRUE; | |
158 | break; | |
159 | } | |
160 | } | |
161 | ||
162 | $table = array( | |
163 | 'name' => $name, | |
164 | 'base' => $daoPath, | |
165 | 'sourceFile' => $sourceFile, | |
166 | 'fileName' => $klass . '.php', | |
167 | 'objectName' => $klass, | |
168 | 'labelName' => substr($name, 8), | |
169 | 'className' => $this->classNames[$name], | |
170 | 'attributes_simple' => trim($database['tableAttributes_simple']), | |
171 | 'attributes_modern' => trim($database['tableAttributes_modern']), | |
172 | 'comment' => $this->value('comment', $tableXML), | |
173 | 'localizable' => $localizable, | |
174 | 'log' => $this->value('log', $tableXML, 'false'), | |
175 | 'archive' => $this->value('archive', $tableXML, 'false'), | |
176 | ); | |
177 | ||
178 | $fields = array(); | |
179 | foreach ($tableXML->field as $fieldXML) { | |
180 | if ($this->value('drop', $fieldXML, 0) > 0 and $this->value('drop', $fieldXML, 0) <= $this->buildVersion) { | |
181 | continue; | |
182 | } | |
183 | ||
184 | if ($this->value('add', $fieldXML, 0) <= $this->buildVersion) { | |
185 | $this->getField($fieldXML, $fields); | |
186 | } | |
187 | } | |
188 | ||
189 | $table['fields'] = &$fields; | |
5e434adf ARW |
190 | |
191 | if ($this->value('primaryKey', $tableXML)) { | |
192 | $this->getPrimaryKey($tableXML->primaryKey, $fields, $table); | |
193 | } | |
194 | ||
195 | // some kind of refresh? | |
196 | CRM_Core_Config::singleton(FALSE); | |
197 | if ($this->value('index', $tableXML)) { | |
198 | $index = array(); | |
199 | foreach ($tableXML->index as $indexXML) { | |
200 | if ($this->value('drop', $indexXML, 0) > 0 and $this->value('drop', $indexXML, 0) <= $this->buildVersion) { | |
201 | continue; | |
202 | } | |
203 | ||
204 | $this->getIndex($indexXML, $fields, $index); | |
205 | } | |
206 | $table['index'] = &$index; | |
207 | } | |
208 | ||
209 | if ($this->value('foreignKey', $tableXML)) { | |
210 | $foreign = array(); | |
211 | foreach ($tableXML->foreignKey as $foreignXML) { | |
212 | // print_r($foreignXML); | |
213 | ||
214 | if ($this->value('drop', $foreignXML, 0) > 0 and $this->value('drop', $foreignXML, 0) <= $this->buildVersion) { | |
215 | continue; | |
216 | } | |
217 | if ($this->value('add', $foreignXML, 0) <= $this->buildVersion) { | |
218 | $this->getForeignKey($foreignXML, $fields, $foreign, $name); | |
219 | } | |
220 | } | |
221 | $table['foreignKey'] = &$foreign; | |
222 | } | |
223 | ||
224 | if ($this->value('dynamicForeignKey', $tableXML)) { | |
225 | $dynamicForeign = array(); | |
226 | foreach ($tableXML->dynamicForeignKey as $foreignXML) { | |
227 | if ($this->value('drop', $foreignXML, 0) > 0 and $this->value('drop', $foreignXML, 0) <= $this->buildVersion) { | |
228 | continue; | |
229 | } | |
230 | if ($this->value('add', $foreignXML, 0) <= $this->buildVersion) { | |
231 | $this->getDynamicForeignKey($foreignXML, $dynamicForeign, $name); | |
232 | } | |
233 | } | |
234 | $table['dynamicForeignKey'] = $dynamicForeign; | |
235 | } | |
236 | ||
237 | $tables[$name] = &$table; | |
238 | return; | |
239 | } | |
240 | ||
241 | function getField(&$fieldXML, &$fields) { | |
242 | $name = trim((string ) $fieldXML->name); | |
243 | $field = array('name' => $name, 'localizable' => $fieldXML->localizable); | |
244 | $type = (string ) $fieldXML->type; | |
245 | switch ($type) { | |
246 | case 'varchar': | |
247 | case 'char': | |
248 | $field['length'] = (int) $fieldXML->length; | |
249 | $field['sqlType'] = "$type({$field['length']})"; | |
250 | $field['phpType'] = 'string'; | |
251 | $field['crmType'] = 'CRM_Utils_Type::T_STRING'; | |
252 | $field['size'] = $this->getSize($fieldXML); | |
253 | break; | |
254 | ||
5e434adf ARW |
255 | case 'text': |
256 | $field['sqlType'] = $field['phpType'] = $type; | |
257 | $field['crmType'] = 'CRM_Utils_Type::T_' . strtoupper($type); | |
5e545f38 CW |
258 | // CRM-13497 see fixme below |
259 | $field['rows'] = isset($fieldXML->html) ? $this->value('rows', $fieldXML->html) : NULL; | |
260 | $field['cols'] = isset($fieldXML->html) ? $this->value('cols', $fieldXML->html) : NULL; | |
261 | break; | |
5e434adf ARW |
262 | break; |
263 | ||
264 | case 'datetime': | |
265 | $field['sqlType'] = $field['phpType'] = $type; | |
266 | $field['crmType'] = 'CRM_Utils_Type::T_DATE + CRM_Utils_Type::T_TIME'; | |
267 | break; | |
268 | ||
269 | case 'boolean': | |
270 | // need this case since some versions of mysql do not have boolean as a valid column type and hence it | |
271 | // is changed to tinyint. hopefully after 2 yrs this case can be removed. | |
272 | $field['sqlType'] = 'tinyint'; | |
273 | $field['phpType'] = $type; | |
274 | $field['crmType'] = 'CRM_Utils_Type::T_' . strtoupper($type); | |
275 | break; | |
276 | ||
277 | case 'decimal': | |
278 | $length = $fieldXML->length ? $fieldXML->length : '20,2'; | |
279 | $field['sqlType'] = 'decimal(' . $length . ')'; | |
280 | $field['phpType'] = 'float'; | |
281 | $field['crmType'] = 'CRM_Utils_Type::T_MONEY'; | |
ac5f2ccd | 282 | $field['precision'] = $length; |
5e434adf ARW |
283 | break; |
284 | ||
285 | case 'float': | |
286 | $field['sqlType'] = 'double'; | |
287 | $field['phpType'] = 'float'; | |
288 | $field['crmType'] = 'CRM_Utils_Type::T_FLOAT'; | |
289 | break; | |
290 | ||
291 | default: | |
292 | $field['sqlType'] = $field['phpType'] = $type; | |
293 | if ($type == 'int unsigned') { | |
294 | $field['crmType'] = 'CRM_Utils_Type::T_INT'; | |
295 | } | |
296 | else { | |
297 | $field['crmType'] = 'CRM_Utils_Type::T_' . strtoupper($type); | |
298 | } | |
299 | break; | |
300 | } | |
301 | ||
302 | $field['required'] = $this->value('required', $fieldXML); | |
303 | $field['collate'] = $this->value('collate', $fieldXML); | |
304 | $field['comment'] = $this->value('comment', $fieldXML); | |
305 | $field['default'] = $this->value('default', $fieldXML); | |
306 | $field['import'] = $this->value('import', $fieldXML); | |
307 | if ($this->value('export', $fieldXML)) { | |
308 | $field['export'] = $this->value('export', $fieldXML); | |
309 | } | |
310 | else { | |
311 | $field['export'] = $this->value('import', $fieldXML); | |
312 | } | |
313 | $field['rule'] = $this->value('rule', $fieldXML); | |
314 | $field['title'] = $this->value('title', $fieldXML); | |
315 | if (!$field['title']) { | |
316 | $field['title'] = $this->composeTitle($name); | |
317 | } | |
318 | $field['headerPattern'] = $this->value('headerPattern', $fieldXML); | |
319 | $field['dataPattern'] = $this->value('dataPattern', $fieldXML); | |
320 | $field['uniqueName'] = $this->value('uniqueName', $fieldXML); | |
5e545f38 CW |
321 | $field['html'] = $this->value('html', $fieldXML); |
322 | if (!empty($field['html'])) { | |
323 | $validOptions = array( | |
324 | 'type', | |
325 | /* Fixme: prior to CRM-13497 these were in a flat structure | |
326 | // CRM-13497 moved them to be nested within 'html' but there's no point | |
327 | // making that change in the DAOs right now since we are in the process of | |
328 | // moving to docrtine anyway. | |
329 | // So translating from nested xml back to flat structure for now. | |
330 | 'rows', | |
331 | 'cols', | |
332 | 'size', */ | |
333 | ); | |
334 | $field['html'] = array(); | |
335 | foreach ($validOptions as $htmlOption) { | |
336 | if(!empty($fieldXML->html->$htmlOption)){ | |
337 | $field['html'][$htmlOption] = $this->value($htmlOption, $fieldXML->html); | |
338 | } | |
339 | } | |
340 | } | |
5e434adf ARW |
341 | $field['pseudoconstant'] = $this->value('pseudoconstant', $fieldXML); |
342 | if(!empty($field['pseudoconstant'])){ | |
343 | //ok this is a bit long-winded but it gets there & is consistent with above approach | |
344 | $field['pseudoconstant'] = array(); | |
345 | $validOptions = array( | |
346 | // Fields can specify EITHER optionGroupName OR table, not both | |
347 | // (since declaring optionGroupName means we are using the civicrm_option_value table) | |
348 | 'optionGroupName', | |
349 | 'table', | |
350 | // If table is specified, keyColumn and labelColumn are also required | |
351 | 'keyColumn', | |
352 | 'labelColumn', | |
353 | // Non-translated machine name for programmatic lookup. Defaults to 'name' if that column exists | |
354 | 'nameColumn', | |
355 | // Where clause snippet (will be joined to the rest of the query with AND operator) | |
356 | 'condition', | |
cc6443c4 | 357 | // callback funtion incase of static arrays |
358 | 'callback', | |
5e434adf ARW |
359 | ); |
360 | foreach ($validOptions as $pseudoOption) { | |
361 | if(!empty($fieldXML->pseudoconstant->$pseudoOption)){ | |
362 | $field['pseudoconstant'][$pseudoOption] = $this->value($pseudoOption, $fieldXML->pseudoconstant); | |
363 | } | |
364 | } | |
365 | // For now, fields that have option lists that are not in the db can simply | |
366 | // declare an empty pseudoconstant tag and we'll add this placeholder. | |
367 | // That field's BAO::buildOptions fn will need to be responsible for generating the option list | |
368 | if (empty($field['pseudoconstant'])) { | |
369 | $field['pseudoconstant'] = 'not in database'; | |
370 | } | |
371 | } | |
372 | $fields[$name] = &$field; | |
373 | } | |
374 | ||
375 | function composeTitle($name) { | |
376 | $names = explode('_', strtolower($name)); | |
377 | $title = ''; | |
378 | for ($i = 0; $i < count($names); $i++) { | |
379 | if ($names[$i] === 'id' || $names[$i] === 'is') { | |
380 | // id's do not get titles | |
381 | return NULL; | |
382 | } | |
383 | ||
384 | if ($names[$i] === 'im') { | |
385 | $names[$i] = 'IM'; | |
386 | } | |
387 | else { | |
388 | $names[$i] = ucfirst(trim($names[$i])); | |
389 | } | |
390 | ||
391 | $title = $title . ' ' . $names[$i]; | |
392 | } | |
393 | return trim($title); | |
394 | } | |
395 | ||
396 | function getPrimaryKey(&$primaryXML, &$fields, &$table) { | |
397 | $name = trim((string ) $primaryXML->name); | |
398 | ||
399 | /** need to make sure there is a field of type name */ | |
400 | if (!array_key_exists($name, $fields)) { | |
401 | echo "primary key $name in $table->name does not have a field definition, ignoring\n"; | |
402 | return; | |
403 | } | |
404 | ||
405 | // set the autoincrement property of the field | |
406 | $auto = $this->value('autoincrement', $primaryXML); | |
407 | $fields[$name]['autoincrement'] = $auto; | |
408 | $primaryKey = array( | |
409 | 'name' => $name, | |
410 | 'autoincrement' => $auto, | |
411 | ); | |
412 | $table['primaryKey'] = &$primaryKey; | |
413 | } | |
414 | ||
415 | function getIndex(&$indexXML, &$fields, &$indices) { | |
416 | //echo "\n\n*******************************************************\n"; | |
417 | //echo "entering getIndex\n"; | |
418 | ||
419 | $index = array(); | |
420 | // empty index name is fine | |
421 | $indexName = trim((string)$indexXML->name); | |
422 | $index['name'] = $indexName; | |
423 | $index['field'] = array(); | |
424 | ||
425 | // populate fields | |
426 | foreach ($indexXML->fieldName as $v) { | |
427 | $fieldName = (string)($v); | |
428 | $length = (string)($v['length']); | |
429 | if (strlen($length) > 0) { | |
430 | $fieldName = "$fieldName($length)"; | |
431 | } | |
432 | $index['field'][] = $fieldName; | |
433 | } | |
434 | ||
435 | $index['localizable'] = FALSE; | |
436 | foreach ($index['field'] as $fieldName) { | |
437 | if (isset($fields[$fieldName]) and $fields[$fieldName]['localizable']) { | |
438 | $index['localizable'] = TRUE; | |
439 | break; | |
440 | } | |
441 | } | |
442 | ||
443 | // check for unique index | |
444 | if ($this->value('unique', $indexXML)) { | |
445 | $index['unique'] = TRUE; | |
446 | } | |
447 | ||
448 | //echo "\$index = \n"; | |
449 | //print_r($index); | |
450 | ||
451 | // field array cannot be empty | |
452 | if (empty($index['field'])) { | |
453 | echo "No fields defined for index $indexName\n"; | |
454 | return; | |
455 | } | |
456 | ||
457 | // all fieldnames have to be defined and should exist in schema. | |
458 | foreach ($index['field'] as $fieldName) { | |
459 | if (!$fieldName) { | |
460 | echo "Invalid field defination for index $indexName\n"; | |
461 | return; | |
462 | } | |
463 | $parenOffset = strpos($fieldName, '('); | |
464 | if ($parenOffset > 0) { | |
465 | $fieldName = substr($fieldName, 0, $parenOffset); | |
466 | } | |
467 | if (!array_key_exists($fieldName, $fields)) { | |
468 | echo "Table does not contain $fieldName\n"; | |
469 | print_r($fields); | |
470 | exit(); | |
471 | } | |
472 | } | |
473 | $indices[$indexName] = &$index; | |
474 | } | |
475 | ||
476 | function getForeignKey(&$foreignXML, &$fields, &$foreignKeys, &$currentTableName) { | |
477 | $name = trim((string ) $foreignXML->name); | |
478 | ||
479 | /** need to make sure there is a field of type name */ | |
480 | if (!array_key_exists($name, $fields)) { | |
481 | echo "foreign $name in $currentTableName does not have a field definition, ignoring\n"; | |
482 | return; | |
483 | } | |
484 | ||
485 | /** need to check for existence of table and key **/ | |
486 | $table = trim($this->value('table', $foreignXML)); | |
487 | $foreignKey = array( | |
488 | 'name' => $name, | |
489 | 'table' => $table, | |
490 | 'uniqName' => "FK_{$currentTableName}_{$name}", | |
491 | 'key' => trim($this->value('key', $foreignXML)), | |
492 | 'import' => $this->value('import', $foreignXML, FALSE), | |
493 | 'export' => $this->value('import', $foreignXML, FALSE), | |
494 | // we do this matching in a seperate phase (resolveForeignKeys) | |
495 | 'className' => NULL, | |
496 | 'onDelete' => $this->value('onDelete', $foreignXML, FALSE), | |
497 | ); | |
498 | $foreignKeys[$name] = &$foreignKey; | |
499 | } | |
500 | ||
501 | function getDynamicForeignKey(&$foreignXML, &$dynamicForeignKeys) { | |
502 | $foreignKey = array( | |
503 | 'idColumn' => trim($foreignXML->idColumn), | |
504 | 'typeColumn' => trim($foreignXML->typeColumn), | |
505 | 'key' => trim($this->value('key', $foreignXML)), | |
506 | ); | |
507 | $dynamicForeignKeys[] = $foreignKey; | |
508 | } | |
509 | ||
510 | protected function value($key, &$object, $default = NULL) { | |
511 | if (isset($object->$key)) { | |
512 | return (string ) $object->$key; | |
513 | } | |
514 | return $default; | |
515 | } | |
516 | ||
517 | protected function checkAndAppend(&$attributes, &$object, $name, $pre = NULL, $post = NULL) { | |
518 | if (!isset($object->$name)) { | |
519 | return; | |
520 | } | |
521 | ||
522 | $value = $pre . trim($object->$name) . $post; | |
523 | $this->append($attributes, ' ', trim($value)); | |
524 | } | |
525 | ||
526 | protected function append(&$str, $delim, $name) { | |
527 | if (empty($name)) { | |
528 | return; | |
529 | } | |
530 | ||
531 | if (is_array($name)) { | |
532 | foreach ($name as $n) { | |
533 | if (empty($n)) { | |
534 | continue; | |
535 | } | |
536 | if (empty($str)) { | |
537 | $str = $n; | |
538 | } | |
539 | else { | |
540 | $str .= $delim . $n; | |
541 | } | |
542 | } | |
543 | } | |
544 | else { | |
545 | if (empty($str)) { | |
546 | $str = $name; | |
547 | } | |
548 | else { | |
549 | $str .= $delim . $name; | |
550 | } | |
551 | } | |
552 | } | |
553 | ||
554 | /** | |
555 | * Sets the size property of a textfield | |
556 | * See constants defined in CRM_Utils_Type for possible values | |
557 | */ | |
558 | protected function getSize($fieldXML) { | |
559 | // Extract from <size> tag if supplied | |
5e545f38 CW |
560 | if (!empty($fieldXML->html) && $this->value('size', $fieldXML->html)) { |
561 | $const = 'CRM_Utils_Type::' . strtoupper($fieldXML->html->size); | |
5e434adf ARW |
562 | if (defined($const)) { |
563 | return $const; | |
564 | } | |
565 | } | |
566 | // Infer from <length> tag if <size> was not explicitly set or was invalid | |
567 | ||
568 | // This map is slightly different from CRM_Core_Form_Renderer::$_sizeMapper | |
569 | // Because we usually want fields to render as smaller than their maxlength | |
570 | $sizes = array( | |
571 | 2 => 'TWO', | |
572 | 4 => 'FOUR', | |
573 | 6 => 'SIX', | |
574 | 8 => 'EIGHT', | |
575 | 16 => 'TWELVE', | |
576 | 32 => 'MEDIUM', | |
577 | 64 => 'BIG', | |
578 | ); | |
579 | foreach ($sizes as $length => $name) { | |
580 | if ($fieldXML->length <= $length) { | |
581 | return "CRM_Utils_Type::$name"; | |
582 | } | |
583 | } | |
584 | return 'CRM_Utils_Type::HUGE'; | |
585 | } | |
586 | } |