[BUGFIX] IRRE: Selected items remain in selector with foreign_unique
authorStanislas Rolland <typo3@sjbr.ca>
Wed, 8 Feb 2012 05:15:32 +0000 (00:15 -0500)
committerStanislas Rolland <typo3@sjbr.ca>
Fri, 10 Feb 2012 17:24:34 +0000 (18:24 +0100)
Problem: When an inline field is defined as unique (foreign_unique
is set), selected items are removed neither from the inline record
selector, nor from the children record selectors.

Solution: Remove the used records from all selectors. Also, when
updating and collapseAll is set, remove records already used from
the child record after its ajax-retrieval/expansion.

Change-Id: I84c7fa3bfd8139f07604c05ab80c5bf4d90af736
Fixes: #21102
Releases: 4.5, 4.6, 4.7
Reviewed-on: http://review.typo3.org/8955
Reviewed-by: Tolleiv Nietsch
Tested-by: Tolleiv Nietsch
Reviewed-by: Stanislas Rolland
Tested-by: Stanislas Rolland
t3lib/class.t3lib_tceforms.php
t3lib/class.t3lib_tceforms_inline.php
t3lib/jsfunc.inline.js

index 47e8bb7..dd0af4c 100644 (file)
@@ -1471,8 +1471,8 @@ class t3lib_TCEforms {
                $inlineParent = $this->inline->getStructureLevel(-1);
                if (is_array($inlineParent) && $inlineParent['uid']) {
                        if ($inlineParent['config']['foreign_table'] == $table && $inlineParent['config']['foreign_unique'] == $field) {
-                               $uniqueIds = $this->inline->inlineData['unique'][$this->inline->inlineNames['object'] . '[' . $table . ']']['used'];
-                               $PA['fieldChangeFunc']['inlineUnique'] = "inline.updateUnique(this,'" . $this->inline->inlineNames['object'] . '[' . $table . "]','" . $this->inline->inlineNames['form'] . "','" . $row['uid'] . "');";
+                               $uniqueIds = $this->inline->inlineData['unique'][$this->inline->inlineNames['object'] . t3lib_TCEforms_inline::Structure_Separator . $table]['used'];
+                               $PA['fieldChangeFunc']['inlineUnique'] = "inline.updateUnique(this,'" . $this->inline->inlineNames['object'] . t3lib_TCEforms_inline::Structure_Separator . $table . "','" . $this->inline->inlineNames['form'] . "','" . $row['uid'] . "');";
                        }
                                // hide uid of parent record for symmetric relations
                        if ($inlineParent['config']['foreign_table'] == $table && ($inlineParent['config']['foreign_field'] == $field || $inlineParent['config']['symmetric_field'] == $field)) {
@@ -3589,7 +3589,7 @@ class t3lib_TCEforms {
                                $inlineParent = $this->inline->getStructureLevel(-1);
                                if (is_array($inlineParent) && $inlineParent['uid']) {
                                        if ($inlineParent['config']['foreign_table'] == $table && $inlineParent['config']['foreign_unique'] == $field) {
-                                               $objectPrefix = $this->inline->inlineNames['object'] . '[' . $table . ']';
+                                               $objectPrefix = $this->inline->inlineNames['object'] . t3lib_TCEforms_inline::Structure_Separator . $table;
                                                $aOnClickInline = $objectPrefix . '|inline.checkUniqueElement|inline.setUniqueElement';
                                                $rOnClickInline = 'inline.revertUnique(\'' . $objectPrefix . '\',null,\'' . $uid . '\');';
                                        }
index 0b7366c..a4d8a66 100644 (file)
@@ -1231,7 +1231,9 @@ class t3lib_TCEforms_inline {
                                'inline.domAddRecordDetails(\'' . $domObjectId . '\',\'' . $objectPrefix . '\',' . ($expandSingle ? '1' : '0') . ',json.data);',
                        )
                );
-
+               if ($config['foreign_unique']) {
+                       $jsonArray['scriptCall'][] = 'inline.removeUsed(\'' . $objectPrefix . '\',\'' . $record['uid'] . '\');';
+               }
                $this->getCommonScriptCalls($jsonArray, $config);
                        // Collapse all other records if requested:
                if (!$collapseAll && $expandSingle) {
index abfff23..95b6182 100644 (file)
@@ -316,36 +316,71 @@ var inline = {
                // alert(objectId+'/'+table+'/'+uid+'/'+recordUid);
                this.setUnique(objectId, recordUid, uid);
        },
-
+               // Remove all select items already used
+               // from a newly retrieved/expanded record
+       removeUsed: function(objectId, recordUid) {
+               if (this.data.unique && this.data.unique[objectId]) {
+                       var unique = this.data.unique[objectId];
+                       if (unique.type == 'select') {
+                               var formName = this.prependFormFieldNames+this.parseObjectId('parts', objectId, 3, 1, true);
+                               var formObj = document.getElementsByName(formName);
+                               var recordObj = document.getElementsByName(this.prependFormFieldNames+'['+unique.table+']['+recordUid+']['+unique.field+']');
+                               var values = $H(unique.used).values();
+                               if (recordObj.length) {
+                                       var selectedValue = recordObj[0].options[recordObj[0].selectedIndex].value;
+                                       for (var i=0; i<values.length; i++) {
+                                               if (values[i] != selectedValue) {
+                                                       this.removeSelectOption(recordObj[0], values[i]);
+                                               }
+                                       }
+                               }
+                       }
+               }
+       },
                // this function is applied to a newly inserted record by AJAX
                // it removes the used select items, that should be unique
        setUnique: function(objectId, recordUid, selectedValue) {
                if (this.data.unique && this.data.unique[objectId]) {
                        var unique = this.data.unique[objectId];
-
                        if (unique.type == 'select') {
-                                       // remove used items from each select-field of the child records
                                if (!(unique.selector && unique.max == -1)) {
                                        var formName = this.prependFormFieldNames+this.parseObjectId('parts', objectId, 3, 1, true);
-
-                                       var fieldObj = document.getElementsByName(elName);
+                                       var formObj = document.getElementsByName(formName);
+                                       var recordObj = document.getElementsByName(this.prependFormFieldNames+'['+unique.table+']['+recordUid+']['+unique.field+']');
                                        var values = $H(unique.used).values();
-
-                                       if (fieldObj.length) {
+                                       var selector = $(objectId+'_selector');
+                                       if (selector.length) {
                                                        // remove all items from the new select-item which are already used in other children
-                                               for (var i=0; i<values.length; i++) this.removeSelectOption(fieldObj[0], values[i]);
-                                                       // set the selected item automatically to the first of the remaining items if no selector is used
-                                               if (!unique.selector) {
-                                                       selectedValue = fieldObj[0].options[0].value;
-                                                       fieldObj[0].options[0].selected = true;
-                                                       this.updateUnique(fieldObj[0], objectId, formName, recordUid);
-                                                       this.handleChangedField(fieldObj[0], objectId+'['+recordUid+']');
+                                               if (recordObj.length) {
+                                                       for (var i=0; i<values.length; i++) {
+                                                               this.removeSelectOption(recordObj[0], values[i]);
+                                                       }
+                                                               // set the selected item automatically to the first of the remaining items if no selector is used
+                                                       if (!unique.selector) {
+                                                               selectedValue = recordObj[0].options[0].value;
+                                                               recordObj[0].options[0].selected = true;
+                                                               this.updateUnique(recordObj[0], objectId, formName, recordUid);
+                                                               this.handleChangedField(recordObj[0], objectId+'['+recordUid+']');
+                                                       }
+                                               }
+                                               for (var i=0; i<values.length; i++) {
+                                                       this.removeSelectOption(selector, values[i]);
                                                }
                                                if (typeof this.data.unique[objectId].used.length != 'undefined') {
                                                        this.data.unique[objectId].used = {};
                                                }
                                                this.data.unique[objectId].used[recordUid] = selectedValue;
                                        }
+                                               // remove the newly used item from each select-field of the child records
+                                       if (formObj.length && selectedValue) {
+                                               var records = formObj[0].value.split(',');
+                                               for (var i=0; i<records.length; i++) {
+                                                       recordObj = document.getElementsByName(this.prependFormFieldNames+'['+unique.table+']['+records[i]+']['+unique.field+']');
+                                                       if (recordObj.length && records[i] != recordUid) {
+                                                               this.removeSelectOption(recordObj[0], selectedValue);
+                                                       }
+                                               }
+                                       }
                                }
                        } else if (unique.type == 'groupdb') {
                                        // add the new record to the used items: