[FEATURE] Enable TCA type field to depend on field of foreign table
authorIngmar Schlecht <ingmar@typo3.org>
Fri, 6 Jan 2012 16:08:52 +0000 (17:08 +0100)
committerOliver Hader <oliver@typo3.org>
Tue, 31 Jan 2012 13:52:46 +0000 (14:52 +0100)
TCA type fields can now refer to a field on a foreign record with a colon-separated
syntax (e.g. uid_local:type).  This will be used by sys_file_references table, where
the type (showItems) depends on a value on the foreign record (sys_file)

Change-Id: I7d153325a64224012bddd4047fc73724ed6648f3
Releases: 4.7
Resolves: #33045
Reviewed-on: http://review.typo3.org/7706
Reviewed-by: Oliver Hader
Tested-by: Oliver Hader
t3lib/class.t3lib_befunc.php
t3lib/class.t3lib_tceforms.php

index 2cfe525..6ff0d7a 100644 (file)
@@ -765,23 +765,70 @@ final class t3lib_BEfunc {
         * If no "type" field is configured in the "ctrl"-section of the $GLOBALS['TCA'] for the table, zero is used.
         * If zero is not an index in the "types" section of $GLOBALS['TCA'] for the table, then the $fieldValue returned will default to 1 (no matter if that is an index or not)
         *
+        * Note: This method is very similar to t3lib_TCEforms::getRTypeNum(), however, it has two differences:
+        *       1) The method in TCEForms also takes care of localization (which is difficult to do here as the whole infrastructure for language overlays is only in TCEforms).
+        *       2) The $rec array looks different in TCEForms, as in there it's not the raw record but the t3lib_transferdata version of it, which changes e.g. how "select"
+        *          and "group" field values are stored, which makes different processing of the "foreign pointer field" type field variant necessary.
+        *
         * @param       string          Table name present in TCA
         * @param       array           Record from $table
         * @return      string          Field value
         * @see getTCAtypes()
         */
-       public static function getTCAtypeValue($table, $rec) {
+       public static function getTCAtypeValue($table, $row) {
+
+               $typeNum = 0;
 
-                       // If no field-value, set it to zero. If there is no type matching the field-value (which now may be zero...) test field-value '1' as default.
                t3lib_div::loadTCA($table);
                if ($GLOBALS['TCA'][$table]) {
                        $field = $GLOBALS['TCA'][$table]['ctrl']['type'];
-                       $fieldValue = $field ? ($rec[$field] ? $rec[$field] : 0) : 0;
-                       if (!is_array($GLOBALS['TCA'][$table]['types'][$fieldValue])) {
-                               $fieldValue = 1;
+
+                       if (strpos($field, ':') !== FALSE) {
+                               list($pointerField, $foreignTableTypeField) = explode(':', $field);
+
+                               // Get field value from database if field is not in the $row array
+                               if (!isset($row[$pointerField])) {
+                                       $localRow = t3lib_BEfunc::getRecord($table, $row['uid'], $pointerField);
+                                       $foreignUid = $localRow[$pointerField];
+                               } else {
+                                       $foreignUid = $row[$pointerField];
+                               }
+
+                               if ($foreignUid) {
+                                       $fieldConfig = $GLOBALS['TCA'][$table]['columns'][$pointerField]['config'];
+                                       $relationType = $fieldConfig['type'];
+                                       if ($relationType === 'select') {
+                                               $foreignTable = $fieldConfig['foreign_table'];
+                                       } elseif ($relationType === 'group') {
+                                               $allowedTables = explode(',', $fieldConfig['allowed']);
+                                               $foreignTable = $allowedTables[0]; // Always take the first configured table.
+                                       } else {
+                                               throw new RuntimeException('TCA foreign field pointer fields are only allowed to be used with group or select field types.', 1325862240);
+                                       }
+
+                                       $foreignRow = t3lib_BEfunc::getRecord($foreignTable, $foreignUid, $foreignTableTypeField);
+
+                                       if ($foreignRow[$foreignTableTypeField]) {
+                                               $typeNum = $foreignRow[$foreignTableTypeField];
+                                       }
+                               }
+                       } else {
+                               $typeNum = $row[$field];
+                       }
+
+                       if (!strcmp($typeNum, '')) {  // If that value is an empty string, set it to "0" (zero)
+                               $typeNum = 0;
                        }
-                       return $fieldValue;
                }
+
+               // If current typeNum doesn't exist, set it to 0 (or to 1 for historical reasons, if 0 doesn't exist)
+               if (!$GLOBALS['TCA'][$table]['types'][$typeNum]) {
+                       $typeNum = $GLOBALS['TCA'][$table]['types']["0"] ? 0 : 1;
+               }
+
+               $typeNum = (string)$typeNum; // Force to string. Necessary for eg '-1' to be recognized as a type value.
+
+               return $typeNum;
        }
 
        /**
index 409992b..d77fcd3 100644 (file)
@@ -716,9 +716,15 @@ class t3lib_TCEforms {
                                        $PA['itemFormElValue'] = $this->defaultLanguageData[$table . ':' . $row['uid']][$field];
                                }
 
+                               if(strpos($GLOBALS['TCA'][$table]['ctrl']['type'], ':') === FALSE) {
+                                       $typeField = $GLOBALS['TCA'][$table]['ctrl']['type'];
+                               } else {
+                                       $typeField = substr($GLOBALS['TCA'][$table]['ctrl']['type'], 0, strpos($GLOBALS['TCA'][$table]['ctrl']['type'],':'));
+                               }
+
                                        // Create a JavaScript code line which will ask the user to save/update the form due to changing the element. This is used for eg. "type" fields and others configured with "requestUpdate"
                                if (
-                                       ($GLOBALS['TCA'][$table]['ctrl']['type'] && !strcmp($field, $GLOBALS['TCA'][$table]['ctrl']['type']))
+                                       ($GLOBALS['TCA'][$table]['ctrl']['type'] && !strcmp($field, $typeField))
                                        || ($GLOBALS['TCA'][$table]['ctrl']['requestUpdate']
                                                && t3lib_div::inList($GLOBALS['TCA'][$table]['ctrl']['requestUpdate'], $field))) {
                                        if ($GLOBALS['BE_USER']->jsConfirmation(1)) {
@@ -3086,24 +3092,56 @@ class t3lib_TCEforms {
         * @return      string          Return the "type" value for this record, ready to pick a "types" configuration from the $GLOBALS['TCA'] array.
         */
        function getRTypeNum($table, $row) {
-                       // If there is a "type" field configured...
-               if ($GLOBALS['TCA'][$table]['ctrl']['type']) {
-                       $typeFieldName = $GLOBALS['TCA'][$table]['ctrl']['type'];
-                       $typeFieldConfig = $GLOBALS['TCA'][$table]['columns'][$typeFieldName];
-                       $typeNum = $this->getLanguageOverlayRawValue($table, $row, $typeFieldName, $typeFieldConfig);
-                       if (!strcmp($typeNum, '')) {
-                               $typeNum = 0;
-                       } // If that value is an empty string, set it to "0" (zero)
-               } else {
-                       $typeNum = 0; // If no "type" field, then set to "0" (zero)
+
+               $typeNum = 0;
+
+               $field = $GLOBALS['TCA'][$table]['ctrl']['type'];
+               if ($field) {
+                       if (strpos($field, ':') !== FALSE) {
+                               list($pointerField, $foreignTypeField) = explode(':', $field);
+
+                               $fieldConfig = $GLOBALS['TCA'][$table]['columns'][$pointerField]['config'];
+                               $relationType = $fieldConfig['type'];
+                               if ($relationType === 'select') {
+                                       $foreignUid = $row[$pointerField];
+                                       $foreignTable = $fieldConfig['foreign_table'];
+                               } elseif ($relationType === 'group') {
+                                       $values = $this->extractValuesOnlyFromValueLabelList($row[$pointerField]);
+                                       list(,$foreignUid) = t3lib_div::revExplode('_', $values[0], 2);
+                                       $allowedTables = explode(',', $fieldConfig['allowed']);
+                                       $foreignTable = $allowedTables[0]; // Always take the first configured table.
+                               } else {
+                                       throw new RuntimeException('TCA Foreign field pointer fields are only allowed to be used with group or select field types.', 1325861239);
+                               }
+
+                               if($foreignUid) {
+                                       $foreignRow = t3lib_BEfunc::getRecord($foreignTable, $foreignUid, $foreignTypeField);
+
+                                       t3lib_div::loadTCA($foreignTable);
+                                       $this->registerDefaultLanguageData($foreignTable, $foreignRow);
+
+                                       if($foreignRow[$foreignTypeField]) {
+                                               $foreignTypeFieldConfig = $GLOBALS['TCA'][$table]['columns'][$field];
+                                               $typeNum = $this->getLanguageOverlayRawValue($foreignTable, $foreignRow, $foreignTypeField, $foreignTypeFieldConfig);
+                                       }
+                               }
+                       } else {
+                               $typeFieldConfig = $GLOBALS['TCA'][$table]['columns'][$field];
+                               $typeNum = $this->getLanguageOverlayRawValue($table, $row, $field, $typeFieldConfig);
+                       }
+               }
+
+               if (!strcmp($typeNum, '')) {  // If that value is an empty string, set it to "0" (zero)
+                       $typeNum = 0;
                }
 
-               $typeNum = (string) $typeNum; // Force to string. Necessary for eg '-1' to be recognized as a type value.
+               // If current typeNum doesn't exist, set it to 0 (or to 1 for historical reasons, if 0 doesn't exist)
                if (!$GLOBALS['TCA'][$table]['types'][$typeNum]) {
-                               // However, if the type "0" is not found in the "types" array, then default to "1" (for historical reasons)
-                       $typeNum = 1;
+                       $typeNum = $GLOBALS['TCA'][$table]['types']["0"] ? 0 : 1;
                }
 
+               $typeNum = (string)$typeNum; // Force to string. Necessary for eg '-1' to be recognized as a type value.
+
                return $typeNum;
        }