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
00097 var $fObj;
00098 var $backPath;
00099
00100 var $isAjaxCall = false;
00101 var $inlineStructure = array();
00102 var $inlineFirstPid;
00103 var $inlineNames = array();
00104 var $inlineData = array();
00105 var $inlineView = array();
00106 var $inlineCount = 0;
00107 var $inlineStyles = array();
00108
00109 var $prependNaming = 'data';
00110 var $prependFormFieldNames;
00111 var $prependCmdFieldNames;
00112
00113
00120 function init(&$tceForms) {
00121 $this->fObj =& $tceForms;
00122 $this->backPath =& $tceForms->backPath;
00123 $this->prependFormFieldNames =& $this->fObj->prependFormFieldNames;
00124 $this->prependCmdFieldNames =& $this->fObj->prependCmdFieldNames;
00125 $this->inlineStyles['margin-right'] = '5';
00126 }
00127
00128
00139 function getSingleField_typeInline($table,$field,$row,&$PA) {
00140
00141 if ($this->checkConfiguration($PA['fieldConf']['config']) === false) return false;
00142
00143
00144 $this->inlineCount++;
00145
00146
00147 $config = $PA['fieldConf']['config'];
00148 $foreign_table = $config['foreign_table'];
00149 t3lib_div::loadTCA($foreign_table);
00150
00151 $minitems = t3lib_div::intInRange($config['minitems'],0);
00152 $maxitems = t3lib_div::intInRange($config['maxitems'],0);
00153 if (!$maxitems) $maxitems=100000;
00154
00155
00156 $this->fObj->requiredElements[$PA['itemFormElName']] = array($minitems,$maxitems,'imgName'=>$table.'_'.$row['uid'].'_'.$field);
00157
00158
00159
00160 if (!isset($this->inlineFirstPid)) {
00161
00162
00163 if (t3lib_div::testInt($row['uid'])) {
00164 $inlineView = unserialize($GLOBALS['BE_USER']->uc['inlineView']);
00165 $this->inlineView = $inlineView[$table][$row['uid']];
00166 }
00167
00168 if ($table == 'pages') {
00169 $this->inlineFirstPid = $row['uid'];
00170
00171 } elseif ($row['pid'] < 0) {
00172 $prevRec = t3lib_BEfunc::getRecord($table, abs($row['pid']));
00173 $this->inlineFirstPid = $prevRec['pid'];
00174
00175 } else {
00176 $this->inlineFirstPid = $row['pid'];
00177 }
00178 }
00179
00180 $this->pushStructure($table, $row['uid'], $field, $config);
00181
00182 $nameForm = $this->inlineNames['form'];
00183
00184 $nameObject = $this->inlineNames['object'];
00185
00186 $recordList = $this->getRelatedRecords($table,$field,$row,$PA,$config);
00187
00188 $config['inline']['first'] = $recordList[0]['uid'];
00189 $config['inline']['last'] = $recordList[count($recordList)-1]['uid'];
00190
00191
00192 $top = $this->getStructureLevel(0);
00193 $this->inlineData['config'][$nameObject] = array('table' => $foreign_table);
00194 $this->inlineData['config'][$nameObject.'['.$foreign_table.']'] = array(
00195 'min' => $minitems,
00196 'max' => $maxitems,
00197 'sortable' => $config['appearance']['useSortable'],
00198 'top' => array(
00199 'table' => $top['table'],
00200 'uid' => $top['uid'],
00201 ),
00202 );
00203
00204 $this->inlineData['nested'][$nameObject] = $this->fObj->getDynNestedStack(false, $this->isAjaxCall);
00205
00206
00207 if ($config['foreign_unique']) {
00208
00209 $selConfig = $this->getPossibleRecordsSelectorConfig($config, $config['foreign_unique']);
00210
00211 $uniqueIds = $this->getUniqueIds($recordList, $config, $selConfig['type']=='groupdb');
00212 $possibleRecords = $this->getPossibleRecords($table,$field,$row,$config,'foreign_unique');
00213 $uniqueMax = $config['appearance']['useCombination'] || $possibleRecords === false ? -1 : count($possibleRecords);
00214 $this->inlineData['unique'][$nameObject.'['.$foreign_table.']'] = array(
00215 'max' => $uniqueMax,
00216 'used' => $uniqueIds,
00217 'type' => $selConfig['type'],
00218 'table' => $config['foreign_table'],
00219 'elTable' => $selConfig['table'],
00220 'field' => $config['foreign_unique'],
00221 'selector' => $selConfig['selector'],
00222 'possible' => $this->getPossibleRecordsFlat($possibleRecords),
00223 );
00224 }
00225
00226
00227 if ($config['foreign_selector']) {
00228
00229 if (!$config['foreign_unique']) {
00230 $possibleRecords = $this->getPossibleRecords($table,$field,$row,$config);
00231 $uniqueIds = array();
00232 }
00233 $selectorBox = $this->renderPossibleRecordsSelector($possibleRecords,$config,$uniqueIds);
00234 $item .= $selectorBox;
00235 }
00236
00237
00238 $item .= '<div id="'.$nameObject.'">';
00239
00240
00241 if (count($recordList) >= $maxitems || ($uniqueMax > 0 && count($recordList) >= $uniqueMax)) {
00242 $config['inline']['inlineNewButtonStyle'] = 'display: none;';
00243 }
00244
00245 if (in_array($config['appearance']['newRecordLinkPosition'], array('both', 'top'))) {
00246 $item .= $this->getNewRecordLink($nameObject.'['.$foreign_table.']', $config);
00247 }
00248
00249 $item .= '<div id="'.$nameObject.'_records">';
00250 $relationList = array();
00251 if (count($recordList)) {
00252 foreach ($recordList as $rec) {
00253 $item .= $this->renderForeignRecord($row['uid'],$rec,$config);
00254 $relationList[] = $rec['uid'];
00255 }
00256 }
00257 $item .= '</div>';
00258
00259
00260 if (in_array($config['appearance']['newRecordLinkPosition'], array('both', 'bottom'))) {
00261 $item .= $this->getNewRecordLink($nameObject.'['.$foreign_table.']', $config);
00262 }
00263
00264
00265 if (count($relationList) > 1 && $config['appearance']['useSortable'])
00266 $this->addJavaScriptSortable($nameObject.'_records');
00267
00268 $item .= '<input type="hidden" name="'.$nameForm.'" value="'.implode(',', $relationList).'" class="inlineRecord" />';
00269
00270 $item .= '</div>';
00271
00272
00273 $this->popStructure();
00274
00275
00276 if (!$this->getStructureDepth()) {
00277 unset($this->inlineFirstPid);
00278 }
00279
00280 return $item;
00281 }
00282
00283
00284
00285
00286
00287
00288
00289
00290
00299 function renderForeignRecord($parentUid, $rec, $config = array()) {
00300 $foreign_table = $config['foreign_table'];
00301 $foreign_field = $config['foreign_field'];
00302 $foreign_selector = $config['foreign_selector'];
00303
00304
00305
00306 $this->inlineData['map'][$this->inlineNames['form']] = $this->inlineNames['object'];
00307
00308
00309 $isNewRecord = t3lib_div::testInt($rec['uid']) ? false : true;
00310
00311 if ($foreign_selector) {
00312 $rec[$foreign_selector] = $this->normalizeUid($rec[$foreign_selector]);
00313 }
00314
00315 $hasAccess = $this->checkAccess($isNewRecord?'new':'edit', $foreign_table, $rec['uid']);
00316
00317 if(!$hasAccess) return false;
00318
00319
00320 $nameObject = $this->inlineNames['object'];
00321 $appendFormFieldNames = '['.$foreign_table.']['.$rec['uid'].']';
00322 $formFieldNames = $nameObject.$appendFormFieldNames;
00323
00324 $this->fObj->pushToDynNestedStack('inline', $this->inlineNames['object'].$appendFormFieldNames);
00325
00326 $header = $this->renderForeignRecordHeader($parentUid, $foreign_table, $rec, $config);
00327 $combination = $this->renderCombinationTable($rec, $appendFormFieldNames, $config);
00328 $fields = $this->fObj->getMainFields($foreign_table,$rec);
00329 $fields = $this->wrapFormsSection($fields);
00330
00331 if ($isNewRecord) {
00332
00333 $isExpanded = is_array($config['appearance']) && $config['appearance']['collapseAll'] ? 1 : 0;
00334
00335 $top = $this->getStructureLevel(0);
00336 $ucFieldName = 'uc['.$top['table'].']['.$top['uid'].']'.$appendFormFieldNames;
00337
00338 $fields .= '<input type="hidden" name="'.$this->prependFormFieldNames.$appendFormFieldNames.'[pid]" value="'.$rec['pid'].'"/>';
00339 $fields .= '<input type="hidden" name="'.$ucFieldName.'" value="'.$isExpanded.'" />';
00340
00341 } else {
00342
00343 $isExpanded = $this->getExpandedCollapsedState($foreign_table, $rec['uid']);
00344
00345 $fields .= '<input type="hidden" name="'.$this->prependCmdFieldNames.$appendFormFieldNames.'[delete]" value="1" disabled="disabled" />';
00346 }
00347
00348
00349 if (!$isExpanded) $appearanceStyleFields = ' style="display: none;"';
00350
00351
00352 $out = '<div id="'.$formFieldNames.'_header">'.$header.'</div>';
00353 $out .= '<div id="'.$formFieldNames.'_fields"'.$appearanceStyleFields.'>'.$fields.$combination.'</div>';
00354
00355 $out = '<div id="'.$formFieldNames.'_div" class="inlineDiv'.($isNewRecord ? ' inlineIsNewRecord' : '').'">' . $out . '</div>';
00356
00357
00358 $this->fObj->popFromDynNestedStack();
00359
00360 return $out;
00361 }
00362
00363
00374 function renderForeignRecordHeader($parentUid, $foreign_table, $rec, $config = array()) {
00375
00376 $formFieldNames = $this->inlineNames['object'].'['.$foreign_table.']['.$rec['uid'].']';
00377 $expandSingle = $config['appearance']['expandSingle'] ? 1 : 0;
00378 $onClick = "return inline.expandCollapseRecord('".htmlspecialchars($formFieldNames)."', $expandSingle)";
00379
00380
00381 $isOnSymmetricSide = t3lib_loadDBGroup::isOnSymmetricSide($parentUid, $config, $rec);
00382 $hasForeignLabel = !$isOnSymmetricSide && $config['foreign_label'] ? true : false;
00383 $hasSymmetricLabel = $isOnSymmetricSide && $config['symmetric_label'] ? true : false;
00384
00385
00386 if ($GLOBALS['TCA'][$foreign_table]['ctrl']['label_userFunc']) {
00387 $params = array(
00388 'table' => $foreign_table,
00389 'row' => $rec,
00390 'title' => '',
00391 'isOnSymmetricSide' => $isOnSymmetricSide
00392 );
00393 $null = null;
00394 t3lib_div::callUserFunction($GLOBALS['TCA'][$foreign_table]['ctrl']['label_userFunc'], $params, $null);
00395 $recTitle = $params['title'];
00396
00397 } elseif ($hasForeignLabel || $hasSymmetricLabel) {
00398 $titleCol = $hasForeignLabel ? $config['foreign_label'] : $config['symmetric_label'];
00399 $foreignConfig = $this->getPossibleRecordsSelectorConfig($config, $titleCol);
00400
00401 if ($foreignConfig['type'] != 'groupdb') {
00402 $recTitle = t3lib_BEfunc::getProcessedValueExtra($foreign_table, $titleCol, $rec[$titleCol], 0, 0, false);
00403
00404 } else {
00405
00406 $valueParts = t3lib_div::trimExplode('|', $rec[$titleCol]);
00407 $itemParts = t3lib_div::revExplode('_', $valueParts[0], 2);
00408 $recTemp = t3lib_befunc::getRecordWSOL($itemParts[0], $itemParts[1]);
00409 $recTitle = t3lib_BEfunc::getRecordTitle($itemParts[0], $recTemp, true);
00410 }
00411 $recTitle = t3lib_BEfunc::getRecordTitlePrep($recTitle);
00412 if (!strcmp(trim($recTitle),'')) {
00413 $recTitle = t3lib_BEfunc::getNoRecordTitle(true);
00414 }
00415
00416 } else {
00417 $recTitle = t3lib_BEfunc::getRecordTitle($foreign_table, $rec, true);
00418 }
00419
00420 $altText = t3lib_BEfunc::getRecordIconAltText($rec, $foreign_table);
00421 $iconImg =
00422 '<a href="#" onclick="'.htmlspecialchars($onClick).'">'.t3lib_iconWorks::getIconImage(
00423 $foreign_table, $rec, $this->backPath,
00424 'title="'.htmlspecialchars($altText).'" class="absmiddle"'
00425 ).'</a>';
00426
00427 $label =
00428 '<a href="#" onclick="'.htmlspecialchars($onClick).'" style="display: block;">'.
00429 '<span id="'.$formFieldNames.'_label">'.$recTitle.'</span>'.
00430 '</a>';
00431
00432 $ctrl = $this->renderForeignRecordHeaderControl($parentUid, $foreign_table, $rec, $config);
00433
00434
00435 $header =
00436 '<table cellspacing="0" cellpadding="0" border="0" width="100%" style="margin-right: '.$this->inlineStyles['margin-right'].'px;"'.
00437 ($this->fObj->borderStyle[2] ? ' background="'.htmlspecialchars($this->backPath.$this->fObj->borderStyle[2]).'"':'').
00438 ($this->fObj->borderStyle[3] ? ' class="'.htmlspecialchars($this->fObj->borderStyle[3]).'"':'').'>' .
00439 '<tr class="class-main12"><td width="18">'.$iconImg.'</td><td align="left"><b>'.$label.'</b></td><td align="right">'.$ctrl.'</td></tr></table>';
00440
00441 return $header;
00442 }
00443
00444
00455 function renderForeignRecordHeaderControl($parentUid, $foreign_table, $rec, $config = array()) {
00456
00457 $cells=array();
00458 $isNewItem = substr($rec['uid'], 0, 3) == 'NEW';
00459
00460 $tcaTableCtrl =& $GLOBALS['TCA'][$foreign_table]['ctrl'];
00461 $tcaTableCols =& $GLOBALS['TCA'][$foreign_table]['columns'];
00462
00463 $isPagesTable = $foreign_table == 'pages' ? true : false;
00464 $isOnSymmetricSide = t3lib_loadDBGroup::isOnSymmetricSide($parentUid, $config, $rec);
00465 $enableManualSorting = $tcaTableCtrl['sortby'] || $config['MM'] || (!$isOnSymmetricSide && $config['foreign_sortby']) || ($isOnSymmetricSide && $config['symmetric_sortby']) ? true : false;
00466
00467 $nameObjectFt = $this->inlineNames['object'].'['.$foreign_table.']';
00468 $nameObjectFtId = $nameObjectFt.'['.$rec['uid'].']';
00469
00470 $calcPerms = $GLOBALS['BE_USER']->calcPerms(
00471 t3lib_BEfunc::readPageAccess($rec['pid'], $GLOBALS['BE_USER']->getPagePermsClause(1))
00472 );
00473
00474
00475 if ($isPagesTable) {
00476 $localCalcPerms = $GLOBALS['BE_USER']->calcPerms(t3lib_BEfunc::getRecord('pages',$rec['uid']));
00477 }
00478
00479
00480 $permsEdit = ($isPagesTable && ($localCalcPerms&2)) || (!$isPagesTable && ($calcPerms&16));
00481
00482
00483 if (!$isNewItem)
00484 $cells[]='<a href="#" onclick="'.htmlspecialchars('top.launchView(\''.$foreign_table.'\', \''.$rec['uid'].'\'); return false;').'">'.
00485 '<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="" />'.
00486 '</a>';
00487
00488
00489 if (!$tcaTableCtrl['readOnly']) {
00490
00491
00492 if ($enableManualSorting || $tcaTableCtrl['useColumnsForDefaultValues']) {
00493 if (
00494 (!$isPagesTable && ($calcPerms&16)) ||
00495 ($isPagesTable && ($calcPerms&8))
00496 ) {
00497 $onClick = "return inline.createNewRecord('".$nameObjectFt."','".$rec['uid']."')";
00498 if ($config['inline']['inlineNewButtonStyle']) {
00499 $style = ' style="'.$config['inline']['inlineNewButtonStyle'].'"';
00500 }
00501 $cells[]='<a href="#" onclick="'.htmlspecialchars($onClick).'" class="inlineNewButton"'.$style.'>'.
00502 '<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="" />'.
00503 '</a>';
00504 }
00505 }
00506
00507
00508 if ($permsEdit && $enableManualSorting && $config['appearance']['useSortable']) {
00509 $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" />';
00510 }
00511
00512
00513 if ($permsEdit && $enableManualSorting) {
00514 $onClick = "return inline.changeSorting('".$nameObjectFtId."', '1')";
00515 $style = $config['inline']['first'] == $rec['uid'] ? 'style="visibility: hidden;"' : '';
00516 $cells[]='<a href="#" onclick="'.htmlspecialchars($onClick).'" class="sortingUp" '.$style.'>'.
00517 '<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="" />'.
00518 '</a>';
00519
00520 $onClick = "return inline.changeSorting('".$nameObjectFtId."', '-1')";
00521 $style = $config['inline']['last'] == $rec['uid'] ? 'style="visibility: hidden;"' : '';
00522 $cells[]='<a href="#" onclick="'.htmlspecialchars($onClick).'" class="sortingDown" '.$style.'>'.
00523 '<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="" />'.
00524 '</a>';
00525 }
00526
00527
00528 $hiddenField = $tcaTableCtrl['enablecolumns']['disabled'];
00529 if ($permsEdit && $hiddenField && $tcaTableCols[$hiddenField] && (!$tcaTableCols[$hiddenField]['exclude'] || $GLOBALS['BE_USER']->check('non_exclude_fields',$foreign_table.':'.$hiddenField))) {
00530 $onClick = "return inline.enableDisableRecord('".$nameObjectFtId."')";
00531 if ($rec[$hiddenField]) {
00532 $cells[]='<a href="#" onclick="'.htmlspecialchars($onClick).'">'.
00533 '<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" />'.
00534 '</a>';
00535 } else {
00536 $cells[]='<a href="#" onclick="'.htmlspecialchars($onClick).'">'.
00537 '<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" />'.
00538 '</a>';
00539 }
00540 }
00541
00542
00543 if (
00544 ($isPagesTable && ($localCalcPerms&4)) || (!$isPagesTable && ($calcPerms&16))
00545 ) {
00546 $onClick = "inline.deleteRecord('".$nameObjectFtId."');";
00547 $cells[]='<a href="#" onclick="'.htmlspecialchars('if (confirm('.$GLOBALS['LANG']->JScharCode($GLOBALS['LANG']->getLL('deleteWarning')).')) { '.$onClick.' } return false;').'">'.
00548 '<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="" />'.
00549 '</a>';
00550 }
00551 }
00552
00553
00554 if ($lockInfo=t3lib_BEfunc::isRecordLocked($foreign_table,$rec['uid'])) {
00555 $cells[]='<a href="#" onclick="'.htmlspecialchars('alert('.$GLOBALS['LANG']->JScharCode($lockInfo['msg']).');return false;').'">'.
00556 '<img'.t3lib_iconWorks::skinImg('','gfx/recordlock_warning3.gif','width="17" height="12"').' title="'.htmlspecialchars($lockInfo['msg']).'" alt="" />'.
00557 '</a>';
00558 }
00559
00560
00561 return '
00562 <!-- CONTROL PANEL: '.$foreign_table.':'.$rec['uid'].' -->
00563 <div class="typo3-DBctrl">'.implode('',$cells).'</div>';
00564 }
00565
00566
00577 function renderCombinationTable(&$rec, $appendFormFieldNames, $config = array()) {
00578 $foreign_table = $config['foreign_table'];
00579 $foreign_selector = $config['foreign_selector'];
00580
00581 if ($foreign_selector && $config['appearance']['useCombination']) {
00582 $comboConfig = $GLOBALS['TCA'][$foreign_table]['columns'][$foreign_selector]['config'];
00583 $comboRecord = array();
00584
00585
00586 if (t3lib_div::testInt($rec[$foreign_selector])) {
00587 $comboRecord = $this->getRecord(
00588 $this->inlineFirstPid,
00589 $comboConfig['foreign_table'],
00590 $rec[$foreign_selector]
00591 );
00592 $isNewRecord = false;
00593
00594 } else {
00595 $comboRecord = $this->getNewRecord(
00596 $this->inlineFirstPid,
00597 $comboConfig['foreign_table']
00598 );
00599 $isNewRecord = true;
00600 }
00601
00602
00603 $out = $this->fObj->getMainFields($comboConfig['foreign_table'], $comboRecord);
00604 $out = $this->wrapFormsSection($out, array(), array('class' => 'wrapperAttention'));
00605
00606
00607 if ($isNewRecord) {
00608 $comboFormFieldName = $this->prependFormFieldNames.'['.$comboConfig['foreign_table'].']['.$comboRecord['uid'].'][pid]';
00609 $out .= '<input type="hidden" name="'.$comboFormFieldName.'" value="'.$this->inlineFirstPid.'"/>';
00610 }
00611
00612
00613 if ($isNewRecord || $config['foreign_unique'] == $foreign_selector) {
00614 $parentFormFieldName = $this->prependFormFieldNames.$appendFormFieldNames.'['.$foreign_selector.']';
00615 $out .= '<input type="hidden" name="'.$parentFormFieldName.'" value="'.$comboRecord['uid'].'" />';
00616 }
00617 }
00618
00619 return $out;
00620 }
00621
00622
00632 function renderPossibleRecordsSelector($selItems, $conf, $uniqueIds=array()) {
00633 $foreign_table = $conf['foreign_table'];
00634 $foreign_selector = $conf['foreign_selector'];
00635
00636 $selConfig = $this->getPossibleRecordsSelectorConfig($conf, $foreign_selector);
00637 $config = $selConfig['PA']['fieldConf']['config'];
00638
00639 if ($selConfig['type'] == 'select') {
00640 $item = $this->renderPossibleRecordsSelectorTypeSelect($selItems, $conf, $selConfig['PA'], $uniqueIds);
00641 } elseif ($selConfig['type'] == 'groupdb') {
00642 $item = $this->renderPossibleRecordsSelectorTypeGroupDB($conf, $selConfig['PA']);
00643 }
00644
00645 return $item;
00646 }
00647
00648
00659 function renderPossibleRecordsSelectorTypeSelect($selItems, $conf, &$PA, $uniqueIds=array()) {
00660 $foreign_table = $conf['foreign_table'];
00661 $foreign_selector = $conf['foreign_selector'];
00662
00663 $PA = array();
00664 $PA['fieldConf'] = $GLOBALS['TCA'][$foreign_table]['columns'][$foreign_selector];
00665 $PA['fieldConf']['config']['form_type'] = $PA['fieldConf']['config']['form_type'] ? $PA['fieldConf']['config']['form_type'] : $PA['fieldConf']['config']['type'];
00666 $PA['fieldTSConfig'] = $this->fObj->setTSconfig($foreign_table,array(),$foreign_selector);
00667 $config = $PA['fieldConf']['config'];
00668
00669 if(!$disabled) {
00670
00671 $opt = array();
00672 $styleAttrValue = '';
00673 foreach($selItems as $p) {
00674 if ($config['iconsInOptionTags']) {
00675 $styleAttrValue = $this->fObj->optionTagStyle($p[2]);
00676 }
00677 if (!in_array($p[1], $uniqueIds)) {
00678 $opt[]= '<option value="'.htmlspecialchars($p[1]).'"'.
00679 ' style="'.(in_array($p[1], $uniqueIds) ? '' : '').
00680 ($styleAttrValue ? ' style="'.htmlspecialchars($styleAttrValue) : '').'">'.
00681 htmlspecialchars($p[0]).'</option>';
00682 }
00683 }
00684
00685 // Put together the selector box:
00686 $selector_itemListStyle = isset($config['itemListStyle']) ? ' style="'.htmlspecialchars($config['itemListStyle']).'"' : ' style="'.$this->fObj->defaultMultipleSelectorStyle.'"';
00687 $size = intval($conf['size']);
00688 $size = $conf['autoSizeMax'] ? t3lib_div::intInRange(count($itemArray)+1,t3lib_div::intInRange($size,1),$conf['autoSizeMax']) : $size;
00689 $onChange = "return inline.importNewRecord('".$this->inlineNames['object']."[".$conf['foreign_table']."]')";
00690 $item = '
00691 <select id="'.$this->inlineNames['object'].'['.$conf['foreign_table'].']_selector"'.
00692 $this->fObj->insertDefStyle('select').
00693 ($size ? ' size="'.$size.'"' : '').
00694 ' onchange="'.htmlspecialchars($onChange).'"'.
00695 $PA['onFocus'].
00696 $selector_itemListStyle.
00697 ($conf['foreign_unique'] ? ' isunique="isunique"' : '').'>
00698 '.implode('
00699 ',$opt).'
00700 </select>';
00701
00702
00703
00704
00705
00706 $createNewRelationText = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:cm.createNewRelation',1);
00707 $item .=
00708 '<a href="#" onclick="'.htmlspecialchars($onChange).'" align="abstop">'.
00709 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/edit2.gif','width="11" height="12"').' align="absmiddle" '.t3lib_BEfunc::titleAltAttrib($createNewRelationText).' /> '.$createNewRelationText.
00710 '</a>';
00711
00712 $item = '<div style="margin-bottom: 20px;">'.$item.'</div>';
00713 }
00714
00715 return $item;
00716 }
00717
00718
00727 function renderPossibleRecordsSelectorTypeGroupDB($conf, &$PA) {
00728 $foreign_table = $conf['foreign_table'];
00729
00730 $config = $PA['fieldConf']['config'];
00731 $allowed = $config['allowed'];
00732 $objectPrefix = $this->inlineNames['object'].'['.$foreign_table.']';
00733
00734 $createNewRelationText = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:cm.createNewRelation',1);
00735 $onClick = "setFormValueOpenBrowser('db','".('|||'.$allowed.'|'.$objectPrefix.'|inline.checkUniqueElement||inline.importElement')."'); return false;";
00736 $item =
00737 '<a href="#" onclick="'.htmlspecialchars($onClick).'">'.
00738 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/insert3.gif','width="14" height="14"').' align="absmiddle" '.t3lib_BEfunc::titleAltAttrib($createNewRelationText).' /> '.$createNewRelationText.
00739 '</a>';
00740
00741 return $item;
00742 }
00743
00744
00752 function getNewRecordLink($objectPrefix, $conf = array()) {
00753 if ($conf['inline']['inlineNewButtonStyle']) $style = ' style="'.$conf['inline']['inlineNewButtonStyle'].'"';
00754
00755 $onClick = "return inline.createNewRecord('$objectPrefix')";
00756 $title = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:cm.createnew',1);
00757
00758 if ($conf['appearance']['newRecordLinkAddTitle'])
00759 $tableTitle .= ' '.$GLOBALS['LANG']->sL($GLOBALS['TCA'][$conf['foreign_table']]['ctrl']['title'],1);
00760
00761 $out = '
00762 <div class="typo3-newRecordLink">
00763 <a href="#" onClick="'.$onClick.'" class="inlineNewButton"'.$style.' title="'.$title.$tableTitle.'">'.
00764 '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/new_el.gif','width="11" height="12"').' alt="'.$title.$tableTitle.'" />'.
00765 $title.t3lib_div::fixed_lgd_cs($tableTitle, $this->fObj->titleLen).
00766 '</a>
00767 </div>';
00768 return $out;
00769 }
00770
00771
00778 function addJavaScriptSortable($objectId) {
00779 $this->fObj->additionalJS_post[] = '
00780 inline.createDragAndDropSorting("'.$objectId.'");
00781 ';
00782 }
00783
00784
00785
00786
00787
00788
00789
00790
00791
00799 function initForAJAX($method, &$arguments) {
00800
00801 if ($method == 'createNewRecord') {
00802 $this->fObj->RTEcounter = intval(array_shift($arguments));
00803 }
00804 }
00805
00806
00815 function createNewRecord($domObjectId, $foreignUid = 0) {
00816 $this->isAjaxCall = true;
00817
00818 $this->parseStructureString($domObjectId, true);
00819
00820 $current = $this->inlineStructure['unstable'];
00821
00822 $parent = $this->getStructureLevel(-1);
00823
00824 $config = $parent['config'];
00825
00826
00827 $this->fObj->pushToDynNestedStack('inline', $this->inlineNames['object']);
00828
00829
00830 if (!$foreignUid || !t3lib_div::testInt($foreignUid) || $config['foreign_selector']) {
00831 $record = $this->getNewRecord($this->inlineFirstPid, $current['table']);
00832
00833
00834 } else {
00835 $record = $this->getRecord($this->inlineFirstPid, $current['table'], $foreignUid);
00836 }
00837
00838
00839
00840
00841 if ($config['foreign_selector'] && $foreignUid) {
00842 $selConfig = $this->getPossibleRecordsSelectorConfig($config, $config['foreign_selector']);
00843
00844 $record[$config['foreign_selector']] = $selConfig['type'] != 'groupdb' ? '' : $selConfig['table'].'_';
00845 $record[$config['foreign_selector']] .= $foreignUid;
00846 }
00847
00848
00849 $objectPrefix = $this->inlineNames['object'].'['.$current['table'].']';
00850 $objectId = $objectPrefix.'['.$record['uid'].']';
00851
00852
00853 $item = $this->renderForeignRecord($parent['uid'], $record, $config);
00854 if($item === false) {
00855 $jsonArray = array(
00856 'data' => 'Access denied',
00857 'scriptCall' => array(
00858 "alert('Access denied');",
00859 )
00860 );
00861 return t3lib_div::array2json($jsonArray);
00862 }
00863
00864
00865 $item = $GLOBALS['LANG']->csConvObj->utf8_encode($item, $GLOBALS['LANG']->charSet);
00866
00867 if (!$current['uid']) {
00868 $jsonArray = array(
00869 'data' => $item,
00870 'scriptCall' => array(
00871 "inline.domAddNewRecord('bottom','".$this->inlineNames['object']."_records','$objectPrefix',json.data);",
00872 "inline.memorizeAddRecord('$objectPrefix','".$record['uid']."',null,'$foreignUid');"
00873 )
00874 );
00875
00876
00877 } else {
00878 $jsonArray = array(
00879 'data' => $item,
00880 'scriptCall' => array(
00881 "inline.domAddNewRecord('after','".$domObjectId.'_div'."','$objectPrefix',json.data);",
00882 "inline.memorizeAddRecord('$objectPrefix','".$record['uid']."','".$current['uid']."','$foreignUid');"
00883 )
00884 );
00885 }
00886
00887
00888 $jsonArray['scriptCall'][] = $this->fObj->JSbottom($this->fObj->formName, true);
00889
00890 if ($config['appearance']['useSortable'])
00891 $jsonArray['scriptCall'][] = "inline.createDragAndDropSorting('".$this->inlineNames['object']."_records');";
00892
00893 if ($this->fObj->extJSCODE)
00894 $jsonArray['scriptCall'][] = $this->fObj->extJSCODE;
00895
00896 $jsonArray['scriptCall'][] = "Element.scrollTo('".$objectId."_div');";
00897
00898 $jsonArray['scriptCall'][] = "inline.fadeOutFadeIn('".$objectId."_div');";
00899
00900
00901 $this->fObj->popFromDynNestedStack();
00902
00903
00904 return t3lib_div::array2json($jsonArray);
00905 }
00906
00907
00916 function setExpandedCollapsedState($domObjectId, $expand, $collapse) {
00917
00918 $this->parseStructureString($domObjectId, false);
00919
00920 $current = $this->inlineStructure['unstable'];
00921
00922 $top = $this->getStructureLevel(0);
00923
00924
00925 if (t3lib_div::testInt($top['uid'])) {
00926 $inlineView = unserialize($GLOBALS['BE_USER']->uc['inlineView']);
00927 $inlineViewCurrent =& $inlineView[$top['table']][$top['uid']];
00928
00929 $expandUids = t3lib_div::trimExplode(',', $expand);
00930 $collapseUids = t3lib_div::trimExplode(',', $collapse);
00931
00932
00933 foreach ($expandUids as $uid) {
00934 $inlineViewCurrent[$current['table']][] = $uid;
00935 }
00936
00937 foreach ($collapseUids as $uid) {
00938 $inlineViewCurrent[$current['table']] = $this->removeFromArray($uid, $inlineViewCurrent[$current['table']]);
00939 }
00940
00941
00942 if (is_array($inlineViewCurrent[$current['table']])) {
00943 $GLOBALS['BE_USER']->uc['inlineView'] = serialize($inlineView);
00944 $GLOBALS['BE_USER']->writeUC();
00945 }
00946 }
00947 }
00948
00949
00950
00951
00952
00953
00954
00955
00956
00967 function getRelatedRecords($table,$field,$row,&$PA,$config) {
00968 $records = array();
00969
00970
00971 $nMV_label = isset($PA['fieldTSConfig']['noMatchingValue_label']) ? $this->fObj->sL($PA['fieldTSConfig']['noMatchingValue_label']) : '[ '.$this->fObj->getLL('l_noMatchingValue').' ]';
00972
00973
00974 # $this->fObj->requiredElements[$PA['itemFormElName']] = array($minitems,$maxitems,'imgName'=>$table.'_'.$row['uid'].'_'.$field);
00975
00976
00977 $itemArray = t3lib_div::trimExplode(',',$PA['itemFormElValue'],1);
00978 foreach($itemArray as $tk => $tv) {
00979 $tvP = explode('|',$tv,2);
00980
00981 $records[] = $this->getRecord($row['pid'], $config['foreign_table'], $tvP[0]);
00982 }
00983
00984 return $records;
00985 }
00986
00987
00999 function getPossibleRecords($table,$field,$row,$conf,$checkForConfField='foreign_selector') {
01000
01001 $tcaTableCtrl = $GLOBALS['TCA'][$table]['ctrl'];
01002
01003 $foreign_table = $conf['foreign_table'];
01004 $foreign_check = $conf[$checkForConfField];
01005
01006 $foreignConfig = $this->getPossibleRecordsSelectorConfig($conf, $foreign_check);
01007 $PA = $foreignConfig['PA'];
01008 $config = $PA['fieldConf']['config'];
01009
01010 if ($foreignConfig['type'] == 'select') {
01011
01012 $selItems = $this->fObj->addSelectOptionsToItemArray($this->fObj->initItemArray($PA['fieldConf']),$PA['fieldConf'],$this->fObj->setTSconfig($table,$row),$field);
01013 if ($config['itemsProcFunc']) $selItems = $this->fObj->procItems($selItems,$PA['fieldTSConfig']['itemsProcFunc.'],$config,$table,$row,$field);
01014
01015
01016 $removeItems = t3lib_div::trimExplode(',',$PA['fieldTSConfig']['removeItems'],1);
01017 foreach($selItems as $tk => $p) {
01018
01019
01020 $languageDeny = $tcaTableCtrl['languageField'] && !strcmp($tcaTableCtrl['languageField'], $field) && !$GLOBALS['BE_USER']->checkLanguageAccess($p[1]);
01021 $authModeDeny = $config['form_type']=='select' && $config['authMode'] && !$GLOBALS['BE_USER']->checkAuthMode($table,$field,$p[1],$config['authMode']);
01022 if (in_array($p[1],$removeItems) || $languageDeny || $authModeDeny) {
01023 unset($selItems[$tk]);
01024 } elseif (isset($PA['fieldTSConfig']['altLabels.'][$p[1]])) {
01025 $selItems[$tk][0]=$this->fObj->sL($PA['fieldTSConfig']['altLabels.'][$p[1]]);
01026 }
01027
01028
01029 if ($table.'.'.$field == 'pages.doktype') {
01030 if (!($GLOBALS['BE_USER']->isAdmin() || t3lib_div::inList($GLOBALS['BE_USER']->groupData['pagetypes_select'],$p[1]))) {
01031 unset($selItems[$tk]);
01032 }
01033 }
01034 }
01035 } else {
01036 $selItems = false;
01037 }
01038
01039 return $selItems;
01040 }
01041
01050 function getUniqueIds($records, $conf=array(), $splitValue=false) {
01051 $uniqueIds = array();
01052
01053 if ($conf['foreign_unique'] && count($records)) {
01054 foreach ($records as $rec) {
01055 $value = $rec[$conf['foreign_unique']];
01056
01057 if ($splitValue) {
01058 $valueParts = t3lib_div::trimExplode('|', $value);
01059 $itemParts = explode('_', $valueParts[0]);
01060 $value = array(
01061 'uid' => array_pop($itemParts),
01062 'table' => implode('_', $itemParts)
01063 );
01064 }
01065 $uniqueIds[$rec['uid']] = $value;
01066 }
01067 }
01068
01069 return $uniqueIds;
01070 }
01071
01072
01083 function getRecord($pid, $table, $uid, $cmd='') {
01084 $trData = t3lib_div::makeInstance('t3lib_transferData');
01085 $trData->addRawData = TRUE;
01086 # $trData->defVals = $this->defVals;
01087 $trData->lockRecords=1;
01088 $trData->disableRTE = $GLOBALS['SOBE']->MOD_SETTINGS['disableRTE'];
01089
01090 $trData->fetchRecord($table, $uid, ($cmd === 'new' ? 'new' : ''));
01091 reset($trData->regTableItems_data);
01092 $rec = current($trData->regTableItems_data);
01093 $rec['uid'] = $cmd == 'new' ? uniqid('NEW') : $uid;
01094 if ($cmd=='new') $rec['pid'] = $pid;
01095
01096 return $rec;
01097 }
01098
01099
01107 function getNewRecord($pid, $table) {
01108 return $this->getRecord($pid, $table, $pid, 'new');
01109 }
01110
01111
01112
01113
01114
01115
01116
01117
01118
01129 function pushStructure($table, $uid, $field = '', $config = array()) {
01130 $this->inlineStructure['stable'][] = array(
01131 'table' => $table,
01132 'uid' => $uid,
01133 'field' => $field,
01134 'config' => $config,
01135 );
01136 $this->updateStructureNames();
01137 }
01138
01139
01145 function popStructure() {
01146 if (count($this->inlineStructure['stable'])) {
01147 $popItem = array_pop($this->inlineStructure['stable']);
01148 $this->updateStructureNames();
01149 }
01150 return $popItem;
01151 }
01152
01153
01162 function updateStructureNames() {
01163 $current = $this->getStructureLevel(-1);
01164
01165 if ($current !== false) {
01166 $lastItemName = $this->getStructureItemName($current);
01167 $this->inlineNames = array(
01168 'form' => $this->prependFormFieldNames.$lastItemName,
01169 'object' => $this->prependNaming.'['.$this->inlineFirstPid.']'.$this->getStructurePath(),
01170 );
01171
01172 } else {
01173 $this->inlineNames = array();
01174 }
01175 }
01176
01177
01184 function getStructureItemName($levelData) {
01185 if (is_array($levelData)) {
01186 $name = '['.$levelData['table'].']' .
01187 '['.$levelData['uid'].']' .
01188 (isset($levelData['field']) ? '['.$levelData['field'].']' : '');
01189 }
01190 return $name;
01191 }
01192
01193
01202 function getStructureLevel($level) {
01203 $inlineStructureCount = count($this->inlineStructure['stable']);
01204 if ($level < 0) $level = $inlineStructureCount+$level;
01205 if ($level >= 0 && $level < $inlineStructureCount)
01206 return $this->inlineStructure['stable'][$level];
01207 else
01208 return false;
01209 }
01210
01211
01219 function getStructurePath($structureDepth = -1) {
01220 $structureCount = count($this->inlineStructure['stable']);
01221 if ($structureDepth < 0 || $structureDepth > $structureCount) $structureDepth = $structureCount;
01222
01223 for ($i = 1; $i <= $structureDepth; $i++) {
01224 $current = $this->getStructureLevel(-$i);
01225 $string = $this->getStructureItemName($current).$string;
01226 }
01227
01228 return $string;
01229 }
01230
01231
01244 function parseStructureString($string, $loadConfig = false) {
01245 $unstable = array();
01246 $vector = array('table', 'uid', 'field');
01247 $pattern = '/^'.$this->prependNaming.'\[(.+?)\]\[(.+)\]$/';
01248 if (preg_match($pattern, $string, $match)) {
01249 $this->inlineFirstPid = $match[1];
01250 $parts = explode('][', $match[2]);
01251 $partsCnt = count($parts);
01252 for ($i = 0; $i < $partsCnt; $i++) {
01253 if ($i > 0 && $i % 3 == 0) {
01254
01255 if ($loadConfig) {
01256 t3lib_div::loadTCA($unstable['table']);
01257 $unstable['config'] = $GLOBALS['TCA'][$unstable['table']]['columns'][$unstable['field']]['config'];
01258
01259 $TSconfig = $this->fObj->setTSconfig(
01260 $unstable['table'],
01261 array('uid' => $unstable['uid'], 'pid' => $this->inlineFirstPid),
01262 $unstable['field']
01263 );
01264
01265 if (!$TSconfig['disabled']) {
01266 $unstable['config'] = $this->fObj->overrideFieldConf($unstable['config'], $TSconfig);
01267 }
01268 }
01269 $this->inlineStructure['stable'][] = $unstable;
01270 $unstable = array();
01271 }
01272 $unstable[$vector[$i % 3]] = $parts[$i];
01273 }
01274 $this->updateStructureNames();
01275 if (count($unstable)) $this->inlineStructure['unstable'] = $unstable;
01276 }
01277 }
01278
01279
01280
01281
01282
01283
01284
01285
01286
01293 function checkConfiguration(&$config) {
01294 $foreign_table = $config['foreign_table'];
01295
01296
01297 if (!$foreign_table || !is_array($GLOBALS['TCA'][$foreign_table])) {
01298 return false;
01299 }
01300
01301 if (!is_array($config['appearance'])) {
01302 $config['appearance'] = array();
01303 }
01304