00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00090 class t3lib_TCEforms_inline {
00091 var $fObj;
00092 var $backPath;
00093
00094 var $isAjaxCall = false;
00095 var $inlineStructure = array();
00096 var $inlineFirstPid;
00097 var $inlineNames = array();
00098 var $inlineData = array();
00099 var $inlineView = array();
00100 var $inlineCount = 0;
00101 var $inlineStyles = array();
00102
00103 var $prependNaming = 'data';
00104 var $prependFormFieldNames;
00105 var $prependCmdFieldNames;
00106
00107
00114 function init(&$tceForms) {
00115 $this->fObj =& $tceForms;
00116 $this->backPath =& $tceForms->backPath;
00117 $this->prependFormFieldNames =& $this->fObj->prependFormFieldNames;
00118 $this->prependCmdFieldNames =& $this->fObj->prependCmdFieldNames;
00119 $this->inlineStyles['margin-right'] = '5';
00120 }
00121
00122
00133 function getSingleField_typeInline($table,$field,$row,&$PA) {
00134
00135 if ($this->checkConfiguration($PA['fieldConf']['config']) === false) return false;
00136
00137
00138 $this->inlineCount++;
00139
00140
00141 $config = $PA['fieldConf']['config'];
00142 $foreign_table = $config['foreign_table'];
00143 t3lib_div::loadTCA($foreign_table);
00144
00145 $minitems = t3lib_div::intInRange($config['minitems'],0);
00146 $maxitems = t3lib_div::intInRange($config['maxitems'],0);
00147 if (!$maxitems) $maxitems=100000;
00148
00149
00150 $this->fObj->requiredElements[$PA['itemFormElName']] = array($minitems,$maxitems,'imgName'=>$table.'_'.$row['uid'].'_'.$field);
00151
00152
00153
00154 if (!isset($this->inlineFirstPid)) {
00155
00156
00157 if (t3lib_div::testInt($row['uid'])) {
00158 $inlineView = unserialize($GLOBALS['BE_USER']->uc['inlineView']);
00159 $this->inlineView = $inlineView[$table][$row['uid']];
00160 }
00161
00162 if ($table == 'pages') {
00163 $this->inlineFirstPid = $row['uid'];
00164
00165 } elseif ($row['pid'] < 0) {
00166 $prevRec = t3lib_BEfunc::getRecord($table, abs($row['pid']));
00167 $this->inlineFirstPid = $prevRec['pid'];
00168
00169 } else {
00170 $this->inlineFirstPid = $row['pid'];
00171 }
00172 }
00173
00174 $this->pushStructure($table, $row['uid'], $field, $config);
00175
00176 $nameForm = $this->inlineNames['form'];
00177
00178 $nameObject = $this->inlineNames['object'];
00179
00180 $recordList = $this->getRelatedRecords($table,$field,$row,$PA,$config);
00181
00182 $config['inline']['first'] = $recordList[0]['uid'];
00183 $config['inline']['last'] = $recordList[count($recordList)-1]['uid'];
00184
00185
00186 $top = $this->getStructureLevel(0);
00187 $this->inlineData['config'][$nameObject] = array('table' => $foreign_table);
00188 $this->inlineData['config'][$nameObject.'['.$foreign_table.']'] = array(
00189 'min' => $minitems,
00190 'max' => $maxitems,
00191 'sortable' => $config['appearance']['useSortable'],
00192 'top' => array(
00193 'table' => $top['table'],
00194 'uid' => $top['uid'],
00195 ),
00196 );
00197
00198 $this->inlineData['nested'][$nameObject] = $this->fObj->getDynNestedStack(false, $this->isAjaxCall);
00199
00200
00201 if ($config['foreign_unique']) {
00202
00203 $selConfig = $this->getPossibleRecordsSelectorConfig($config, $config['foreign_unique']);
00204
00205 $uniqueIds = $this->getUniqueIds($recordList, $config, $selConfig['type']=='groupdb');
00206 $possibleRecords = $this->getPossibleRecords($table,$field,$row,$config,'foreign_unique');
00207 $uniqueMax = $config['appearance']['useCombination'] || $possibleRecords === false ? -1 : count($possibleRecords);
00208 $this->inlineData['unique'][$nameObject.'['.$foreign_table.']'] = array(
00209 'max' => $uniqueMax,
00210 'used' => $uniqueIds,
00211 'type' => $selConfig['type'],
00212 'table' => $config['foreign_table'],
00213 'elTable' => $selConfig['table'],
00214 'field' => $config['foreign_unique'],
00215 'selector' => $selConfig['selector'],
00216 'possible' => $this->getPossibleRecordsFlat($possibleRecords),
00217 );
00218 }
00219
00220
00221 if ($config['foreign_selector']) {
00222
00223 if (!$config['foreign_unique']) {
00224 $possibleRecords = $this->getPossibleRecords($table,$field,$row,$config);
00225 $uniqueIds = array();
00226 }
00227 $selectorBox = $this->renderPossibleRecordsSelector($possibleRecords,$config,$uniqueIds);
00228 $item .= $selectorBox;
00229 }
00230
00231
00232 $item .= '<div id="'.$nameObject.'">';
00233
00234
00235 if (count($recordList) >= $maxitems || ($uniqueMax > 0 && count($recordList) >= $uniqueMax)) {
00236 $config['inline']['inlineNewButtonStyle'] = 'display: none;';
00237 }
00238
00239 if (in_array($config['appearance']['newRecordLinkPosition'], array('both', 'top'))) {
00240 $item .= $this->getNewRecordLink($nameObject.'['.$foreign_table.']', $config);
00241 }
00242
00243 $item .= '<div id="'.$nameObject.'_records">';
00244 $relationList = array();
00245 if (count($recordList)) {
00246 foreach ($recordList as $rec) {
00247 $item .= $this->renderForeignRecord($row['uid'],$rec,$config);
00248 $relationList[] = $rec['uid'];
00249 }
00250 }
00251 $item .= '</div>';
00252
00253
00254 if (in_array($config['appearance']['newRecordLinkPosition'], array('both', 'bottom'))) {
00255 $item .= $this->getNewRecordLink($nameObject.'['.$foreign_table.']', $config);
00256 }
00257
00258
00259 if (count($relationList) > 1 && $config['appearance']['useSortable'])
00260 $this->addJavaScriptSortable($nameObject.'_records');
00261
00262 $item .= '<input type="hidden" name="'.$nameForm.'" value="'.implode(',', $relationList).'" class="inlineRecord" />';
00263
00264 $item .= '</div>';
00265
00266
00267 $this->popStructure();
00268
00269
00270 if (!$this->getStructureDepth()) {
00271 unset($this->inlineFirstPid);
00272 }
00273
00274 return $item;
00275 }
00276
00277
00278
00279
00280
00281
00282
00283
00284
00293 function renderForeignRecord($parentUid, $rec, $config = array()) {
00294 $foreign_table = $config['foreign_table'];
00295 $foreign_field = $config['foreign_field'];
00296 $foreign_selector = $config['foreign_selector'];
00297
00298
00299
00300 $this->inlineData['map'][$this->inlineNames['form']] = $this->inlineNames['object'];
00301
00302
00303 $isNewRecord = t3lib_div::testInt($rec['uid']) ? false : true;
00304
00305 if ($foreign_selector) {
00306 $rec[$foreign_selector] = $this->normalizeUid($rec[$foreign_selector]);
00307 }
00308
00309 $hasAccess = $this->checkAccess($isNewRecord?'new':'edit', $foreign_table, $rec['uid']);
00310
00311 if(!$hasAccess) return false;
00312
00313
00314 $nameObject = $this->inlineNames['object'];
00315 $appendFormFieldNames = '['.$foreign_table.']['.$rec['uid'].']';
00316 $formFieldNames = $nameObject.$appendFormFieldNames;
00317
00318 $this->fObj->pushToDynNestedStack('inline', $this->inlineNames['object'].$appendFormFieldNames);
00319
00320 $header = $this->renderForeignRecordHeader($parentUid, $foreign_table, $rec, $config);
00321 $combination = $this->renderCombinationTable($rec, $appendFormFieldNames, $config);
00322 $fields = $this->fObj->getMainFields($foreign_table,$rec);
00323 $fields = $this->wrapFormsSection($fields);
00324
00325 if ($isNewRecord) {
00326
00327 $isExpanded = is_array($config['appearance']) && $config['appearance']['collapseAll'] ? 1 : 0;
00328
00329 $top = $this->getStructureLevel(0);
00330 $ucFieldName = 'uc['.$top['table'].']['.$top['uid'].']'.$appendFormFieldNames;
00331
00332 $fields .= '<input type="hidden" name="'.$this->prependFormFieldNames.$appendFormFieldNames.'[pid]" value="'.$rec['pid'].'"/>';
00333 $fields .= '<input type="hidden" name="'.$ucFieldName.'" value="'.$isExpanded.'" />';
00334
00335 } else {
00336
00337 $isExpanded = $this->getExpandedCollapsedState($foreign_table, $rec['uid']);
00338
00339 $fields .= '<input type="hidden" name="'.$this->prependCmdFieldNames.$appendFormFieldNames.'[delete]" value="1" disabled="disabled" />';
00340 }
00341
00342
00343 if (!$isExpanded) $appearanceStyleFields = ' style="display: none;"';
00344
00345
00346 $out = '<div id="'.$formFieldNames.'_header">'.$header.'</div>';
00347 $out .= '<div id="'.$formFieldNames.'_fields"'.$appearanceStyleFields.'>'.$fields.$combination.'</div>';
00348
00349 $out = '<div id="'.$formFieldNames.'_div"'.($isNewRecord ? ' class="inlineIsNewRecord"' : '').'>' . $out . '</div>';
00350
00351
00352 $this->fObj->popFromDynNestedStack();
00353
00354 return $out;
00355 }
00356
00357
00368 function renderForeignRecordHeader($parentUid, $foreign_table, $rec, $config = array()) {
00369
00370 $formFieldNames = $this->inlineNames['object'].'['.$foreign_table.']['.$rec['uid'].']';
00371 $expandSingle = $config['appearance']['expandSingle'] ? 1 : 0;
00372 $onClick = "return inline.expandCollapseRecord('".htmlspecialchars($formFieldNames)."', $expandSingle)";
00373
00374
00375 $isOnSymmetricSide = t3lib_loadDBGroup::isOnSymmetricSide($parentUid, $config, $rec);
00376 $hasForeignLabel = !$isOnSymmetricSide && $config['foreign_label'] ? true : false;
00377 $hasSymmetricLabel = $isOnSymmetricSide && $config['symmetric_label'] ? true : false;
00378
00379
00380 if ($GLOBALS['TCA'][$foreign_table]['ctrl']['label_userFunc']) {
00381 $params = array(
00382 'table' => $foreign_table,
00383 'row' => $rec,
00384 'title' => '',
00385 'isOnSymmetricSide' => $isOnSymmetricSide
00386 );
00387 $null = null;
00388 t3lib_div::callUserFunction($GLOBALS['TCA'][$foreign_table]['ctrl']['label_userFunc'], $params, $null);
00389 $recTitle = $params['title'];
00390
00391 } elseif ($hasForeignLabel || $hasSymmetricLabel) {
00392 $titleCol = $hasForeignLabel ? $config['foreign_label'] : $config['symmetric_label'];
00393 $foreignConfig = $this->getPossibleRecordsSelectorConfig($config, $titleCol);
00394
00395 if ($foreignConfig['type'] != 'groupdb') {
00396 $recTitle = t3lib_BEfunc::getProcessedValueExtra($foreign_table, $titleCol, $rec[$titleCol], 0, 0, false);
00397
00398 } else {
00399
00400 $valueParts = t3lib_div::trimExplode('|', $rec[$titleCol]);
00401 $itemParts = t3lib_div::revExplode('_', $valueParts[0], 2);
00402 $recTemp = t3lib_befunc::getRecordWSOL($itemParts[0], $itemParts[1]);
00403 $recTitle = t3lib_BEfunc::getRecordTitle($itemParts[0], $recTemp, true);
00404 }
00405 $recTitle = t3lib_BEfunc::getRecordTitlePrep($recTitle);
00406 if (!strcmp(trim($recTitle),'')) {
00407 $recTitle = t3lib_BEfunc::getNoRecordTitle(true);
00408 }
00409
00410 } else {
00411 $recTitle = t3lib_BEfunc::getRecordTitle($foreign_table, $rec, true);
00412 }
00413
00414 $altText = t3lib_BEfunc::getRecordIconAltText($rec, $foreign_table);
00415 $iconImg =
00416 '<a href="#" onclick="'.htmlspecialchars($onClick).'">'.t3lib_iconWorks::getIconImage(
00417 $foreign_table, $rec, $this->backPath,
00418 'title="'.htmlspecialchars($altText).'" class="absmiddle"'
00419 ).'</a>';
00420
00421 $label =
00422 '<a href="#" onclick="'.htmlspecialchars($onClick).'" style="display: block;">'.
00423 '<span id="'.$formFieldNames.'_label">'.$recTitle.'</span>'.
00424 '</a>';
00425
00426 $ctrl = $this->renderForeignRecordHeaderControl($parentUid, $foreign_table, $rec, $config);
00427
00428
00429 $header =
00430 '<table cellspacing="0" cellpadding="0" border="0" width="100%" style="margin-right: '.$this->inlineStyles['margin-right'].'px;"'.
00431 ($this->fObj->borderStyle[2] ? ' background="'.htmlspecialchars($this->backPath.$this->fObj->borderStyle[2]).'"':'').
00432 ($this->fObj->borderStyle[3] ? ' class="'.htmlspecialchars($this->fObj->borderStyle[3]).'"':'').'>' .
00433 '<tr class="class-main12"><td width="18">'.$iconImg.'</td><td align="left"><b>'.$label.'</b></td><td align="right">'.$ctrl.'</td></tr></table>';
00434
00435 return $header;
00436 }
00437
00438
00449 function renderForeignRecordHeaderControl($parentUid, $foreign_table, $rec, $config = array()) {
00450
00451 $cells=array();
00452 $isNewItem = substr($rec['uid'], 0, 3) == 'NEW';
00453
00454 $tcaTableCtrl =& $GLOBALS['TCA'][$foreign_table]['ctrl'];
00455 $tcaTableCols =& $GLOBALS['TCA'][$foreign_table]['columns'];
00456
00457 $isPagesTable = $foreign_table == 'pages' ? true : false;
00458 $isOnSymmetricSide = t3lib_loadDBGroup::isOnSymmetricSide($parentUid, $config, $rec);
00459 $enableManualSorting = $tcaTableCtrl['sortby'] || $config['MM'] || (!$isOnSymmetricSide && $config['foreign_sortby']) || ($isOnSymmetricSide && $config['symmetric_sortby']) ? true : false;
00460
00461 $nameObjectFt = $this->inlineNames['object'].'['.$foreign_table.']';
00462 $nameObjectFtId = $nameObjectFt.'['.$rec['uid'].']';
00463
00464 $calcPerms = $GLOBALS['BE_USER']->calcPerms(
00465 t3lib_BEfunc::readPageAccess($rec['pid'], $GLOBALS['BE_USER']->getPagePermsClause(1))
00466 );
00467
00468
00469 if ($isPagesTable) {
00470 $localCalcPerms = $GLOBALS['BE_USER']->calcPerms(t3lib_BEfunc::getRecord('pages',$rec['uid']));
00471 }
00472
00473
00474 $permsEdit = ($isPagesTable && ($localCalcPerms&2)) || (!$isPagesTable && ($calcPerms&16));
00475
00476
00477 if (!$isNewItem)
00478 $cells[]='<a href="#" onclick="'.htmlspecialchars('top.launchView(\''.$foreign_table.'\', \''.$rec['uid'].'\'); return false;').'">'.
00479 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/zoom2.gif','width="12" height="12"').' title="'.$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.xml:showInfo',1).'" alt="" />'.
00480 '</a>';
00481
00482
00483 if (!$tcaTableCtrl['readOnly']) {
00484
00485
00486 if ($enableManualSorting || $tcaTableCtrl['useColumnsForDefaultValues']) {
00487 if (
00488 (!$isPagesTable && ($calcPerms&16)) ||
00489 ($isPagesTable && ($calcPerms&8))
00490 ) {
00491 $onClick = "return inline.createNewRecord('".$nameObjectFt."','".$rec['uid']."')";
00492 if ($config['inline']['inlineNewButtonStyle']) {
00493 $style = ' style="'.$config['inline']['inlineNewButtonStyle'].'"';
00494 }
00495 $cells[]='<a href="#" onclick="'.htmlspecialchars($onClick).'" class="inlineNewButton"'.$style.'>'.
00496 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/new_'.($isPagesTable?'page':'el').'.gif','width="'.($isPagesTable?13:11).'" height="12"').' title="'.$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.xml:new'.($isPagesTable?'Page':'Record'),1).'" alt="" />'.
00497 '</a>';
00498 }
00499 }
00500
00501
00502 if ($permsEdit && $enableManualSorting && $config['appearance']['useSortable']) {
00503 $cells[] = '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/move.gif','width="16" height="16" hspace="2"').' title="'.$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.move',1).'" alt="" style="cursor: move;" class="sortableHandle" />';
00504 }
00505
00506
00507 if ($permsEdit && $enableManualSorting) {
00508 $onClick = "return inline.changeSorting('".$nameObjectFtId."', '1')";
00509 $style = $config['inline']['first'] == $rec['uid'] ? 'style="visibility: hidden;"' : '';
00510 $cells[]='<a href="#" onclick="'.htmlspecialchars($onClick).'" class="sortingUp" '.$style.'>'.
00511 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/button_up.gif','width="11" height="10"').' title="'.$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.xml:moveUp',1).'" alt="" />'.
00512 '</a>';
00513
00514 $onClick = "return inline.changeSorting('".$nameObjectFtId."', '-1')";
00515 $style = $config['inline']['last'] == $rec['uid'] ? 'style="visibility: hidden;"' : '';
00516 $cells[]='<a href="#" onclick="'.htmlspecialchars($onClick).'" class="sortingDown" '.$style.'>'.
00517 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/button_down.gif','width="11" height="10"').' title="'.$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.xml:moveDown',1).'" alt="" />'.
00518 '</a>';
00519 }
00520
00521
00522 $hiddenField = $tcaTableCtrl['enablecolumns']['disabled'];
00523 if ($permsEdit && $hiddenField && $tcaTableCols[$hiddenField] && (!$tcaTableCols[$hiddenField]['exclude'] || $GLOBALS['BE_USER']->check('non_exclude_fields',$foreign_table.':'.$hiddenField))) {
00524 $onClick = "return inline.enableDisableRecord('".$nameObjectFtId."')";
00525 if ($rec[$hiddenField]) {
00526 $cells[]='<a href="#" onclick="'.htmlspecialchars($onClick).'">'.
00527 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/button_unhide.gif','width="11" height="10"').' title="'.$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.xml:unHide'.($isPagesTable?'Page':''),1).'" alt="" id="'.$nameObjectFtId.'_disabled" />'.
00528 '</a>';
00529 } else {
00530 $cells[]='<a href="#" onclick="'.htmlspecialchars($onClick).'">'.
00531 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/button_hide.gif','width="11" height="10"').' title="'.$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.xml:hide'.($isPagesTable?'Page':''),1).'" alt="" id="'.$nameObjectFtId.'_disabled" />'.
00532 '</a>';
00533 }
00534 }
00535
00536
00537 if (
00538 ($isPagesTable && ($localCalcPerms&4)) || (!$isPagesTable && ($calcPerms&16))
00539 ) {
00540 $onClick = "inline.deleteRecord('".$nameObjectFtId."');";
00541 $cells[]='<a href="#" onclick="'.htmlspecialchars('if (confirm('.$GLOBALS['LANG']->JScharCode($GLOBALS['LANG']->getLL('deleteWarning')).')) { '.$onClick.' } return false;').'">'.
00542 '<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="" />'.
00543 '</a>';
00544 }
00545 }
00546
00547
00548 if ($lockInfo=t3lib_BEfunc::isRecordLocked($foreign_table,$rec['uid'])) {
00549 $cells[]='<a href="#" onclick="'.htmlspecialchars('alert('.$GLOBALS['LANG']->JScharCode($lockInfo['msg']).');return false;').'">'.
00550 '<img'.t3lib_iconWorks::skinImg('','gfx/recordlock_warning3.gif','width="17" height="12"').' title="'.htmlspecialchars($lockInfo['msg']).'" alt="" />'.
00551 '</a>';
00552 }
00553
00554
00555 return '
00556 <!-- CONTROL PANEL: '.$foreign_table.':'.$rec['uid'].' -->
00557 <div class="typo3-DBctrl">'.implode('',$cells).'</div>';
00558 }
00559
00560
00571 function renderCombinationTable(&$rec, $appendFormFieldNames, $config = array()) {
00572 $foreign_table = $config['foreign_table'];
00573 $foreign_selector = $config['foreign_selector'];
00574
00575 if ($foreign_selector && $config['appearance']['useCombination']) {
00576 $comboConfig = $GLOBALS['TCA'][$foreign_table]['columns'][$foreign_selector]['config'];
00577 $comboRecord = array();
00578
00579
00580 if (t3lib_div::testInt($rec[$foreign_selector])) {
00581 $comboRecord = $this->getRecord(
00582 $this->inlineFirstPid,
00583 $comboConfig['foreign_table'],
00584 $rec[$foreign_selector]
00585 );
00586 $isNewRecord = false;
00587
00588 } else {
00589 $comboRecord = $this->getNewRecord(
00590 $this->inlineFirstPid,
00591 $comboConfig['foreign_table']
00592 );
00593 $isNewRecord = true;
00594 }
00595
00596
00597 $out = $this->fObj->getMainFields($comboConfig['foreign_table'], $comboRecord);
00598 $out = $this->wrapFormsSection($out, array(), array('class' => 'wrapperAttention'));
00599
00600
00601 if ($isNewRecord) {
00602 $comboFormFieldName = $this->prependFormFieldNames.'['.$comboConfig['foreign_table'].']['.$comboRecord['uid'].'][pid]';
00603 $out .= '<input type="hidden" name="'.$comboFormFieldName.'" value="'.$this->inlineFirstPid.'"/>';
00604 }
00605
00606
00607 if ($isNewRecord || $config['foreign_unique'] == $foreign_selector) {
00608 $parentFormFieldName = $this->prependFormFieldNames.$appendFormFieldNames.'['.$foreign_selector.']';
00609 $out .= '<input type="hidden" name="'.$parentFormFieldName.'" value="'.$comboRecord['uid'].'" />';
00610 }
00611 }
00612
00613 return $out;
00614 }
00615
00616
00626 function renderPossibleRecordsSelector($selItems, $conf, $uniqueIds=array()) {
00627 $foreign_table = $conf['foreign_table'];
00628 $foreign_selector = $conf['foreign_selector'];
00629
00630 $selConfig = $this->getPossibleRecordsSelectorConfig($conf, $foreign_selector);
00631 $config = $selConfig['PA']['fieldConf']['config'];
00632
00633 if ($selConfig['type'] == 'select') {
00634 $item = $this->renderPossibleRecordsSelectorTypeSelect($selItems, $conf, $selConfig['PA'], $uniqueIds);
00635 } elseif ($selConfig['type'] == 'groupdb') {
00636 $item = $this->renderPossibleRecordsSelectorTypeGroupDB($conf, $selConfig['PA']);
00637 }
00638
00639 return $item;
00640 }
00641
00642
00653 function renderPossibleRecordsSelectorTypeSelect($selItems, $conf, &$PA, $uniqueIds=array()) {
00654 $foreign_table = $conf['foreign_table'];
00655 $foreign_selector = $conf['foreign_selector'];
00656
00657 $PA = array();
00658 $PA['fieldConf'] = $GLOBALS['TCA'][$foreign_table]['columns'][$foreign_selector];
00659 $PA['fieldConf']['config']['form_type'] = $PA['fieldConf']['config']['form_type'] ? $PA['fieldConf']['config']['form_type'] : $PA['fieldConf']['config']['type'];
00660 $PA['fieldTSConfig'] = $this->fObj->setTSconfig($foreign_table,array(),$foreign_selector);
00661 $config = $PA['fieldConf']['config'];
00662
00663 if(!$disabled) {
00664
00665 $opt = array();
00666 $styleAttrValue = '';
00667 foreach($selItems as $p) {
00668 if ($config['iconsInOptionTags']) {
00669 $styleAttrValue = $this->fObj->optionTagStyle($p[2]);
00670 }
00671 if (!in_array($p[1], $uniqueIds)) {
00672 $opt[]= '<option value="'.htmlspecialchars($p[1]).'"'.
00673 ' style="'.(in_array($p[1], $uniqueIds) ? '' : '').
00674 ($styleAttrValue ? ' style="'.htmlspecialchars($styleAttrValue) : '').'">'.
00675 htmlspecialchars($p[0]).'</option>';
00676 }
00677 }
00678
00679 // Put together the selector box:
00680 $selector_itemListStyle = isset($config['itemListStyle']) ? ' style="'.htmlspecialchars($config['itemListStyle']).'"' : ' style="'.$this->fObj->defaultMultipleSelectorStyle.'"';
00681 $size = intval($conf['size']);
00682 $size = $conf['autoSizeMax'] ? t3lib_div::intInRange(count($itemArray)+1,t3lib_div::intInRange($size,1),$conf['autoSizeMax']) : $size;
00683 $onChange = "return inline.importNewRecord('".$this->inlineNames['object']."[".$conf['foreign_table']."]')";
00684 $item = '
00685 <select id="'.$this->inlineNames['object'].'['.$conf['foreign_table'].']_selector"'.
00686 $this->fObj->insertDefStyle('select').
00687 ($size ? ' size="'.$size.'"' : '').
00688 ' onchange="'.htmlspecialchars($onChange).'"'.
00689 $PA['onFocus'].
00690 $selector_itemListStyle.
00691 ($conf['foreign_unique'] ? ' isunique="isunique"' : '').'>
00692 '.implode('
00693 ',$opt).'
00694 </select>';
00695
00696
00697
00698
00699
00700 $createNewRelationText = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:cm.createNewRelation',1);
00701 $item .=
00702 '<a href="#" onclick="'.htmlspecialchars($onChange).'" align="abstop">'.
00703 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/edit2.gif','width="11" height="12"').' align="absmiddle" '.t3lib_BEfunc::titleAltAttrib($createNewRelationText).' /> '.$createNewRelationText.
00704 '</a>';
00705
00706 $item = '<div style="margin-bottom: 20px;">'.$item.'</div>';
00707 }
00708
00709 return $item;
00710 }
00711
00712
00721 function renderPossibleRecordsSelectorTypeGroupDB($conf, &$PA) {
00722 $foreign_table = $conf['foreign_table'];
00723
00724 $config = $PA['fieldConf']['config'];
00725 $allowed = $config['allowed'];
00726 $objectPrefix = $this->inlineNames['object'].'['.$foreign_table.']';
00727
00728 $createNewRelationText = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:cm.createNewRelation',1);
00729 $onClick = "setFormValueOpenBrowser('db','".('|||'.$allowed.'|'.$objectPrefix.'|inline.checkUniqueElement||inline.importElement')."'); return false;";
00730 $item =
00731 '<a href="#" onclick="'.htmlspecialchars($onClick).'">'.
00732 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/insert3.gif','width="14" height="14"').' align="absmiddle" '.t3lib_BEfunc::titleAltAttrib($createNewRelationText).' /> '.$createNewRelationText.
00733 '</a>';
00734
00735 return $item;
00736 }
00737
00738
00746 function getNewRecordLink($objectPrefix, $conf = array()) {
00747 if ($conf['inline']['inlineNewButtonStyle']) $style = ' style="'.$conf['inline']['inlineNewButtonStyle'].'"';
00748
00749 $onClick = "return inline.createNewRecord('$objectPrefix')";
00750 $title = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:cm.createnew',1);
00751
00752 if ($conf['appearance']['newRecordLinkAddTitle'])
00753 $tableTitle .= ' '.$GLOBALS['LANG']->sL($GLOBALS['TCA'][$conf['foreign_table']]['ctrl']['title'],1);
00754
00755 $out = '
00756 <div class="typo3-newRecordLink">
00757 <a href="#" onClick="'.$onClick.'" class="inlineNewButton"'.$style.' title="'.$title.$tableTitle.'">'.
00758 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/new_el.gif','width="11" height="12"').' alt="'.$title.$tableTitle.'" />'.
00759 $title.t3lib_div::fixed_lgd_cs($tableTitle, $this->fObj->titleLen).
00760 '</a>
00761 </div>';
00762 return $out;
00763 }
00764
00765
00772 function addJavaScriptSortable($objectId) {
00773 $this->fObj->additionalJS_post[] = '
00774 inline.createDragAndDropSorting("'.$objectId.'");
00775 ';
00776 }
00777
00778
00779
00780
00781
00782
00783
00784
00785
00793 function initForAJAX($method, &$arguments) {
00794
00795 if ($method == 'createNewRecord') {
00796 $this->fObj->RTEcounter = intval(array_shift($arguments));
00797 }
00798 }
00799
00800
00809 function createNewRecord($domObjectId, $foreignUid = 0) {
00810 $this->isAjaxCall = true;
00811
00812 $this->parseStructureString($domObjectId, true);
00813
00814 $current = $this->inlineStructure['unstable'];
00815
00816 $parent = $this->getStructureLevel(-1);
00817
00818 $config = $parent['config'];
00819
00820
00821 $this->fObj->pushToDynNestedStack('inline', $this->inlineNames['object']);
00822
00823
00824 if (!$foreignUid || !t3lib_div::testInt($foreignUid) || $config['foreign_selector']) {
00825 $record = $this->getNewRecord($this->inlineFirstPid, $current['table']);
00826
00827
00828 } else {
00829 $record = $this->getRecord($this->inlineFirstPid, $current['table'], $foreignUid);
00830 }
00831
00832
00833
00834
00835 if ($config['foreign_selector'] && $foreignUid) {
00836 $selConfig = $this->getPossibleRecordsSelectorConfig($config, $config['foreign_selector']);
00837
00838 $record[$config['foreign_selector']] = $selConfig['type'] != 'groupdb' ? '' : $selConfig['table'].'_';
00839 $record[$config['foreign_selector']] .= $foreignUid;
00840 }
00841
00842
00843 $objectPrefix = $this->inlineNames['object'].'['.$current['table'].']';
00844 $objectId = $objectPrefix.'['.$record['uid'].']';
00845
00846
00847 $item = $this->renderForeignRecord($parent['uid'], $record, $config);
00848 if($item === false) {
00849 $jsonArray = array(
00850 'data' => 'Access denied',
00851 'scriptCall' => array(
00852 "alert('Access denied');",
00853 )
00854 );
00855 return $this->getJSON($jsonArray);
00856 }
00857
00858
00859 $item = $GLOBALS['LANG']->csConvObj->utf8_encode($item, $GLOBALS['LANG']->charSet);
00860
00861 if (!$current['uid']) {
00862 $jsonArray = array(
00863 'data' => $item,
00864 'scriptCall' => array(
00865 "inline.domAddNewRecord('bottom','".$this->inlineNames['object']."_records','$objectPrefix',json.data);",
00866 "inline.memorizeAddRecord('$objectPrefix','".$record['uid']."',null,'$foreignUid');"
00867 )
00868 );
00869
00870
00871 } else {
00872 $jsonArray = array(
00873 'data' => $item,
00874 'scriptCall' => array(
00875 "inline.domAddNewRecord('after','".$domObjectId.'_div'."','$objectPrefix',json.data);",
00876 "inline.memorizeAddRecord('$objectPrefix','".$record['uid']."','".$current['uid']."','$foreignUid');"
00877 )
00878 );
00879 }
00880
00881
00882 $jsonArray['scriptCall'][] = $this->fObj->JSbottom($this->fObj->formName, true);
00883
00884 if ($config['appearance']['useSortable'])
00885 $jsonArray['scriptCall'][] = "inline.createDragAndDropSorting('".$this->inlineNames['object']."_records');";
00886
00887 if ($this->fObj->extJSCODE)
00888 $jsonArray['scriptCall'][] = $this->fObj->extJSCODE;
00889
00890 $jsonArray['scriptCall'][] = "Element.scrollTo('".$objectId."_div');";
00891
00892 $jsonArray['scriptCall'][] = "inline.fadeOutFadeIn('".$objectId."_div');";
00893
00894
00895 $this->fObj->popFromDynNestedStack();
00896
00897
00898 return $this->getJSON($jsonArray);
00899 }
00900
00901
00910 function setExpandedCollapsedState($domObjectId, $expand, $collapse) {
00911
00912 $this->parseStructureString($domObjectId, false);
00913
00914 $current = $this->inlineStructure['unstable'];
00915
00916 $top = $this->getStructureLevel(0);
00917
00918
00919 if (t3lib_div::testInt($top['uid'])) {
00920 $inlineView = unserialize($GLOBALS['BE_USER']->uc['inlineView']);
00921 $inlineViewCurrent =& $inlineView[$top['table']][$top['uid']];
00922
00923 $expandUids = t3lib_div::trimExplode(',', $expand);
00924 $collapseUids = t3lib_div::trimExplode(',', $collapse);
00925
00926
00927 foreach ($expandUids as $uid) {
00928 $inlineViewCurrent[$current['table']][] = $uid;
00929 }
00930
00931 foreach ($collapseUids as $uid) {
00932 $inlineViewCurrent[$current['table']] = $this->removeFromArray($uid, $inlineViewCurrent[$current['table']]);
00933 }
00934
00935
00936 if (is_array($inlineViewCurrent[$current['table']])) {
00937 $GLOBALS['BE_USER']->uc['inlineView'] = serialize($inlineView);
00938 $GLOBALS['BE_USER']->writeUC();
00939 }
00940 }
00941 }
00942
00943
00944
00945
00946
00947
00948
00949
00950
00961 function getRelatedRecords($table,$field,$row,&$PA,$config) {
00962 $records = array();
00963
00964
00965 $nMV_label = isset($PA['fieldTSConfig']['noMatchingValue_label']) ? $this->fObj->sL($PA['fieldTSConfig']['noMatchingValue_label']) : '[ '.$this->fObj->getLL('l_noMatchingValue').' ]';
00966
00967
00968 # $this->fObj->requiredElements[$PA['itemFormElName']] = array($minitems,$maxitems,'imgName'=>$table.'_'.$row['uid'].'_'.$field);
00969
00970
00971 $itemArray = t3lib_div::trimExplode(',',$PA['itemFormElValue'],1);
00972 foreach($itemArray as $tk => $tv) {
00973 $tvP = explode('|',$tv,2);
00974
00975 $records[] = $this->getRecord($row['pid'], $config['foreign_table'], $tvP[0]);
00976 }
00977
00978 return $records;
00979 }
00980
00981
00993 function getPossibleRecords($table,$field,$row,$conf,$checkForConfField='foreign_selector') {
00994
00995 $tcaTableCtrl = $GLOBALS['TCA'][$table]['ctrl'];
00996
00997 $foreign_table = $conf['foreign_table'];
00998 $foreign_check = $conf[$checkForConfField];
00999
01000 $foreignConfig = $this->getPossibleRecordsSelectorConfig($conf, $foreign_check);
01001 $PA = $foreignConfig['PA'];
01002 $config = $PA['fieldConf']['config'];
01003
01004 if ($foreignConfig['type'] == 'select') {
01005
01006 $selItems = $this->fObj->addSelectOptionsToItemArray($this->fObj->initItemArray($PA['fieldConf']),$PA['fieldConf'],$this->fObj->setTSconfig($table,$row),$field);
01007 if ($config['itemsProcFunc']) $selItems = $this->fObj->procItems($selItems,$PA['fieldTSConfig']['itemsProcFunc.'],$config,$table,$row,$field);
01008
01009
01010 $removeItems = t3lib_div::trimExplode(',',$PA['fieldTSConfig']['removeItems'],1);
01011 foreach($selItems as $tk => $p) {
01012
01013
01014 $languageDeny = $tcaTableCtrl['languageField'] && !strcmp($tcaTableCtrl['languageField'], $field) && !$GLOBALS['BE_USER']->checkLanguageAccess($p[1]);
01015 $authModeDeny = $config['form_type']=='select' && $config['authMode'] && !$GLOBALS['BE_USER']->checkAuthMode($table,$field,$p[1],$config['authMode']);
01016 if (in_array($p[1],$removeItems) || $languageDeny || $authModeDeny) {
01017 unset($selItems[$tk]);
01018 } elseif (isset($PA['fieldTSConfig']['altLabels.'][$p[1]])) {
01019 $selItems[$tk][0]=$this->fObj->sL($PA['fieldTSConfig']['altLabels.'][$p[1]]);
01020 }
01021
01022
01023 if ($table.'.'.$field == 'pages.doktype') {
01024 if (!($GLOBALS['BE_USER']->isAdmin() || t3lib_div::inList($GLOBALS['BE_USER']->groupData['pagetypes_select'],$p[1]))) {
01025 unset($selItems[$tk]);
01026 }
01027 }
01028 }
01029 } else {
01030 $selItems = false;
01031 }
01032
01033 return $selItems;
01034 }
01035
01044 function getUniqueIds($records, $conf=array(), $splitValue=false) {
01045 $uniqueIds = array();
01046
01047 if ($conf['foreign_unique'] && count($records)) {
01048 foreach ($records as $rec) {
01049 $value = $rec[$conf['foreign_unique']];
01050
01051 if ($splitValue) {
01052 $valueParts = t3lib_div::trimExplode('|', $value);
01053 $itemParts = explode('_', $valueParts[0]);
01054 $value = array(
01055 'uid' => array_pop($itemParts),
01056 'table' => implode('_', $itemParts)
01057 );
01058 }
01059 $uniqueIds[$rec['uid']] = $value;
01060 }
01061 }
01062
01063 return $uniqueIds;
01064 }
01065
01066
01077 function getRecord($pid, $table, $uid, $cmd='') {
01078 $trData = t3lib_div::makeInstance('t3lib_transferData');
01079 $trData->addRawData = TRUE;
01080 # $trData->defVals = $this->defVals;
01081 $trData->lockRecords=1;
01082 $trData->disableRTE = $GLOBALS['SOBE']->MOD_SETTINGS['disableRTE'];
01083
01084 $trData->fetchRecord($table, $uid, ($cmd === 'new' ? 'new' : ''));
01085 reset($trData->regTableItems_data);
01086 $rec = current($trData->regTableItems_data);
01087 $rec['uid'] = $cmd == 'new' ? uniqid('NEW') : $uid;
01088 if ($cmd=='new') $rec['pid'] = $pid;
01089
01090 return $rec;
01091 }
01092
01093
01101 function getNewRecord($pid, $table) {
01102 return $this->getRecord($pid, $table, '', 'new');
01103 }
01104
01105
01106
01107
01108
01109
01110
01111
01112
01123 function pushStructure($table, $uid, $field = '', $config = array()) {
01124 $this->inlineStructure['stable'][] = array(
01125 'table' => $table,
01126 'uid' => $uid,
01127 'field' => $field,
01128 'config' => $config,
01129 );
01130 $this->updateStructureNames();
01131 }
01132
01133
01139 function popStructure() {
01140 if (count($this->inlineStructure['stable'])) {
01141 $popItem = array_pop($this->inlineStructure['stable']);
01142 $this->updateStructureNames();
01143 }
01144 return $popItem;
01145 }
01146
01147
01156 function updateStructureNames() {
01157 $current = $this->getStructureLevel(-1);
01158
01159 if ($current !== false) {
01160 $lastItemName = $this->getStructureItemName($current);
01161 $this->inlineNames = array(
01162 'form' => $this->prependFormFieldNames.$lastItemName,
01163 'object' => $this->prependNaming.'['.$this->inlineFirstPid.']'.$this->getStructurePath(),
01164 );
01165
01166 } else {
01167 $this->inlineNames = array();
01168 }
01169 }
01170
01171
01178 function getStructureItemName($levelData) {
01179 if (is_array($levelData)) {
01180 $name = '['.$levelData['table'].']' .
01181 '['.$levelData['uid'].']' .
01182 (isset($levelData['field']) ? '['.$levelData['field'].']' : '');
01183 }
01184 return $name;
01185 }
01186
01187
01196 function getStructureLevel($level) {
01197 $inlineStructureCount = count($this->inlineStructure['stable']);
01198 if ($level < 0) $level = $inlineStructureCount+$level;
01199 if ($level >= 0 && $level < $inlineStructureCount)
01200 return $this->inlineStructure['stable'][$level];
01201 else
01202 return false;
01203 }
01204
01205
01213 function getStructurePath($structureDepth = -1) {
01214 $structureCount = count($this->inlineStructure['stable']);
01215 if ($structureDepth < 0 || $structureDepth > $structureCount) $structureDepth = $structureCount;
01216
01217 for ($i = 1; $i <= $structureDepth; $i++) {
01218 $current = $this->getStructureLevel(-$i);
01219 $string = $this->getStructureItemName($current).$string;
01220 }
01221
01222 return $string;
01223 }
01224
01225
01238 function parseStructureString($string, $loadConfig = false) {
01239 $unstable = array();
01240 $vector = array('table', 'uid', 'field');
01241 $pattern = '/^'.$this->prependNaming.'\[(.+?)\]\[(.+)\]$/';
01242 if (preg_match($pattern, $string, $match)) {
01243 $this->inlineFirstPid = $match[1];
01244 $parts = explode('][', $match[2]);
01245 $partsCnt = count($parts);
01246 for ($i = 0; $i < $partsCnt; $i++) {
01247 if ($i > 0 && $i % 3 == 0) {
01248
01249 if ($loadConfig) {
01250 t3lib_div::loadTCA($unstable['table']);
01251 $unstable['config'] = $GLOBALS['TCA'][$unstable['table']]['columns'][$unstable['field']]['config'];
01252
01253 $TSconfig = $this->fObj->setTSconfig(
01254 $unstable['table'],
01255 array('uid' => $unstable['uid'], 'pid' => $this->inlineFirstPid),
01256 $unstable['field']
01257 );
01258
01259 if (!$TSconfig['disabled']) {
01260 $unstable['config'] = $this->fObj->overrideFieldConf($unstable['config'], $TSconfig);
01261 }
01262 }
01263 $this->inlineStructure['stable'][] = $unstable;
01264 $unstable = array();
01265 }
01266 $unstable[$vector[$i % 3]] = $parts[$i];
01267 }
01268 $this->updateStructureNames();
01269 if (count($unstable)) $this->inlineStructure['unstable'] = $unstable;
01270 }
01271 }
01272
01273
01274
01275
01276
01277
01278
01279
01280
01287 function checkConfiguration(&$config) {
01288 $foreign_table = $config['foreign_table'];
01289
01290
01291 if (!$foreign_table || !is_array($GLOBALS['TCA'][$foreign_table])) {
01292 return false;
01293 }
01294
01295 if (!is_array($config['appearance'])) {
<