Feature #16887 » irre_RC1_stress_2.patch
t3lib/class.t3lib_tceforms.php (Arbeitskopie) | ||
---|---|---|
// add JS required for inline fields
|
||
if (count($this->inline->inlineData)) {
|
||
// print_r($this->inline->inlineData);
|
||
$out .= '
|
||
inline.addToDataArray('.$this->inline->getJSON($this->inline->inlineData).');
|
||
';
|
t3lib/jsfunc.inline.js (Arbeitskopie) | ||
---|---|---|
prependFormFieldNames: 'data',
|
||
noTitleString: '[No title]',
|
||
data: {},
|
||
|
||
addToDataArray: function(object) {
|
||
for (var i in object) {
|
||
this.data[i] = $H(this.data[i]).merge(object[i]);
|
||
... | ... | |
setPrependFormFieldNames: function(value) {
|
||
this.prependFormFieldNames = value;
|
||
},
|
||
|
||
setNoTitleString: function(value) {
|
||
this.noTitleString = value;
|
||
},
|
||
|
||
expandCollapseRecord: function(objectId, expandSingle) {
|
||
var currentUid = this.parseFormElementName('none', objectId, 1);
|
||
var objectPrefix = this.parseFormElementName('full', objectId, 0, 1);
|
||
... | ... | |
Element.toggle(objectId+'_fields');
|
||
currentState = Element.visible(objectId+'_fields') ? 1 : 0
|
||
|
||
if (this.isNewRecord(objectId))
|
||
this.updateExpandedCollapsedStateLocally(objectId, currentState);
|
||
else if (currentState)
|
||
... | ... | |
collapse.push(currentUid);
|
||
this.setExpandedCollapsedState(objectId, expand.join(','), collapse.join(','));
|
||
|
||
return false;
|
||
},
|
||
... | ... | |
}
|
||
}
|
||
}
|
||
|
||
return collapse;
|
||
},
|
||
|
||
updateExpandedCollapsedStateLocally: function(objectId, value) {
|
||
var ucName = 'uc'+this.parseFormElementName('parts', objectId, 3, 2);
|
||
var ucFormObj = document.getElementsByName(ucName);
|
||
if (ucFormObj.length) ucFormObj[0].value = value;
|
||
},
|
||
|
||
createNewRecord: function(objectId,prevRecordUid) {
|
||
if (this.isBelowMax(objectId)) this.makeAjaxCall('createNewRecord', objectId+(prevRecordUid ? '['+prevRecordUid+']' : ''));
|
||
else alert('There are no more relations possible at this moment!');
|
||
... | ... | |
},
|
||
setExpandedCollapsedState: function(objectId, expand, collapse) {
|
||
// alert(objectId+': '+expand+', '+collapse);
|
||
this.makeAjaxCall('setExpandedCollapsedState', objectId, expand, collapse);
|
||
},
|
||
|
||
makeAjaxCall: function() {
|
||
if (arguments.length > 1) {
|
||
var params = '';
|
||
... | ... | |
new Ajax.Request(url, options);
|
||
}
|
||
},
|
||
|
||
processAjaxResponse: function(xhr) {
|
||
var json = eval('('+xhr.responseText+')');
|
||
for (var i in json.scriptCall) eval(json.scriptCall[i]);
|
||
... | ... | |
showAjaxFailure: function(xhr) {
|
||
alert('Error: '+xhr.status+"\n"+xhr.statusText);
|
||
},
|
||
|
||
// foreign_selector: used by selector box (type='select')
|
||
importNewRecord: function(objectId) {
|
||
var selector = $(objectId+'_selector');
|
||
if (selector.selectedIndex != -1) {
|
||
... | ... | |
}
|
||
return false;
|
||
},
|
||
|
||
// foreign_selector: used by element browser (type='group/db')
|
||
importElement: function(objectId, table, uid, type) {
|
||
if (this.checkUniqueUsed(objectId, uid, table)) {
|
||
return {
|
||
error: true,
|
||
close: false,
|
||
message: 'There is already a relation to the selected element!',
|
||
};
|
||
} else {
|
||
window.setTimeout(function() { inline.makeAjaxCall('createNewRecord', objectId, uid); }, 10);
|
||
return {error: false, close: true};
|
||
}
|
||
},
|
||
// Checks if a record was used and should be unique:
|
||
checkUniqueUsed: function(objectId, uid, table) {
|
||
if (this.data.unique && this.data.unique[objectId]) {
|
||
var unique = this.data.unique[objectId];
|
||
var values = $H(unique.used).values();
|
||
|
||
// for select: only the uid is stored
|
||
if (unique['type'] == 'select') {
|
||
if (values.indexOf(uid) != -1) return true;
|
||
|
||
// for group/db: table and uid is stored in a assoc array
|
||
} else if (unique.type == 'groupdb') {
|
||
for (var i=values.length-1; i>=0; i--) {
|
||
// if the pair table:uid is already used:
|
||
if (values[i].table==table && values[i].uid==uid) return true;
|
||
}
|
||
}
|
||
}
|
||
return false;
|
||
},
|
||
// 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];
|
||
// remove used items from each select-field of the child records
|
||
if (!(unique.selector && unique.max == -1)) {
|
||
var elName = this.parseFormElementName('full', objectId, 1)+'['+recordUid+']['+unique.field+']';
|
||
var formName = this.prependFormFieldNames+this.parseFormElementName('parts', objectId, 3, 1);
|
||
var fieldObj = document.getElementsByName(elName);
|
||
var values = $H(unique.used).values();
|
||
|
||
if (fieldObj.length) {
|
||
// remove all before used items from the new select-item
|
||
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
|
||
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 (typeof this.data.unique[objectId]['used'].length != 'undefined')
|
||
this.data.unique[objectId]['used'] = {};
|
||
this.data.unique[objectId]['used'][recordUid] = selectedValue;
|
||
if (unique.type == 'select') {
|
||
// remove used items from each select-field of the child records
|
||
if (!(unique.selector && unique.max == -1)) {
|
||
var elName = this.parseFormElementName('full', objectId, 1)+'['+recordUid+']['+unique.field+']';
|
||
var formName = this.prependFormFieldNames+this.parseFormElementName('parts', objectId, 3, 1);
|
||
|
||
var fieldObj = document.getElementsByName(elName);
|
||
var values = $H(unique.used).values();
|
||
|
||
if (fieldObj.length) {
|
||
// remove all before used items from the new select-item
|
||
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
|
||
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 (typeof this.data.unique[objectId].used.length != 'undefined') {
|
||
this.data.unique[objectId].used = {};
|
||
}
|
||
this.data.unique[objectId].used[recordUid] = selectedValue;
|
||
}
|
||
}
|
||
} else if (unique.type == 'groupdb') {
|
||
// add the new record to the used items:
|
||
this.data.unique[objectId].used[recordUid] = {'table':unique.elTable, 'uid':selectedValue};
|
||
}
|
||
|
||
// remove used items from a selector-box
|
||
if (unique.selector && selectedValue) {
|
||
if (unique.selector == 'select' && selectedValue) {
|
||
var selector = $(objectId+'_selector');
|
||
this.removeSelectOption(selector, selectedValue);
|
||
this.data.unique[objectId]['used'][recordUid] = selectedValue;
|
||
}
|
||
}
|
||
},
|
||
|
||
domAddNewRecord: function(method, insertObject, objectPrefix, htmlData) {
|
||
if (this.isBelowMax(objectPrefix)) {
|
||
if (method == 'bottom')
|
||
... | ... | |
new Insertion.After(insertObject, htmlData);
|
||
}
|
||
},
|
||
|
||
changeSorting: function(objectId, direction) {
|
||
var objectName = this.prependFormFieldNames+this.parseFormElementName('parts', objectId, 3, 2);
|
||
var objectPrefix = this.parseFormElementName('full', objectId, 0, 1);
|
||
... | ... | |
|
||
return false;
|
||
},
|
||
|
||
dragAndDropSorting: function(element) {
|
||
var objectId = element.getAttribute('id').replace(/_records$/, '');
|
||
var objectName = inline.prependFormFieldNames+inline.parseFormElementName('parts', objectId, 3);
|
||
... | ... | |
}
|
||
}
|
||
},
|
||
|
||
createDragAndDropSorting: function(objectId) {
|
||
Sortable.create(
|
||
objectId,
|
||
... | ... | |
}
|
||
);
|
||
},
|
||
|
||
destroyDragAndDropSorting: function(objectId) {
|
||
Sortable.destroy(objectId);
|
||
},
|
||
|
||
redrawSortingButtons: function(objectPrefix, records) {
|
||
var i;
|
||
var headerObj;
|
||
var sortingObj = new Array();
|
||
|
||
// if no records were passed, fetch them from form field
|
||
if (typeof records == 'undefined') {
|
||
records = new Array();
|
||
... | ... | |
|
||
for (i=0; i<records.length; i++) {
|
||
if (!records[i].length) continue;
|
||
|
||
headerObj = $(objectPrefix+'['+records[i]+']_header');
|
||
sortingObj[0] = headerObj.getElementsByClassName('sortingUp');
|
||
sortingObj[1] = headerObj.getElementsByClassName('sortingDown');
|
||
|
||
if (sortingObj[0].length)
|
||
sortingObj[0][0].style.visibility = i == 0 ? 'hidden' : 'visible';
|
||
if (sortingObj[1].length)
|
||
sortingObj[1][0].style.visibility = i == records.length-1 ? 'hidden' : 'visible';
|
||
}
|
||
},
|
||
|
||
memorizeAddRecord: function(objectPrefix, newUid, afterUid, selectedValue) {
|
||
if (this.isBelowMax(objectPrefix)) {
|
||
var objectName = this.prependFormFieldNames+this.parseFormElementName('parts', objectPrefix, 3, 1);
|
||
var formObj = document.getElementsByName(objectName);
|
||
|
||
if (formObj.length) {
|
||
var records = new Array();
|
||
if (formObj[0].value.length) records = formObj[0].value.split(',');
|
||
... | ... | |
}
|
||
formObj[0].value = records.join(',');
|
||
}
|
||
|
||
this.redrawSortingButtons(objectPrefix, records);
|
||
|
||
if (this.data.unique && this.data.unique[objectPrefix]) {
|
||
var unique = this.data.unique[objectPrefix];
|
||
this.setUnique(objectPrefix, newUid, selectedValue);
|
||
}
|
||
}
|
||
|
||
// if we reached the maximum off possible records after this action, hide the new buttons
|
||
if (!this.isBelowMax(objectPrefix))
|
||
if (!this.isBelowMax(objectPrefix)) {
|
||
this.hideElementsWithClassName('inlineNewButton', this.parseFormElementName('full', objectPrefix, 0 , 1));
|
||
}
|
||
if (TBE_EDITOR) TBE_EDITOR.fieldChanged_fName(objectName, formObj);
|
||
},
|
||
|
||
memorizeRemoveRecord: function(objectName, removeUid) {
|
||
var formObj = document.getElementsByName(objectName);
|
||
if (formObj.length) {
|
||
... | ... | |
}
|
||
return false;
|
||
},
|
||
|
||
updateUnique: function(srcElement, objectPrefix, formName, recordUid) {
|
||
if (this.data.unique && this.data.unique[objectPrefix]) {
|
||
var unique = this.data.unique[objectPrefix];
|
||
var oldValue = unique.used[recordUid];
|
||
if (unique.selector) {
|
||
if (unique.selector == 'select') {
|
||
var selector = $(objectPrefix+'_selector');
|
||
this.removeSelectOption(selector, srcElement.value);
|
||
if (typeof oldValue != 'undefined') this.readdSelectOption(selector, oldValue, unique);
|
||
}
|
||
|
||
if (!(unique.selector && unique.max == -1)) {
|
||
var formObj = document.getElementsByName(formName);
|
||
if (unique && formObj.length) {
|
||
... | ... | |
}
|
||
}
|
||
},
|
||
|
||
revertUnique: function(objectPrefix, elName, recordUid) {
|
||
var unique = this.data.unique[objectPrefix];
|
||
var fieldObj = document.getElementsByName(elName+'['+unique.field+']');
|
||
if (fieldObj.length) {
|
||
delete(this.data.unique[objectPrefix].used[recordUid])
|
||
|
||
if (unique.selector) {
|
||
if (!isNaN(fieldObj[0].value)) {
|
||
var selector = $(objectPrefix+'_selector');
|
||
this.readdSelectOption(selector, fieldObj[0].value, unique);
|
||
if (unique.type == 'select') {
|
||
if (fieldObj.length) {
|
||
delete(this.data.unique[objectPrefix].used[recordUid])
|
||
|
||
if (unique.selector == 'select') {
|
||
if (!isNaN(fieldObj[0].value)) {
|
||
var selector = $(objectPrefix+'_selector');
|
||
this.readdSelectOption(selector, fieldObj[0].value, unique);
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!(unique.selector && unique.max == -1)) {
|
||
var formName = this.prependFormFieldNames+this.parseFormElementName('parts', objectPrefix, 3, 1);
|
||
var formObj = document.getElementsByName(formName);
|
||
if (formObj.length) {
|
||
var records = formObj[0].value.split(',');
|
||
var recordObj;
|
||
// walk through all inline records on that level and get the select field
|
||
for (var i=0; i<records.length; i++) {
|
||
recordObj = document.getElementsByName(this.prependFormFieldNames+'['+unique.table+']['+records[i]+']['+unique.field+']');
|
||
if (recordObj.length) this.readdSelectOption(recordObj[0], fieldObj[0].value, unique);
|
||
|
||
if (!(unique.selector && unique.max == -1)) {
|
||
var formName = this.prependFormFieldNames+this.parseFormElementName('parts', objectPrefix, 3, 1);
|
||
var formObj = document.getElementsByName(formName);
|
||
if (formObj.length) {
|
||
var records = formObj[0].value.split(',');
|
||
var recordObj;
|
||
// walk through all inline records on that level and get the select field
|
||
for (var i=0; i<records.length; i++) {
|
||
recordObj = document.getElementsByName(this.prependFormFieldNames+'['+unique.table+']['+records[i]+']['+unique.field+']');
|
||
if (recordObj.length) this.readdSelectOption(recordObj[0], fieldObj[0].value, unique);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} else if (unique.type == 'groupdb') {
|
||
delete(this.data.unique[objectPrefix].used[recordUid])
|
||
}
|
||
},
|
||
|
||
enableDisableRecord: function(objectId) {
|
||
var elName = this.parseFormElementName('full', objectId, 2);
|
||
var imageObj = $(objectId+'_disabled');
|
||
... | ... | |
|
||
return false;
|
||
},
|
||
|
||
deleteRecord: function(objectId) {
|
||
var i, j, inlineRecords, records, childObjectId, childTable;
|
||
var objectPrefix = this.parseFormElementName('full', objectId, 0 , 1);
|
||
var elName = this.parseFormElementName('full', objectId, 2);
|
||
var shortName = this.parseFormElementName('parts', objectId, 2);
|
||
... | ... | |
new Effect.Fade(objectId+'_div');
|
||
}
|
||
// remove from TBE_EDITOR (required fields, required range, etc.):
|
||
// Remove from TBE_EDITOR (required fields, required range, etc.):
|
||
if (TBE_EDITOR && TBE_EDITOR.removeElement) {
|
||
inlineRecords = document.getElementsByClassName('inlineRecord', objectId+'_div');
|
||
// Remove nested child records from TBE_EDITOR required/range checks:
|
||
for (i=inlineRecords.length-1; i>=0; i--) {
|
||
if (inlineRecords[i].value.length) {
|
||
records = inlineRecords[i].value.split(',');
|
||
childObjectId = this.data.map[inlineRecords[i].name];
|
||
childTable = this.data.config[childObjectId].table;
|
||
for (j=records.length-1; j>=0; j--) {
|
||
TBE_EDITOR.removeElement(this.prependFormFieldNames+'['+childTable+']['+records[j]+']');
|
||
}
|
||
}
|
||
}
|
||
TBE_EDITOR.removeElement(this.prependFormFieldNames+shortName);
|
||
}
|
||
t3lib/class.t3lib_tceforms_inline.php (Arbeitskopie) | ||
---|---|---|
// Init:
|
||
$config = $PA['fieldConf']['config'];
|
||
$foreign_table = $config['foreign_table'];
|
||
t3lib_div::loadTCA($foreign_table);
|
||
$minitems = t3lib_div::intInRange($config['minitems'],0);
|
||
$maxitems = t3lib_div::intInRange($config['maxitems'],0);
|
||
... | ... | |
// if relations are required to be unique, get the uids that have already been used on the foreign side of the relation
|
||
if ($config['foreign_unique']) {
|
||
$uniqueIds = $this->getUniqueIds($recordList, $config);
|
||
// If unique *and* selector, the should both be the same - get config:
|
||
$selConfig = $this->getPossibleRecordsSelectorConfig($config, $config['foreign_unique']);
|
||
// Get the used unique ids:
|
||
$uniqueIds = $this->getUniqueIds($recordList, $config, $selConfig['type']=='groupdb');
|
||
$possibleRecords = $this->getPossibleRecords($table,$field,$row,$config,'foreign_unique');
|
||
$uniqueMax = $config['appearance']['useCombination'] ? -1 : count($possibleRecords);
|
||
$uniqueMax = $config['appearance']['useCombination'] || $possibleRecords === false ? -1 : count($possibleRecords);
|
||
$this->inlineData['unique'][$nameObject.'['.$foreign_table.']'] = array(
|
||
'max' => $uniqueMax,
|
||
'used' => $uniqueIds,
|
||
'type' => $selConfig['type'],
|
||
'table' => $config['foreign_table'],
|
||
'elTable' => $selConfig['table'], // element/record table (one step down in hierarchy)
|
||
'field' => $config['foreign_unique'],
|
||
'selector' => $config['foreign_selector'] ? true : false,
|
||
'selector' => $selConfig['PA'] && $selConfig['type'] ? $selConfig['type'] : false,
|
||
'possible' => $this->getPossibleRecordsFlat($possibleRecords),
|
||
);
|
||
}
|
||
... | ... | |
$config['inline']['inlineNewButtonStyle'] = 'display: none;';
|
||
}
|
||
// add the "Create new record" link before all child records
|
||
if ($config['appearance']['newRecordLinkPosition'] != 'bottom') {
|
||
if (in_array($config['appearance']['newRecordLinkPosition'], array('both', 'top'))) {
|
||
$item .= $this->getNewRecordLink($nameObject.'['.$foreign_table.']', $config);
|
||
}
|
||
... | ... | |
$item .= '</div>';
|
||
// add the "Create new record" link after all child records
|
||
if ($config['appearance']['newRecordLinkPosition'] != 'top') {
|
||
if (in_array($config['appearance']['newRecordLinkPosition'], array('both', 'bottom'))) {
|
||
$item .= $this->getNewRecordLink($nameObject.'['.$foreign_table.']', $config);
|
||
}
|
||
... | ... | |
$foreign_table = $config['foreign_table'];
|
||
$foreign_field = $config['foreign_field'];
|
||
$foreign_selector = $config['foreign_selector'];
|
||
$selConfig = $this->getPossibleRecordsSelectorConfig($config, $foreign_selector);
|
||
// record comes from storage (e.g. database)
|
||
// Send a mapping information to the browser via JSON:
|
||
// e.g. data[<curTable>][<curId>][<curField>] => data[<pid>][<parentTable>][<parentId>][<parentField>][<curTable>][<curId>][<curField>]
|
||
$this->inlineData['map'][$this->inlineNames['form']] = $this->inlineNames['object'];
|
||
// Set this variable if we handle a brand new unsaved record:
|
||
$isNewRecord = t3lib_div::testInt($rec['uid']) ? false : true;
|
||
// if there is a selector field, normalize it
|
||
// If there is a selector field, normalize it:
|
||
if ($foreign_selector) {
|
||
$rec[$foreign_selector] = $this->normalizeUid($rec[$foreign_selector]);
|
||
}
|
||
... | ... | |
if(!$hasAccess) return false;
|
||
// get the current prependObjectId
|
||
// Get the current naming scheme for DOM name/id attributes:
|
||
$nameObject = $this->inlineNames['object'];
|
||
$appendFormFieldNames = '['.$foreign_table.']['.$rec['uid'].']';
|
||
$formFieldNames = $nameObject.$appendFormFieldNames;
|
||
... | ... | |
// set additional field for processing for saving
|
||
$fields .= '<input type="hidden" name="'.$this->prependCmdFieldNames.$appendFormFieldNames.'[delete]" value="1" disabled="disabled" />';
|
||
}
|
||
if ($foreign_selector && $selConfig['type'] == 'groupdb') {
|
||
$fields .= '<input type="hidden" name="'.$this->prependFormFieldNames.$appendFormFieldNames.'['.$foreign_selector.']" value="'.$rec[$foreign_selector].'" />';
|
||
}
|
||
|
||
// if this record should be shown collapsed
|
||
if (!$isExpanded) $appearanceStyleFields = ' style="display: none;"';
|
||
... | ... | |
// render the special alternative title
|
||
} elseif ($hasForeignLabel || $hasSymmetricLabel) {
|
||
$titleCol = $hasForeignLabel ? $config['foreign_label'] : $config['symmetric_label'];
|
||
$recTitle = t3lib_BEfunc::getProcessedValueExtra($foreign_table, $titleCol, $rec[$titleCol], 0, 0, false);
|
||
$foreignConfig = $this->getPossibleRecordsSelectorConfig($config, $titleCol);
|
||
// Render title for everything else than group/db:
|
||
if ($foreignConfig['type'] != 'groupdb') {
|
||
$recTitle = t3lib_BEfunc::getProcessedValueExtra($foreign_table, $titleCol, $rec[$titleCol], 0, 0, false);
|
||
// Render title for group/db:
|
||
} else {
|
||
// $recTitle would be something like: "tx_table_123",
|
||
$itemParts = $this->rightExplode('_', $rec[$titleCol], 2);
|
||
$recTemp = t3lib_befunc::getRecordWSOL($itemParts[0], $itemParts[1]);
|
||
$recTitle = t3lib_BEfunc::getRecordTitle($itemParts[0], $recTemp, true);
|
||
}
|
||
$recTitle = t3lib_BEfunc::getRecordTitlePrep($recTitle);
|
||
if (!strcmp(trim($recTitle),'')) {
|
||
$recTitle = t3lib_BEfunc::getNoRecordTitle(true);
|
||
... | ... | |
($isPagesTable && ($localCalcPerms&4)) || (!$isPagesTable && ($calcPerms&16))
|
||
) {
|
||
$onClick = "inline.deleteRecord('".$nameObjectFtId."');";
|
||
$cells[]='<a href="#" onclick="'.htmlspecialchars('if (confirm('.$GLOBALS['LANG']->JScharCode($GLOBALS['LANG']->getLL('deleteWarning').t3lib_BEfunc::referenceCount($foreign_table,$rec['uid'],' (There are %s reference(s) to this record!)')).')) { '.$onClick.' } return false;').'">'.
|
||
$cells[]='<a href="#" onclick="'.htmlspecialchars('if (confirm('.$GLOBALS['LANG']->JScharCode($GLOBALS['LANG']->getLL('deleteWarning')).')) { '.$onClick.' } return false;').'">'.
|
||
'<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/garbage.gif','width="11" height="12"').' title="'.$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.xml:delete',1).'" alt="" />'.
|
||
'</a>';
|
||
}
|
||
... | ... | |
return $out;
|
||
}
|
||
|
||
|
||
/**
|
||
* Determine the configuration and the type of a record selector.
|
||
*
|
||
* @param array $conf: TCA configuration of the parent(!) field
|
||
* @return array Associative array with the keys 'PA' and 'type', both are false if the selector was not valid.
|
||
*/
|
||
function getPossibleRecordsSelectorConfig($conf, $field = '') {
|
||
$foreign_table = $conf['foreign_table'];
|
||
$foreign_selector = $conf['foreign_selector'];
|
||
$PA = false;
|
||
$type = false;
|
||
$table = false;
|
||
|
||
if ($field) {
|
||
$PA = array();
|
||
$PA['fieldConf'] = $GLOBALS['TCA'][$foreign_table]['columns'][$field];
|
||
$PA['fieldConf']['config']['form_type'] = $PA['fieldConf']['config']['form_type'] ? $PA['fieldConf']['config']['form_type'] : $PA['fieldConf']['config']['type']; // Using "form_type" locally in this script
|
||
$PA['fieldTSConfig'] = $this->fObj->setTSconfig($foreign_table,array(),$field);
|
||
$config = $PA['fieldConf']['config'];
|
||
// Determine type of Selector:
|
||
$type = $this->getPossibleRecordsSelectorType($config);
|
||
// Return table on this level:
|
||
$table = $type == 'select' ? $config['foreign_table'] : $config['allowed'];
|
||
}
|
||
|
||
return array(
|
||
'PA' => $PA,
|
||
'type' => $type,
|
||
'table' => $table
|
||
);
|
||
}
|
||
|
||
/**
|
||
* Determine the type of a record selector, e.g. select or group/db.
|
||
*
|
||
* @param array $config: TCE configuration of the selector
|
||
* @return mixed The type of the selector, 'select' or 'groupdb' - false not valid
|
||
*/
|
||
function getPossibleRecordsSelectorType($config) {
|
||
$type = false;
|
||
if ($config['type'] == 'select') {
|
||
$type = 'select';
|
||
} elseif ($config['type'] == 'group' && $config['internal_type'] == 'db') {
|
||
$type = 'groupdb';
|
||
}
|
||
return $type;
|
||
}
|
||
|
||
|
||
/**
|
||
* Get a selector as used for the select type, to select from all available
|
||
* records and to create a relation to the embedding record (e.g. like MM).
|
||
*
|
||
... | ... | |
$foreign_table = $conf['foreign_table'];
|
||
$foreign_selector = $conf['foreign_selector'];
|
||
$selConfig = $this->getPossibleRecordsSelectorConfig($conf, $foreign_selector);
|
||
$config = $selConfig['PA']['fieldConf']['config'];
|
||
if ($selConfig['type'] == 'select') {
|
||
$item = $this->renderPossibleRecordsSelectorTypeSelect($selItems, $conf, $selConfig['PA'], $uniqueIds);
|
||
} elseif ($selConfig['type'] == 'groupdb') {
|
||
$item = $this->renderPossibleRecordsSelectorTypeGroupDB($conf, $selConfig['PA']);
|
||
}
|
||
return $item;
|
||
}
|
||
|
||
/**
|
||
* Get a selector as used for the select type, to select from all available
|
||
* records and to create a relation to the embedding record (e.g. like MM).
|
||
*
|
||
* @param array $selItems: Array of all possible records
|
||
* @param array $conf: TCA configuration of the parent(!) field
|
||
* @param array $PA: An array with additional configuration options
|
||
* @param array $uniqueIds: The uids that have already been used and should be unique
|
||
* @return string A HTML <select> box with all possible records
|
||
*/
|
||
function renderPossibleRecordsSelectorTypeSelect($selItems, $conf, &$PA, $uniqueIds=array()) {
|
||
$foreign_table = $conf['foreign_table'];
|
||
$foreign_selector = $conf['foreign_selector'];
|
||
$PA = array();
|
||
$PA['fieldConf'] = $GLOBALS['TCA'][$foreign_table]['columns'][$foreign_selector];
|
||
$PA['fieldConf']['config']['form_type'] = $PA['fieldConf']['config']['form_type'] ? $PA['fieldConf']['config']['form_type'] : $PA['fieldConf']['config']['type']; // Using "form_type" locally in this script
|
||
... | ... | |
// Put together the selector box:
|
||
$selector_itemListStyle = isset($config['itemListStyle']) ? ' style="'.htmlspecialchars($config['itemListStyle']).'"' : ' style="'.$this->fObj->defaultMultipleSelectorStyle.'"';
|
||
$size = intval($config['size']);
|
||
$size = $config['autoSizeMax'] ? t3lib_div::intInRange(count($itemArray)+1,t3lib_div::intInRange($size,1),$config['autoSizeMax']) : $size;
|
||
$sOnChange = "return inline.importNewRecord('".$this->inlineNames['object']."[".$conf['foreign_table']."]')";
|
||
$itemsToSelect = '
|
||
$size = intval($conf['size']);
|
||
$size = $conf['autoSizeMax'] ? t3lib_div::intInRange(count($itemArray)+1,t3lib_div::intInRange($size,1),$conf['autoSizeMax']) : $size;
|
||
$onChange = "return inline.importNewRecord('".$this->inlineNames['object']."[".$conf['foreign_table']."]')";
|
||
$item = '
|
||
<select id="'.$this->inlineNames['object'].'['.$conf['foreign_table'].']_selector"'.
|
||
$this->fObj->insertDefStyle('select').
|
||
($size ? ' size="'.$size.'"' : '').
|
||
' onchange="'.htmlspecialchars($sOnChange).'"'.
|
||
' onchange="'.htmlspecialchars($onChange).'"'.
|
||
$PA['onFocus'].
|
||
$selector_itemListStyle.
|
||
($conf['foreign_unique'] ? ' isunique="isunique"' : '').'>
|
||
... | ... | |
// there is only one record item in the select-box, that is selected by default
|
||
// the selector-box creates a new relation on using a onChange event (see some line above)
|
||
$createNewRelationText = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:cm.createNewRelation',1);
|
||
$itemsToSelect .=
|
||
'<a href="#" onclick="'.htmlspecialchars($sOnChange).'" align="abstop">'.
|
||
'<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/edit2.gif','width="11" height="12"').' title="'.$createNewRelationText.'" alt="" /> '.$createNewRelationText.
|
||
$item .=
|
||
'<a href="#" onclick="'.htmlspecialchars($onChange).'" align="abstop">'.
|
||
'<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/edit2.gif','width="11" height="12"').' align="absmiddle" '.t3lib_BEfunc::titleAltAttrib($createNewRelationText).' /> '.$createNewRelationText.
|
||
'</a>';
|
||
// wrap the selector and add a spacer to the bottom
|
||
$itemsToSelect = '<div style="margin-bottom: 20px;">'.$itemsToSelect.'</div>';
|
||
$item = '<div style="margin-bottom: 20px;">'.$item.'</div>';
|
||
}
|
||
return $itemsToSelect;
|
||
return $item;
|
||
}
|
||
|
||
/**
|
||
* Generate a link that ipens an element browser in a new window.
|
||
*
|
||
* @param array $conf: TCA configuration of the parent(!) field
|
||
* @param array $PA: An array with additional configuration options
|
||
* @return string A HTML link that opens an element browser in a new window
|
||
*/
|
||
function renderPossibleRecordsSelectorTypeGroupDB($conf, &$PA) {
|
||
$foreign_table = $conf['foreign_table'];
|
||
$config = $PA['fieldConf']['config'];
|
||
$allowed = $config['allowed'];
|
||
$objectPrefix = $this->inlineNames['object'].'['.$foreign_table.']';
|
||
$createNewRelationText = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:cm.createNewRelation',1);
|
||
$onClick = "setFormValueOpenBrowser('db','".($objectPrefix.'|||'.$allowed.'|inline.importElement')."'); return false;";
|
||
$item =
|
||
'<a href="#" onclick="'.htmlspecialchars($onClick).'">'.
|
||
'<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/insert3.gif','width="14" height="14"').' align="absmiddle" '.t3lib_BEfunc::titleAltAttrib($createNewRelationText).' /> '.$createNewRelationText.
|
||
'</a>';
|
||
|
||
return $item;
|
||
}
|
||
|
||
|
||
/**
|
||
* Creates a link/button to create new records
|
||
*
|
||
... | ... | |
$parent = $this->getStructureLevel(-1);
|
||
// get TCA 'config' of the parent table
|
||
$config = $parent['config'];
|
||
|
||
// dynamically create a new record using t3lib_transferData
|
||
if (!$foreignUid || !t3lib_div::testInt($foreignUid) || $config['foreign_selector']) {
|
||
$record = $this->getNewRecord($this->inlineFirstPid, $current['table']);
|
||
... | ... | |
// this intermediate table holds a field, which is responsible for the foreign_selector, so
|
||
// we have to set this field to the uid we get - or if none, to a new uid
|
||
if ($config['foreign_selector'] && $foreignUid) {
|
||
$record[$config['foreign_selector']] = $foreignUid;
|
||
$selConfig = $this->getPossibleRecordsSelectorConfig($config, $config['foreign_selector']);
|
||
// For a selector of type group/db, prepend the tablename (<tablename>_<uid>):
|
||
$record[$config['foreign_selector']] = $selConfig['type'] != 'groupdb' ? '' : $selConfig['table'].'_';
|
||
$record[$config['foreign_selector']] .= $foreignUid;
|
||
}
|
||
// the HTML-object-id's prefix of the dynamically created record
|
||
... | ... | |
* @param array The record data array where the value(s) for the field can be found
|
||
* @param array An array with additional configuration options.
|
||
* @param string $checkForConfField: For which field in the foreign_table the possible records should be fetched
|
||
* @return array Array of possible record items
|
||
* @return mixed Array of possible record items; false if type is "group/db", then everything could be "possible"
|
||
*/
|
||
function getPossibleRecords($table,$field,$row,$conf,$checkForConfField='foreign_selector') {
|
||
// ctrl configuration from TCA:
|
||
... | ... | |
$foreign_table = $conf['foreign_table'];
|
||
$foreign_check = $conf[$checkForConfField];
|
||
$PA = array();
|
||
$PA['fieldConf'] = $GLOBALS['TCA'][$foreign_table]['columns'][$foreign_check];
|
||
$PA['fieldConf']['config']['form_type'] = $PA['fieldConf']['config']['form_type'] ? $PA['fieldConf']['config']['form_type'] : $PA['fieldConf']['config']['type']; // Using "form_type" locally in this script
|
||
$PA['fieldTSConfig'] = $this->fObj->setTSconfig($foreign_table,array(),$foreign_check);
|
||
$foreignConfig = $this->getPossibleRecordsSelectorConfig($conf, $foreign_check);
|
||
$PA = $foreignConfig['PA'];
|
||
$config = $PA['fieldConf']['config'];
|
||
// Getting the selector box items from the system
|
||
$selItems = $this->fObj->addSelectOptionsToItemArray($this->fObj->initItemArray($PA['fieldConf']),$PA['fieldConf'],$this->fObj->setTSconfig($table,$row),$field);
|
||
if ($config['itemsProcFunc']) $selItems = $this->fObj->procItems($selItems,$PA['fieldTSConfig']['itemsProcFunc.'],$config,$table,$row,$field);
|
||
// Possibly remove some items:
|
||
$removeItems = t3lib_div::trimExplode(',',$PA['fieldTSConfig']['removeItems'],1);
|
||
foreach($selItems as $tk => $p) {
|
||
// Checking languages and authMode:
|
||
$languageDeny = $tcaTableCtrl['languageField'] && !strcmp($tcaTableCtrl['languageField'], $field) && !$GLOBALS['BE_USER']->checkLanguageAccess($p[1]);
|
||
$authModeDeny = $config['form_type']=='select' && $config['authMode'] && !$GLOBALS['BE_USER']->checkAuthMode($table,$field,$p[1],$config['authMode']);
|
||
if (in_array($p[1],$removeItems) || $languageDeny || $authModeDeny) {
|
||
unset($selItems[$tk]);
|
||
} elseif (isset($PA['fieldTSConfig']['altLabels.'][$p[1]])) {
|
||
$selItems[$tk][0]=$this->fObj->sL($PA['fieldTSConfig']['altLabels.'][$p[1]]);
|
||
}
|
||
// Removing doktypes with no access:
|
||
if ($table.'.'.$field == 'pages.doktype') {
|
||
if (!($GLOBALS['BE_USER']->isAdmin() || t3lib_div::inList($GLOBALS['BE_USER']->groupData['pagetypes_select'],$p[1]))) {
|
||
|
||
if ($foreignConfig['type'] == 'select') {
|
||
// Getting the selector box items from the system
|
||
$selItems = $this->fObj->addSelectOptionsToItemArray($this->fObj->initItemArray($PA['fieldConf']),$PA['fieldConf'],$this->fObj->setTSconfig($table,$row),$field);
|
||
if ($config['itemsProcFunc']) $selItems = $this->fObj->procItems($selItems,$PA['fieldTSConfig']['itemsProcFunc.'],$config,$table,$row,$field);
|
||
|
||
// Possibly remove some items:
|
||
$removeItems = t3lib_div::trimExplode(',',$PA['fieldTSConfig']['removeItems'],1);
|
||
foreach($selItems as $tk => $p) {
|
||
|
||
// Checking languages and authMode:
|
||
$languageDeny = $tcaTableCtrl['languageField'] && !strcmp($tcaTableCtrl['languageField'], $field) && !$GLOBALS['BE_USER']->checkLanguageAccess($p[1]);
|
||
$authModeDeny = $config['form_type']=='select' && $config['authMode'] && !$GLOBALS['BE_USER']->checkAuthMode($table,$field,$p[1],$config['authMode']);
|
||
if (in_array($p[1],$removeItems) || $languageDeny || $authModeDeny) {
|
||
unset($selItems[$tk]);
|
||
} elseif (isset($PA['fieldTSConfig']['altLabels.'][$p[1]])) {
|
||
$selItems[$tk][0]=$this->fObj->sL($PA['fieldTSConfig']['altLabels.'][$p[1]]);
|
||
}
|
||
|
||
// Removing doktypes with no access:
|
||
if ($table.'.'.$field == 'pages.doktype') {
|
||
if (!($GLOBALS['BE_USER']->isAdmin() || t3lib_div::inList($GLOBALS['BE_USER']->groupData['pagetypes_select'],$p[1]))) {
|
||
unset($selItems[$tk]);
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
$selItems = false;
|
||
}
|
||
return $selItems;
|
||
... | ... | |
*
|
||
* @param array $records: All inline records on this level
|
||
* @param array $conf: The TCA field configuration of the inline field to be rendered
|
||
* @param boolean $splitValue: for usage with group/db, values come like "tx_table_123|Title%20abc", but we need "tx_table" and "123"
|
||
* @return array The uids, that have been used already and should be used unique
|
||
*/
|
||
function getUniqueIds($records, $conf=array()) {
|
||
function getUniqueIds($records, $conf=array(), $splitValue=false) {
|
||
$uniqueIds = array();
|
||
if ($conf['foreign_unique'] && count($records))
|
||
foreach ($records as $rec) $uniqueIds[$rec['uid']] = $rec[$conf['foreign_unique']];
|
||
if ($conf['foreign_unique'] && count($records)) {
|
||
foreach ($records as $rec) {
|
||
$value = $rec[$conf['foreign_unique']];
|
||
// Split the value and extract the table and uid:
|
||
if ($splitValue) {
|
||
$valueParts = t3lib_div::trimExplode('|', $value);
|
||
$itemParts = explode('_', $valueParts[0]);
|
||
$value = array(
|
||
'uid' => array_pop($itemParts),
|
||
'table' => implode('_', $itemParts)
|
||
);
|
||
}
|
||
$uniqueIds[$rec['uid']] = $value;
|
||
}
|
||
}
|
||
return $uniqueIds;
|
||
}
|
||
... | ... | |
$foreign_table = $config['foreign_table'];
|
||
// an inline field must have a foreign_table, if not, stop all further inline actions for this field
|
||
if (!$foreign_table || !is_array($GLOBALS['TCA'][$foreign_table]))
|
||
if (!$foreign_table || !is_array($GLOBALS['TCA'][$foreign_table])) {
|
||
return false;
|
||
}
|
||
if (!is_array($config['appearance']))
|
||
$config['appearance'] = array();
|
||
if (!in_array($config['appearance']['newRecordLinkPosition'], array('top', 'bottom', 'both')))
|
||
if (!in_array($config['appearance']['newRecordLinkPosition'], array('top', 'bottom', 'both', 'none')))
|
||
$config['appearance']['newRecordLinkPosition'] = 'top';
|
||
return true;
|
||
... | ... | |
* the value of the flat array is the label of the record.
|
||
*
|
||
* @param array $possibleRecords: The possibleRecords array (for select fields)
|
||
* @return array A flat array with key=uid, value=label
|
||
* @return mixed A flat array with key=uid, value=label; if $possibleRecords isn't an array, false is returned.
|
||
*/
|
||
function getPossibleRecordsFlat($possibleRecords) {
|
||
$flat = array();
|
||
if (is_array($possibleRecords))
|
||
$flat = false;
|
||
if (is_array($possibleRecords)) {
|
||
$flat = array();
|
||
foreach ($possibleRecords as $record) $flat[$record[1]] = $record[0];
|
||
}
|
||
return $flat;
|
||
}
|
||
... | ... | |
'foreign_table' => $table,
|
||
'%OR' => array(
|
||
'%AND' => array(
|
||
'appearance' => array('useCombination' => 1),
|
||
# 'appearance' => array('useCombination' => 1),
|
||
'foreign_selector' => $field,
|
||
),
|
||
'MM' => $config['MM']
|
||
... | ... | |
// get the parent record from structure stack
|
||
$level = $this->getStructureLevel(-1);
|
||
// if we have symmetric fields, check on which side we are and hide fields, that are set automatically
|
||
// If this field is of type 'select', add an additinal criterium:
|
||
// (using a selector for select types doesn't matter, but useCombination does)
|
||
if ($config['type'] == 'select') {
|
||
$searchArray['%OR']['config'][0]['%AND']['%OR']['%AND']['appearance'] = array('useCombination' => 1);
|
||
}
|
||
// If we have symmetric fields, check on which side we are and hide fields, that are set automatically:
|
||
if (t3lib_loadDBGroup::isOnSymmetricSide($level['uid'], $level['config'], $row)) {
|
||
$searchArray['%OR']['config'][0]['%AND']['%OR']['symmetric_field'] = $field;
|
||
$searchArray['%OR']['config'][0]['%AND']['%OR']['symmetric_sortby'] = $field;
|
||
// hide fields, that are set automatically
|
||
// Hide fields, that are set automatically:
|
||
} else {
|
||
$searchArray['%OR']['config'][0]['%AND']['%OR']['foreign_field'] = $field;
|
||
$searchArray['%OR']['config'][0]['%AND']['%OR']['foreign_sortby'] = $field;
|
||
... | ... | |
$margin = $this->inlineStyles['margin-right'];
|
||
return $margin;
|
||
}
|
||
|
||
|
||
/**
|
||
* Works like explode, but the $limit counts from the end of a string.
|
||
*
|
||
* @param string $delim
|
||
* @param string $string
|
||
* @param integer $limit
|
||
* @return array The right exploded array
|
||
*/
|
||
function rightExplode($delim, $string, $limit = null) {
|
||
$result = array();
|
||
$tokens = explode($delim, $string);
|
||
if ($limit > 0) {
|
||
if ($limit > count($tokens)) {
|
||
$limit = count($tokens);
|
||
}
|
||
for ($i=1; $i<$limit; $i++) {
|
||
array_unshift($result, array_pop($tokens));
|
||
}
|
||
if (count($tokens)) {
|
||
array_unshift($result, implode($delim, $tokens));
|
||
}
|
||
return $result;
|
||
} else {
|
||
return $tokens;
|
||
}
|
||
}
|
||
}
|
||
?>
|
typo3/class.browse_links.php (Arbeitskopie) | ||
---|---|---|
}
|
||
}
|
||
function insertElement(table, uid, type, filename,fp,filetype,imagefile,action, close) { //
|
||
if (1=='.($pArr[0]&&!$pArr[1]&&!$pArr[2] ? 1 : 0).') {
|
||
// Call user defined function:
|
||
if (1=='.($pArr[0]&&$pArr[4] ? 1 : 0).') {
|
||
if (parent.window.opener) {
|
||
var res = parent.window.opener.'.$pArr[4].'("'.addslashes($pArr[0]).'",table,uid,type);
|
||
if (res.error && res.message) alert(res.message);
|
||
if (res.close) focusOpenerAndClose(close);
|
||
} else {
|
||
alert("Error - reference to main window is not set properly!");
|
||
parent.close();
|
||
}
|
||
} else if (1=='.($pArr[0]&&!$pArr[1]&&!$pArr[2] ? 1 : 0).') {
|
||
addElement(filename,table+"_"+uid,fp,close);
|
||
} else {
|
||
if (setReferences()) {
|
||
... | ... | |
} else {
|
||
alert("Error - reference to main window is not set properly!");
|
||
}
|
||
if (close) {
|
||
parent.window.opener.focus();
|
||
parent.close();
|
||
}
|
||
focusOpenerAndClose(close);
|
||
}
|
||
return false;
|
||
}
|
||
function addElement(elName,elValue,altElValue,close) { //
|
||
if (parent.window.opener && parent.window.opener.setFormValueFromBrowseWin) {
|
||
parent.window.opener.setFormValueFromBrowseWin("'.$pArr[0].'",altElValue?altElValue:elValue,elName);
|
||
if (close) {
|
||
parent.window.opener.focus();
|
||
parent.close();
|
||
}
|
||
focusOpenerAndClose(close);
|
||
} else {
|
||
alert("Error - reference to main window is not set properly!");
|
||
parent.close();
|
||
}
|
||
}
|
||
function focusOpenerAndClose(close) { //
|
||
if (close) {
|
||
parent.window.opener.focus();
|
||
parent.close();
|
||
}
|
||
}
|
||
';
|
||
// Finally, add the accumulated JavaScript to the template object:
|
||
... | ... | |
function main_db() {
|
||
// Starting content:
|
||
$content=$this->doc->startPage('TBE file selector');
|
||
$content=$this->doc->startPage('TBE record selector');
|
||
// Init variable:
|
||
$pArr = explode('|',$this->bparams);
|