X-Git-Url: https://git.typo3.org/Packages/TYPO3.CMS.git/blobdiff_plain/17b35e47e76f1891c1b4a4de60b7dbae4cbd11a7..c9b70962c99faab423fc8f63f1fd9645b01f85b3:/t3lib/class.t3lib_tceforms_inline.php diff --git a/t3lib/class.t3lib_tceforms_inline.php b/t3lib/class.t3lib_tceforms_inline.php index 7fd2a92..f146c2f 100644 --- a/t3lib/class.t3lib_tceforms_inline.php +++ b/t3lib/class.t3lib_tceforms_inline.php @@ -1,94 +1,35 @@ -* All rights reserved -* -* This script is part of the TYPO3 project. The TYPO3 project is -* free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* The GNU General Public License can be found at -* http://www.gnu.org/copyleft/gpl.html. -* A copy is found in the textfile GPL.txt and important notices to the license -* from the author is found in LICENSE.txt distributed with these scripts. -* -* -* This script is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* This copyright notice MUST APPEAR in all copies of the script! -***************************************************************/ -/** - * The Inline-Relational-Record-Editing (IRRE) functions as part of the TCEforms. - * - * $Id$ - * - * @author Oliver Hader - */ -/** - * [CLASS/FUNCTION INDEX of SCRIPT] - * - * + * Copyright notice * - * 88: class t3lib_TCEforms_inline - * 109: function init(&$tceForms) - * 127: function getSingleField_typeInline($table,$field,$row,&$PA) + * (c) 2006-2011 Oliver Hader + * All rights reserved * - * SECTION: Regular rendering of forms, fields, etc. - * 263: function renderForeignRecord($parentUid, $rec, $config = array()) - * 319: function renderForeignRecordHeader($parentUid, $foreign_table,$rec,$config = array()) - * 375: function renderForeignRecordHeaderControl($table,$row,$config = array()) - * 506: function renderCombinationTable(&$rec, $appendFormFieldNames, $config = array()) - * 560: function renderPossibleRecordsSelector($selItems, $conf, $uniqueIds=array()) - * 627: function addJavaScript() - * 643: function addJavaScriptSortable($objectId) + * This script is part of the TYPO3 project. The TYPO3 project is + * free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * SECTION: Handling of AJAX calls - * 665: function createNewRecord($domObjectId, $foreignUid = 0) - * 755: function getJSON($jsonArray) - * 770: function getNewRecordLink($objectPrefix, $conf = array()) + * The GNU General Public License can be found at + * http://www.gnu.org/copyleft/gpl.html. + * A copy is found in the textfile GPL.txt and important notices to the license + * from the author is found in LICENSE.txt distributed with these scripts. * - * SECTION: Get data from database and handle relations - * 807: function getRelatedRecords($table,$field,$row,&$PA,$config) - * 839: function getPossibleRecords($table,$field,$row,$conf,$checkForConfField='foreign_selector') - * 885: function getUniqueIds($records, $conf=array()) - * 905: function getRecord($pid, $table, $uid, $cmd='') - * 929: function getNewRecord($pid, $table) * - * SECTION: Structure stack for handling inline objects/levels - * 951: function pushStructure($table, $uid, $field = '', $config = array()) - * 967: function popStructure() - * 984: function updateStructureNames() - * 1000: function getStructureItemName($levelData) - * 1015: function getStructureLevel($level) - * 1032: function getStructurePath($structureDepth = -1) - * 1057: function parseStructureString($string, $loadConfig = false) + * This script is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * SECTION: Helper functions - * 1098: function checkConfiguration(&$config) - * 1123: function checkAccess($cmd, $table, $theUid) - * 1185: function compareStructureConfiguration($compare) - * 1199: function normalizeUid($string) - * 1213: function wrapFormsSection($section, $styleAttrs = array(), $tableAttrs = array()) - * 1242: function isInlineChildAndLabelField($table, $field) - * 1258: function getStructureDepth() - * 1295: function arrayCompareComplex($subjectArray, $searchArray, $type = '') - * 1349: function isAssociativeArray($object) - * 1364: function getPossibleRecordsFlat($possibleRecords) - * 1383: function skipField($table, $field, $row, $config) - * - * TOTAL FUNCTIONS: 35 - * (This index is automatically created/updated by the extension "extdeveval") + * This copyright notice MUST APPEAR in all copies of the script! + ***************************************************************/ + +/** + * The Inline-Relational-Record-Editing (IRRE) functions as part of the TCEforms. * + * @author Oliver Hader */ - - class t3lib_TCEforms_inline { const Structure_Separator = '-'; const Disposal_AttributeName = 'Disposal_AttributeName'; @@ -100,29 +41,39 @@ class t3lib_TCEforms_inline { * @var t3lib_TCEforms */ var $fObj; - var $backPath; // Reference to $fObj->backPath - - var $isAjaxCall = false; // Indicates if a field is rendered upon an AJAX call - var $inlineStructure = array(); // the structure/hierarchy where working in, e.g. cascading inline tables - var $inlineFirstPid; // the first call of an inline type appeared on this page (pid of record) - var $inlineNames = array(); // keys: form, object -> hold the name/id for each of them - var $inlineData = array(); // inline data array used for JSON output - var $inlineView = array(); // expanded/collapsed states for the current BE user - var $inlineCount = 0; // count the number of inline types used + // Reference to $fObj->backPath + var $backPath; + // Indicates if a field is rendered upon an AJAX call + var $isAjaxCall = FALSE; + // The structure/hierarchy where working in, e.g. cascading inline tables + var $inlineStructure = array(); + // The first call of an inline type appeared on this page (pid of record) + var $inlineFirstPid; + // Keys: form, object -> hold the name/id for each of them + var $inlineNames = array(); + // Inline data array used for JSON output + var $inlineData = array(); + // Expanded/collapsed states for the current BE user + var $inlineView = array(); + // Count the number of inline types used + var $inlineCount = 0; var $inlineStyles = array(); - var $prependNaming = 'data'; // how the $this->fObj->prependFormFieldNames should be set ('data' is default) - var $prependFormFieldNames; // reference to $this->fObj->prependFormFieldNames - var $prependCmdFieldNames; // reference to $this->fObj->prependCmdFieldNames - - protected $hookObjects = array(); // array containing instances of hook classes called once for IRRE objects + // How the $this->fObj->prependFormFieldNames should be set ('data' is default) + var $prependNaming = 'data'; + // Reference to $this->fObj->prependFormFieldNames + var $prependFormFieldNames; + // Reference to $this->fObj->prependCmdFieldNames + var $prependCmdFieldNames; + // Array containing instances of hook classes called once for IRRE objects + protected $hookObjects = array(); /** - * Intialize an instance of t3lib_TCEforms_inline + * Initialize an instance of t3lib_TCEforms_inline * - * @param t3lib_TCEforms $tceForms: Reference to an TCEforms instance - * @return void + * @param t3lib_TCEforms $tceForms Reference to an TCEforms instance + * @return void */ function init(&$tceForms) { $this->fObj = $tceForms; @@ -133,22 +84,21 @@ class t3lib_TCEforms_inline { $this->initHookObjects(); } - /** * Initialized the hook objects for this class. * Each hook object has to implement the interface t3lib_tceformsInlineHook. * - * @return void + * @return void */ protected function initHookObjects() { $this->hookObjects = array(); if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tceforms_inline.php']['tceformsInlineHook'])) { $tceformsInlineHook =& $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tceforms_inline.php']['tceformsInlineHook']; if (is_array($tceformsInlineHook)) { - foreach($tceformsInlineHook as $classData) { + foreach ($tceformsInlineHook as $classData) { $processObject = t3lib_div::getUserObj($classData); - if(!($processObject instanceof t3lib_tceformsInlineHook)) { + if (!($processObject instanceof t3lib_tceformsInlineHook)) { throw new UnexpectedValueException('$processObject must implement interface t3lib_tceformsInlineHook', 1202072000); } @@ -159,24 +109,25 @@ class t3lib_TCEforms_inline { } } - /** * Generation of TCEform elements of the type "inline" * This will render inline-relational-record sets. Relations. * - * @param string $table: The table name of the record - * @param string $field: The field name which this element is supposed to edit - * @param array $row: The record data array where the value(s) for the field can be found - * @param array $PA: An array with additional configuration options. - * @return string The HTML code for the TCEform field + * @param string $table The table name of the record + * @param string $field The field name which this element is supposed to edit + * @param array $row The record data array where the value(s) for the field can be found + * @param array $PA An array with additional configuration options. + * @return string The HTML code for the TCEform field */ - function getSingleField_typeInline($table,$field,$row,&$PA) { - // check the TCA configuration - if false is returned, something was wrong - if ($this->checkConfiguration($PA['fieldConf']['config']) === false) { - return false; + function getSingleField_typeInline($table, $field, $row, &$PA) { + // Check the TCA configuration - if FALSE is returned, something was wrong + if ($this->checkConfiguration($PA['fieldConf']['config']) === FALSE) { + return FALSE; } - // count the number of processed inline elements + $item = ''; + + // Count the number of processed inline elements $this->inlineCount++; // Init: @@ -187,43 +138,46 @@ class t3lib_TCEforms_inline { if (t3lib_BEfunc::isTableLocalizable($table)) { $language = intval($row[$GLOBALS['TCA'][$table]['ctrl']['languageField']]); } - $minitems = t3lib_div::intInRange($config['minitems'],0); - $maxitems = t3lib_div::intInRange($config['maxitems'],0); - if (!$maxitems) $maxitems=100000; + $minitems = t3lib_utility_Math::forceIntegerInRange($config['minitems'], 0); + $maxitems = t3lib_utility_Math::forceIntegerInRange($config['maxitems'], 0); + if (!$maxitems) { + $maxitems = 100000; + } // Register the required number of elements: - $this->fObj->requiredElements[$PA['itemFormElName']] = array($minitems,$maxitems,'imgName'=>$table.'_'.$row['uid'].'_'.$field); + $this->fObj->requiredElements[$PA['itemFormElName']] = array($minitems, $maxitems, 'imgName' => $table . '_' . $row['uid'] . '_' . $field); - // remember the page id (pid of record) where inline editing started first - // we need that pid for ajax calls, so that they would know where the action takes place on the page structure + // Remember the page id (pid of record) where inline editing started first + // We need that pid for ajax calls, so that they would know where the action takes place on the page structure if (!isset($this->inlineFirstPid)) { - // if this record is not new, try to fetch the inlineView states + // If this record is not new, try to fetch the inlineView states // @TODO: Add checking/cleaning for unused tables, records, etc. to save space in uc-field - if (t3lib_div::testInt($row['uid'])) { + if (t3lib_utility_Math::canBeInterpretedAsInteger($row['uid'])) { $inlineView = unserialize($GLOBALS['BE_USER']->uc['inlineView']); $this->inlineView = $inlineView[$table][$row['uid']]; } // If the parent is a page, use the uid(!) of the (new?) page as pid for the child records: if ($table == 'pages') { - $this->inlineFirstPid = $row['uid']; - // If pid is negative, fetch the previous record and take its pid: + $liveVersionId = t3lib_BEfunc::getLiveVersionIdOfRecord('pages', $row['uid']); + $this->inlineFirstPid = (is_null($liveVersionId) ? $row['uid'] : $liveVersionId); + // If pid is negative, fetch the previous record and take its pid: } elseif ($row['pid'] < 0) { $prevRec = t3lib_BEfunc::getRecord($table, abs($row['pid'])); $this->inlineFirstPid = $prevRec['pid']; - // Take the pid as it is: + // Take the pid as it is: } else { $this->inlineFirstPid = $row['pid']; } } - // add the current inline job to the structure stack + // Add the current inline job to the structure stack $this->pushStructure($table, $row['uid'], $field, $config); // e.g. data[][][] $nameForm = $this->inlineNames['form']; // e.g. data------- $nameObject = $this->inlineNames['object']; - // get the records related to this inline record - $relatedRecords = $this->getRelatedRecords($table,$field,$row,$PA,$config); - // set the first and last record to the config array + // Get the records related to this inline record + $relatedRecords = $this->getRelatedRecords($table, $field, $row, $PA, $config); + // Set the first and last record to the config array $relatedRecordsUids = array_keys($relatedRecords['records']); $config['inline']['first'] = reset($relatedRecordsUids); $config['inline']['last'] = end($relatedRecordsUids); @@ -234,27 +188,27 @@ class t3lib_TCEforms_inline { 'table' => $foreign_table, 'md5' => md5($nameObject), ); - $this->inlineData['config'][$nameObject. self::Structure_Separator . $foreign_table] = array( + $this->inlineData['config'][$nameObject . self::Structure_Separator . $foreign_table] = array( 'min' => $minitems, 'max' => $maxitems, 'sortable' => $config['appearance']['useSortable'], 'top' => array( 'table' => $top['table'], - 'uid' => $top['uid'], + 'uid' => $top['uid'], ), ); // Set a hint for nested IRRE and tab elements: - $this->inlineData['nested'][$nameObject] = $this->fObj->getDynNestedStack(false, $this->isAjaxCall); + $this->inlineData['nested'][$nameObject] = $this->fObj->getDynNestedStack(FALSE, $this->isAjaxCall); - // if relations are required to be unique, get the uids that have already been used on the foreign side of the relation + // 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']) { // If uniqueness *and* selector are set, they should point to the same field - so, get the configuration of one: $selConfig = $this->getPossibleRecordsSelectorConfig($config, $config['foreign_unique']); // Get the used unique ids: - $uniqueIds = $this->getUniqueIds($relatedRecords['records'], $config, $selConfig['type']=='groupdb'); - $possibleRecords = $this->getPossibleRecords($table,$field,$row,$config,'foreign_unique'); - $uniqueMax = $config['appearance']['useCombination'] || $possibleRecords === false ? -1 : count($possibleRecords); - $this->inlineData['unique'][$nameObject. self::Structure_Separator . $foreign_table] = array( + $uniqueIds = $this->getUniqueIds($relatedRecords['records'], $config, $selConfig['type'] == 'groupdb'); + $possibleRecords = $this->getPossibleRecords($table, $field, $row, $config, 'foreign_unique'); + $uniqueMax = $config['appearance']['useCombination'] || $possibleRecords === FALSE ? -1 : count($possibleRecords); + $this->inlineData['unique'][$nameObject . self::Structure_Separator . $foreign_table] = array( 'max' => $uniqueMax, 'used' => $uniqueIds, 'type' => $selConfig['type'], @@ -266,49 +220,50 @@ class t3lib_TCEforms_inline { ); } - // if it's required to select from possible child records (reusable children), add a selector box - if ($config['foreign_selector']) { - // if not already set by the foreign_unique, set the possibleRecords here and the uniqueIds to an empty array + // If it's required to select from possible child records (reusable children), add a selector box + if ($config['foreign_selector'] && $config['appearance']['showPossibleRecordsSelector'] !== FALSE) { + // If not already set by the foreign_unique, set the possibleRecords here and the uniqueIds to an empty array if (!$config['foreign_unique']) { - $possibleRecords = $this->getPossibleRecords($table,$field,$row,$config); + $possibleRecords = $this->getPossibleRecords($table, $field, $row, $config); $uniqueIds = array(); } - $selectorBox = $this->renderPossibleRecordsSelector($possibleRecords,$config,$uniqueIds); + $selectorBox = $this->renderPossibleRecordsSelector($possibleRecords, $config, $uniqueIds); $item .= $selectorBox; } - // wrap all inline fields of a record with a
(like a container) - $item .= '
'; + // Wrap all inline fields of a record with a
(like a container) + $item .= '
'; - // define how to show the "Create new record" link - if there are more than maxitems, hide it + // Define how to show the "Create new record" link - if there are more than maxitems, hide it if ($relatedRecords['count'] >= $maxitems || ($uniqueMax > 0 && $relatedRecords['count'] >= $uniqueMax)) { $config['inline']['inlineNewButtonStyle'] = 'display: none;'; } // Render the level links (create new record, localize all, synchronize): - if ($config['appearance']['levelLinksPosition']!='none') { + if ($config['appearance']['levelLinksPosition'] != 'none') { $levelLinks = $this->getLevelInteractionLink('newRecord', $nameObject . self::Structure_Separator . $foreign_table, $config); - if ($language>0) { + + if ($language > 0 && $row[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']] > 0) { // Add the "Localize all records" link before all child records: if (isset($config['appearance']['showAllLocalizationLink']) && $config['appearance']['showAllLocalizationLink']) { - $levelLinks.= $this->getLevelInteractionLink('localize', $nameObject . self::Structure_Separator . $foreign_table, $config); + $levelLinks .= $this->getLevelInteractionLink('localize', $nameObject . self::Structure_Separator . $foreign_table, $config); } // Add the "Synchronize with default language" link before all child records: if (isset($config['appearance']['showSynchronizationLink']) && $config['appearance']['showSynchronizationLink']) { - $levelLinks.= $this->getLevelInteractionLink('synchronize', $nameObject . self::Structure_Separator . $foreign_table, $config); + $levelLinks .= $this->getLevelInteractionLink('synchronize', $nameObject . self::Structure_Separator . $foreign_table, $config); } } } // Add the level links before all child records: if (in_array($config['appearance']['levelLinksPosition'], array('both', 'top'))) { - $item.= $levelLinks; + $item .= $levelLinks; } - $item .= '
'; + $item .= '
'; $relationList = array(); if (count($relatedRecords['records'])) { foreach ($relatedRecords['records'] as $rec) { - $item .= $this->renderForeignRecord($row['uid'],$rec,$config); + $item .= $this->renderForeignRecord($row['uid'], $rec, $config); if (!isset($rec['__virtual']) || !$rec['__virtual']) { $relationList[] = $rec['uid']; } @@ -318,21 +273,38 @@ class t3lib_TCEforms_inline { // Add the level links after all child records: if (in_array($config['appearance']['levelLinksPosition'], array('both', 'bottom'))) { - $item.= $levelLinks; + $item .= $levelLinks; + } + + if (is_array($config['customControls'])) { + $item .= '
'; + foreach ($config['customControls'] as $customControlConfig) { + $parameters = array( + 'table' => $table, + 'field' => $field, + 'row' => $row, + 'nameObject' => $nameObject, + 'nameForm' => $nameForm, + 'config' => $config + ); + $item .= t3lib_div::callUserFunction($customControlConfig, $parameters, $this); + } + $item .= '
'; } - // add Drag&Drop functions for sorting to TCEforms::$additionalJS_post - if (count($relationList) > 1 && $config['appearance']['useSortable']) - $this->addJavaScriptSortable($nameObject.'_records'); - // publish the uids of the child records in the given order to the browser - $item .= ''; - // close the wrap for all inline fields (container) + // Add Drag&Drop functions for sorting to TCEforms::$additionalJS_post + if (count($relationList) > 1 && $config['appearance']['useSortable']) { + $this->addJavaScriptSortable($nameObject . '_records'); + } + // Publish the uids of the child records in the given order to the browser + $item .= ''; + // Close the wrap for all inline fields (container) $item .= '
'; - // on finishing this section, remove the last item from the structure stack + // On finishing this section, remove the last item from the structure stack $this->popStructure(); - // if this was the first call to the inline type, restore the values + // If this was the first call to the inline type, restore the values if (!$this->getStructureDepth()) { unset($this->inlineFirstPid); } @@ -340,21 +312,19 @@ class t3lib_TCEforms_inline { return $item; } - /******************************************************* * * Regular rendering of forms, fields, etc. * *******************************************************/ - /** * Render the form-fields of a related (foreign) record. * - * @param string $parentUid: The uid of the parent (embedding) record (uid or NEW...) - * @param array $rec: The table record of the child/embedded table (normaly post-processed by t3lib_transferData) - * @param array $config: content of $PA['fieldConf']['config'] - * @return string The HTML code for this "foreign record" + * @param string $parentUid The uid of the parent (embedding) record (uid or NEW...) + * @param array $rec The table record of the child/embedded table (normaly post-processed by t3lib_transferData) + * @param array $config Content of $PA['fieldConf']['config'] + * @return string The HTML code for this "foreign record" */ function renderForeignRecord($parentUid, $rec, $config = array()) { $foreign_table = $config['foreign_table']; @@ -363,7 +333,7 @@ class t3lib_TCEforms_inline { // Register default localization content: $parent = $this->getStructureLevel(-1); - if (isset($parent['localizationMode']) && $parent['localizationMode']!=false) { + if (isset($parent['localizationMode']) && $parent['localizationMode'] != FALSE) { $this->fObj->registerDefaultLanguageData($foreign_table, $rec); } // Send a mapping information to the browser via JSON: @@ -371,7 +341,7 @@ class t3lib_TCEforms_inline { $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; + $isNewRecord = t3lib_utility_Math::canBeInterpretedAsInteger($rec['uid']) ? FALSE : TRUE; // Set this variable if the record is virtual and only show with header and not editable fields: $isVirtualRecord = (isset($rec['__virtual']) && $rec['__virtual']); // If there is a selector field, normalize it: @@ -380,68 +350,98 @@ class t3lib_TCEforms_inline { } if (!$this->checkAccess(($isNewRecord ? 'new' : 'edit'), $foreign_table, $rec['uid'])) { - return false; + return FALSE; } // Get the current naming scheme for DOM name/id attributes: $nameObject = $this->inlineNames['object']; - $appendFormFieldNames = '['.$foreign_table.']['.$rec['uid'].']'; + $appendFormFieldNames = '[' . $foreign_table . '][' . $rec['uid'] . ']'; $objectId = $nameObject . self::Structure_Separator . $foreign_table . self::Structure_Separator . $rec['uid']; // Put the current level also to the dynNestedStack of TCEforms: $this->fObj->pushToDynNestedStack('inline', $objectId); - $header = $this->renderForeignRecordHeader($parentUid, $foreign_table, $rec, $config, $isVirtualRecord); + $class = ''; if (!$isVirtualRecord) { - $combination = $this->renderCombinationTable($rec, $appendFormFieldNames, $config); - $fields = $this->renderMainFields($foreign_table, $rec); - $fields = $this->wrapFormsSection($fields); // Get configuration: $collapseAll = (isset($config['appearance']['collapseAll']) && $config['appearance']['collapseAll']); + $expandAll = (isset($config['appearance']['collapseAll']) && !$config['appearance']['collapseAll']); + $ajaxLoad = (isset($config['appearance']['ajaxLoad']) && !$config['appearance']['ajaxLoad']) ? FALSE : TRUE; if ($isNewRecord) { - // show this record expanded or collapsed - $isExpanded = (!$collapseAll ? 1 : 0); - // get the top parent table + // Show this record expanded or collapsed + $isExpanded = ($expandAll || (!$collapseAll ? 1 : 0)); + } else { + $isExpanded = ($config['renderFieldsOnly'] || (!$collapseAll && $this->getExpandedCollapsedState($foreign_table, $rec['uid'])) || $expandAll); + } + // Render full content ONLY IF this is a AJAX-request, a new record, the record is not collapsed or AJAX-loading is explicitly turned off + if ($isNewRecord || $isExpanded || !$ajaxLoad) { + $combination = $this->renderCombinationTable($rec, $appendFormFieldNames, $config); + + $overruleTypesArray = isset($config['foreign_types']) ? $config['foreign_types'] : array(); + $fields = $this->renderMainFields($foreign_table, $rec, $overruleTypesArray); + $fields = $this->wrapFormsSection($fields); + + // Replace returnUrl in Wizard-Code, if this is an AJAX call + $ajaxArguments = t3lib_div::_GP('ajax'); + if (isset($ajaxArguments[2]) && trim($ajaxArguments[2]) != '') { + $fields = str_replace('P[returnUrl]=%2F' . rawurlencode(TYPO3_mainDir) . 'ajax.php', 'P[returnUrl]=' . rawurlencode($ajaxArguments[2]), $fields); + } + } else { + $combination = ''; + // This string is the marker for the JS-function to check if the full content has already been loaded + $fields = ''; + } + if ($isNewRecord) { + // Get the top parent table $top = $this->getStructureLevel(0); - $ucFieldName = 'uc[inlineView]['.$top['table'].']['.$top['uid'].']'.$appendFormFieldNames; - // set additional fields for processing for saving - $fields .= ''; - $fields .= ''; + $ucFieldName = 'uc[inlineView][' . $top['table'] . '][' . $top['uid'] . ']' . $appendFormFieldNames; + // Set additional fields for processing for saving + $fields .= ''; + $fields .= ''; } else { - // show this record expanded or collapsed - $isExpanded = (!$collapseAll && $this->getExpandedCollapsedState($foreign_table, $rec['uid'])); - // set additional field for processing for saving - $fields .= ''; + // Set additional field for processing for saving + $fields .= ''; + if (!$isExpanded && !empty($GLOBALS['TCA'][$foreign_table]['ctrl']['enablecolumns']['disabled'])) { + $checked = (!empty($rec['hidden']) ? ' checked="checked"' : ''); + $fields .= ''; + $fields .= ''; + } } - - // if this record should be shown collapsed + // If this record should be shown collapsed if (!$isExpanded) { - $appearanceStyleFields = ' style="display: none;"'; + $class = 't3-form-field-container-inline-collapsed'; } } - // set the record container with data for output - $out = '
' . $header . '
'; - $out .= '
' . $fields.$combination . '
'; - // wrap the header, fields and combination part of a child record with a div container - $class = 'inlineDiv'.($this->fObj->clientInfo['BROWSER']=='msie' ? 'MSIE' : '') . ($isNewRecord ? ' inlineIsNewRecord' : ''); - $out = '
' . $out . '
'; + if ($config['renderFieldsOnly']) { + $out = $fields . $combination; + } else { + // Set the record container with data for output + $out = '
' . $fields . $combination . '
'; + $header = t3lib_iconWorks::getSpriteIcon('apps-irre-' . ($class != '' ? 'collapsed' : 'expanded')); + $header .= $this->renderForeignRecordHeader($parentUid, $foreign_table, $rec, $config, $isVirtualRecord); + $out = '
' . $header . '
' . $out; + // Wrap the header, fields and combination part of a child record with a div container + $classMSIE = ($this->fObj->clientInfo['BROWSER'] == 'msie' && $this->fObj->clientInfo['VERSION'] < 8 ? 'MSIE' : ''); + $class .= ' inlineDiv' . $classMSIE . ($isNewRecord ? ' inlineIsNewRecord' : ''); + $out = '
' . $out . '
'; + } // Remove the current level also from the dynNestedStack of TCEforms: $this->fObj->popFromDynNestedStack(); return $out; } - /** * Wrapper for TCEforms::getMainFields(). * - * @param string $table: The table name - * @param array $row: The record to be rendered - * @return string The rendered form + * @param string $table The table name + * @param array $row The record to be rendered + * @param array $overruleTypesArray Overrule TCA [types] array, e.g to overrride [showitem] configuration of a particular type + * @return string The rendered form */ - protected function renderMainFields($table, $row) { + protected function renderMainFields($table, array $row, array $overruleTypesArray = array()) { // The current render depth of t3lib_TCEforms: $depth = $this->fObj->renderDepth; // If there is some information about already rendered palettes of our parent, store this info: @@ -449,7 +449,7 @@ class t3lib_TCEforms_inline { $palettesRendered = $this->fObj->palettesRendered[$depth][$table]; } // Render the form: - $content = $this->fObj->getMainFields($table, $row, $depth); + $content = $this->fObj->getMainFields($table, $row, $depth, $overruleTypesArray); // If there was some info about rendered palettes stored, write it back for our parent: if (isset($palettesRendered)) { $this->fObj->palettesRendered[$depth][$table] = $palettesRendered; @@ -457,100 +457,122 @@ class t3lib_TCEforms_inline { return $content; } - /** * Renders the HTML header for a foreign record, such as the title, toggle-function, drag'n'drop, etc. * Later on the command-icons are inserted here. * - * @param string $parentUid: The uid of the parent (embedding) record (uid or NEW...) - * @param string $foreign_table: The foreign_table we create a header for - * @param array $rec: The current record of that foreign_table - * @param array $config: content of $PA['fieldConf']['config'] - * @param boolean $isVirtualRecord: - * @return string The HTML code of the header + * @param string $parentUid The uid of the parent (embedding) record (uid or NEW...) + * @param string $foreign_table The foreign_table we create a header for + * @param array $rec The current record of that foreign_table + * @param array $config content of $PA['fieldConf']['config'] + * @param boolean $isVirtualRecord + * @return string The HTML code of the header */ - function renderForeignRecordHeader($parentUid, $foreign_table, $rec, $config, $isVirtualRecord=false) { + function renderForeignRecordHeader($parentUid, $foreign_table, $rec, $config, $isVirtualRecord = FALSE) { // Init: $objectId = $this->inlineNames['object'] . self::Structure_Separator . $foreign_table . self::Structure_Separator . $rec['uid']; - $expandSingle = $config['appearance']['expandSingle'] ? 1 : 0; - $onClick = "return inline.expandCollapseRecord('" . htmlspecialchars($objectId) . "', $expandSingle)"; + // We need the returnUrl of the main script when loading the fields via AJAX-call (to correct wizard code, so include it as 3rd parameter) // Pre-Processing: $isOnSymmetricSide = t3lib_loadDBGroup::isOnSymmetricSide($parentUid, $config, $rec); - $hasForeignLabel = !$isOnSymmetricSide && $config['foreign_label'] ? true : false; - $hasSymmetricLabel = $isOnSymmetricSide && $config['symmetric_label'] ? true : false; + $hasForeignLabel = !$isOnSymmetricSide && $config['foreign_label'] ? TRUE : FALSE; + $hasSymmetricLabel = $isOnSymmetricSide && $config['symmetric_label'] ? TRUE : FALSE; // Get the record title/label for a record: // render using a self-defined user function if ($GLOBALS['TCA'][$foreign_table]['ctrl']['label_userFunc']) { $params = array( 'table' => $foreign_table, - 'row' => $rec, - 'title' => '', + 'row' => $rec, + 'title' => '', 'isOnSymmetricSide' => $isOnSymmetricSide, 'parent' => array( 'uid' => $parentUid, 'config' => $config, ), ); - $null = null; // callUserFunction requires a third parameter, but we don't want to give $this as reference! + // callUserFunction requires a third parameter, but we don't want to give $this as reference! + $null = NULL; t3lib_div::callUserFunction($GLOBALS['TCA'][$foreign_table]['ctrl']['label_userFunc'], $params, $null); $recTitle = $params['title']; - // render the special alternative title + // Render the special alternative title } elseif ($hasForeignLabel || $hasSymmetricLabel) { $titleCol = $hasForeignLabel ? $config['foreign_label'] : $config['symmetric_label']; $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: + $recTitle = t3lib_BEfunc::getProcessedValueExtra($foreign_table, $titleCol, $rec[$titleCol], 0, 0, FALSE); + // Render title for group/db: } else { // $recTitle could be something like: "tx_table_123|...", $valueParts = t3lib_div::trimExplode('|', $rec[$titleCol]); $itemParts = t3lib_div::revExplode('_', $valueParts[0], 2); $recTemp = t3lib_befunc::getRecordWSOL($itemParts[0], $itemParts[1]); - $recTitle = t3lib_BEfunc::getRecordTitle($itemParts[0], $recTemp, false); + $recTitle = t3lib_BEfunc::getRecordTitle($itemParts[0], $recTemp, FALSE); } $recTitle = t3lib_BEfunc::getRecordTitlePrep($recTitle); - if (!strcmp(trim($recTitle),'')) { - $recTitle = t3lib_BEfunc::getNoRecordTitle(true); + if (!strcmp(trim($recTitle), '')) { + $recTitle = t3lib_BEfunc::getNoRecordTitle(TRUE); } - // render the standard + // Render the standard } else { - $recTitle = t3lib_BEfunc::getRecordTitle($foreign_table, $rec, true); + $recTitle = t3lib_BEfunc::getRecordTitle($foreign_table, $rec, TRUE); + } + + // Renders a thumbnail for the header + if (!empty($config['appearance']['headerThumbnail'])) { + $originalRecord = t3lib_BEfunc::getRecord($foreign_table, $rec['uid']); + + if (is_array($originalRecord)) { + $fileUid = $originalRecord[$config['appearance']['headerThumbnail']]; + list($fileUid) = t3lib_div::intExplode(',', $fileUid); + + if ($fileUid) { + $fileObject = t3lib_file_Factory::getInstance()->getFileObject($fileUid); + if ($fileObject) { + $imageUrl = $fileObject->process( + t3lib_file_ProcessedFile::CONTEXT_IMAGEPREVIEW, + array('width' => 64, 'height' => 64) + )->getPublicUrl(TRUE); + + $thumbnail = '' . htmlspecialchars($recTitle) . ''; + } else { + $thumbnail = FALSE; + } + } + } } $altText = t3lib_BEfunc::getRecordIconAltText($rec, $foreign_table); - $iconImg = t3lib_iconWorks::getIconImage($foreign_table, $rec, $this->backPath, 'title="'.htmlspecialchars($altText).'" class="absmiddle"'); + $iconImg = t3lib_iconWorks::getSpriteIconForRecord($foreign_table, $rec, array('title' => htmlspecialchars($altText), 'id' => $objectId . '_icon')); $label = '' . $recTitle . ''; - if (!$isVirtualRecord) { - $iconImg = $this->wrapWithAnchor($iconImg, '#', array('onclick' => $onClick)); - $label = $this->wrapWithAnchor($label, '#', array('onclick' => $onClick, 'style' => 'display: block;')); - } $ctrl = $this->renderForeignRecordHeaderControl($parentUid, $foreign_table, $rec, $config, $isVirtualRecord); - // @TODO: Check the table wrapping and the CSS definitions $header = - '
fObj->borderStyle[2] ? ' background="'.htmlspecialchars($this->backPath.$this->fObj->borderStyle[2]).'"':''). - ($this->fObj->borderStyle[3] ? ' class="'.htmlspecialchars($this->fObj->borderStyle[3]).'"':'').'>' . - '
'.$iconImg.''.$label.''.$ctrl.'
'; + '' . + '' . + (!empty($config['appearance']['headerThumbnail']) && $thumbnail + ? '' + : '') . + '' . + '' . + '' . + '
' . $thumbnail . '' . $iconImg . '' . $label . '' . $ctrl . '
'; return $header; } - /** * Render the control-icons for a record header (create new, sorting, delete, disable/enable). * Most of the parts are copy&paste from class.db_list_extra.inc and modified for the JavaScript calls here * - * @param string $parentUid: The uid of the parent (embedding) record (uid or NEW...) - * @param string $foreign_table: The table (foreign_table) we create control-icons for - * @param array $rec: The current record of that foreign_table - * @param array $config: (modified) TCA configuration of the field - * @return string The HTML code with the control-icons + * @param string $parentUid The uid of the parent (embedding) record (uid or NEW...) + * @param string $foreign_table The table (foreign_table) we create control-icons for + * @param array $rec The current record of that foreign_table + * @param array $config (modified) TCA configuration of the field + * @return string The HTML code with the control-icons */ - function renderForeignRecordHeaderControl($parentUid, $foreign_table, $rec, $config=array(), $isVirtualRecord=false) { + function renderForeignRecordHeaderControl($parentUid, $foreign_table, $rec, $config = array(), $isVirtualRecord = FALSE) { // Initialize: $cells = array(); $isNewItem = substr($rec['uid'], 0, 3) == 'NEW'; @@ -558,9 +580,9 @@ class t3lib_TCEforms_inline { $tcaTableCtrl =& $GLOBALS['TCA'][$foreign_table]['ctrl']; $tcaTableCols =& $GLOBALS['TCA'][$foreign_table]['columns']; - $isPagesTable = $foreign_table == 'pages' ? true : false; + $isPagesTable = $foreign_table == 'pages' ? TRUE : FALSE; $isOnSymmetricSide = t3lib_loadDBGroup::isOnSymmetricSide($parentUid, $config, $rec); - $enableManualSorting = $tcaTableCtrl['sortby'] || $config['MM'] || (!$isOnSymmetricSide && $config['foreign_sortby']) || ($isOnSymmetricSide && $config['symmetric_sortby']) ? true : false; + $enableManualSorting = $tcaTableCtrl['sortby'] || $config['MM'] || (!$isOnSymmetricSide && $config['foreign_sortby']) || ($isOnSymmetricSide && $config['symmetric_sortby']) ? TRUE : FALSE; $nameObject = $this->inlineNames['object']; $nameObjectFt = $nameObject . self::Structure_Separator . $foreign_table; @@ -571,122 +593,137 @@ class t3lib_TCEforms_inline { ); // If the listed table is 'pages' we have to request the permission settings for each page: - if ($isPagesTable) { - $localCalcPerms = $GLOBALS['BE_USER']->calcPerms(t3lib_BEfunc::getRecord('pages',$rec['uid'])); + if ($isPagesTable) { + $localCalcPerms = $GLOBALS['BE_USER']->calcPerms(t3lib_BEfunc::getRecord('pages', $rec['uid'])); } // This expresses the edit permissions for this particular element: - $permsEdit = ($isPagesTable && ($localCalcPerms&2)) || (!$isPagesTable && ($calcPerms&16)); + $permsEdit = ($isPagesTable && ($localCalcPerms & 2)) || (!$isPagesTable && ($calcPerms & 16)); // Controls: Defines which controls should be shown $enabledControls = $config['appearance']['enabledControls']; // Hook: Can disable/enable single controls for specific child records: - foreach ($this->hookObjects as $hookObj) { - $hookObj->renderForeignRecordHeaderControl_preProcess($parentUid, $foreign_table, $rec, $config, $isVirtual, $enabledControls); + foreach ($this->hookObjects as $hookObj) { + $hookObj->renderForeignRecordHeaderControl_preProcess($parentUid, $foreign_table, $rec, $config, $isVirtualRecord, $enabledControls); } // Icon to visualize that a required field is nested in this inline level: - $cells['required'] = ''; + $cells['required'] = ''; if (isset($rec['__create'])) { - $cells['localize.isLocalizable'] = 'backPath,'gfx/localize_green.gif','width="16" height="16"').' title="'.$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_misc.xml:localize.isLocalizable', 1).'" alt="" />'; + $cells['localize.isLocalizable'] = t3lib_iconWorks::getSpriteIcon('actions-edit-localize-status-low', array('title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_misc.xml:localize.isLocalizable', TRUE))); } elseif (isset($rec['__remove'])) { - $cells['localize.wasRemovedInOriginal'] = 'backPath,'gfx/localize_red.gif','width="16" height="16"').' title="'.$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_misc.xml:localize.wasRemovedInOriginal', 1).'" alt="" />'; + $cells['localize.wasRemovedInOriginal'] = t3lib_iconWorks::getSpriteIcon('actions-edit-localize-status-high', array('title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_misc.xml:localize.wasRemovedInOriginal', 1))); } // "Info": (All records) if ($enabledControls['info'] && !$isNewItem) { - $cells['info']=''. - 'backPath,'gfx/zoom2.gif','width="12" height="12"').' title="'.$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.xml:showInfo',1).'" alt="" />'. - ''; + $cells['info'] = '' . + t3lib_iconWorks::getSpriteIcon('status-dialog-information', array('title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.xml:showInfo', TRUE))) . + ''; } // If the table is NOT a read-only table, then show these links: - if (!$tcaTableCtrl['readOnly'] && !$isVirtualRecord) { + if (!$tcaTableCtrl['readOnly'] && !$isVirtualRecord) { // "New record after" link (ONLY if the records in the table are sorted by a "sortby"-row or if default values can depend on previous record): - if ($enabledControls['new'] && ($enableManualSorting || $tcaTableCtrl['useColumnsForDefaultValues'])) { + if ($enabledControls['new'] && ($enableManualSorting || $tcaTableCtrl['useColumnsForDefaultValues'])) { if ( - (!$isPagesTable && ($calcPerms&16)) || // For NON-pages, must have permission to edit content on this parent page - ($isPagesTable && ($calcPerms&8)) // For pages, must have permission to create new pages here. - ) { - $onClick = "return inline.createNewRecord('".$nameObjectFt."','".$rec['uid']."')"; - $class = ' class="inlineNewButton '.$this->inlineData['config'][$nameObject]['md5'].'"'; + (!$isPagesTable && ($calcPerms & 16)) || // For NON-pages, must have permission to edit content on this parent page + ($isPagesTable && ($calcPerms & 8)) // For pages, must have permission to create new pages here. + ) { + $onClick = "return inline.createNewRecord('" . $nameObjectFt . "','" . $rec['uid'] . "')"; + $class = ' class="inlineNewButton ' . $this->inlineData['config'][$nameObject]['md5'] . '"'; if ($config['inline']['inlineNewButtonStyle']) { - $style = ' style="'.$config['inline']['inlineNewButtonStyle'].'"'; + $style = ' style="' . $config['inline']['inlineNewButtonStyle'] . '"'; } - $cells['new']=''. - '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="" />'. - ''; + $cells['new'] = '' . + t3lib_iconWorks::getSpriteIcon('actions-' . ($isPagesTable ? 'page' : 'document') . '-new', + array( + 'title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.xml:new' . ($isPagesTable ? 'Page' : 'Record'), 1) + ) + ) . + ''; } } - // Drag&Drop Sorting: Sortable handler for script.aculo.us - if ($enabledControls['dragdrop'] && $permsEdit && $enableManualSorting && $config['appearance']['useSortable']) { - $cells['dragdrop'] = '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" />'; - } // "Up/Down" links - if ($enabledControls['sort'] && $permsEdit && $enableManualSorting) { - $onClick = "return inline.changeSorting('".$nameObjectFtId."', '1')"; // Up + if ($enabledControls['sort'] && $permsEdit && $enableManualSorting) { + $onClick = "return inline.changeSorting('" . $nameObjectFtId . "', '1')"; // Up $style = $config['inline']['first'] == $rec['uid'] ? 'style="visibility: hidden;"' : ''; - $cells['sort.up']=''. - 'backPath,'gfx/button_up.gif','width="11" height="10"').' title="'.$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.xml:moveUp',1).'" alt="" />'. - ''; + $cells['sort.up'] = '' . + t3lib_iconWorks::getSpriteIcon('actions-move-up', array('title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.xml:moveUp', TRUE))) . + ''; - $onClick = "return inline.changeSorting('".$nameObjectFtId."', '-1')"; // Down + $onClick = "return inline.changeSorting('" . $nameObjectFtId . "', '-1')"; // Down $style = $config['inline']['last'] == $rec['uid'] ? 'style="visibility: hidden;"' : ''; - $cells['sort.down']=''. - 'backPath,'gfx/button_down.gif','width="11" height="10"').' title="'.$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.xml:moveDown',1).'" alt="" />'. - ''; + $cells['sort.down'] = '' . + t3lib_iconWorks::getSpriteIcon('actions-move-down', array('title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.xml:moveDown', TRUE))) . + ''; } // "Hide/Unhide" links: $hiddenField = $tcaTableCtrl['enablecolumns']['disabled']; - if ($enabledControls['hide'] && $permsEdit && $hiddenField && $tcaTableCols[$hiddenField] && (!$tcaTableCols[$hiddenField]['exclude'] || $GLOBALS['BE_USER']->check('non_exclude_fields',$foreign_table.':'.$hiddenField))) { - $onClick = "return inline.enableDisableRecord('".$nameObjectFtId."')"; - if ($rec[$hiddenField]) { - $cells['hide.unhide']=''. - '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" />'. - ''; + if ($enabledControls['hide'] && $permsEdit && $hiddenField && $tcaTableCols[$hiddenField] && (!$tcaTableCols[$hiddenField]['exclude'] || $GLOBALS['BE_USER']->check('non_exclude_fields', $foreign_table . ':' . $hiddenField))) { + $onClick = "return inline.enableDisableRecord('" . $nameObjectFtId . "')"; + if ($rec[$hiddenField]) { + $cells['hide.unhide'] = '' . + t3lib_iconWorks::getSpriteIcon( + 'actions-edit-unhide', + array( + 'title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.xml:unHide' . ($isPagesTable ? 'Page' : ''), 1), + 'id' => $nameObjectFtId . '_disabled' + ) + ) . + ''; } else { - $cells['hide.hide']=''. - '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" />'. - ''; + $cells['hide.hide'] = '' . + t3lib_iconWorks::getSpriteIcon( + 'actions-edit-hide', + array( + 'title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.xml:hide' . ($isPagesTable ? 'Page' : ''), 1), + 'id' => $nameObjectFtId . '_disabled' + ) + ) . + ''; } } // "Delete" link: - if ($enabledControls['delete'] && ($isPagesTable && $localCalcPerms&4 || !$isPagesTable && $calcPerms&16)) { - $onClick = "inline.deleteRecord('".$nameObjectFtId."');"; - $cells['delete']=''. - 'backPath,'gfx/garbage.gif','width="11" height="12"').' title="'.$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.xml:delete',1).'" alt="" />'. - ''; + if ($enabledControls['delete'] && ($isPagesTable && $localCalcPerms & 4 || !$isPagesTable && $calcPerms & 16)) { + $onClick = "inline.deleteRecord('" . $nameObjectFtId . "');"; + $cells['delete'] = '' . + t3lib_iconWorks::getSpriteIcon('actions-edit-delete', array('title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_web_list.xml:delete', TRUE))) . + ''; + } + + // Drag&Drop Sorting: Sortable handler for script.aculo.us + if ($enabledControls['dragdrop'] && $permsEdit && $enableManualSorting && $config['appearance']['useSortable']) { + $cells['dragdrop'] = t3lib_iconWorks::getSpriteIcon('actions-move-move', array('class' => 'sortableHandle', 'title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.move', TRUE))); } - // If this is a virtual record offer a minimized set of icons for user interaction: + // If this is a virtual record offer a minimized set of icons for user interaction: } elseif ($isVirtualRecord) { if ($enabledControls['localize'] && isset($rec['__create'])) { - $onClick = "inline.synchronizeLocalizeRecords('".$nameObjectFt."', ".$rec['uid'].");"; - $cells['localize'] = '' . - 'backPath,'gfx/localize_el.gif','width="16" height="16"').' title="'.$GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_misc.xml:localize', 1).'" alt="" />' . - ''; + $onClick = "inline.synchronizeLocalizeRecords('" . $nameObjectFt . "', " . $rec['uid'] . ');'; + $cells['localize'] = '' . + t3lib_iconWorks::getSpriteIcon('actions-document-localize', array('title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_misc.xml:localize', TRUE))) . + ''; } } // If the record is edit-locked by another user, we will show a little warning sign: - if ($lockInfo=t3lib_BEfunc::isRecordLocked($foreign_table,$rec['uid'])) { - $cells['locked']=''. - ''. - ''; + if ($lockInfo = t3lib_BEfunc::isRecordLocked($foreign_table, $rec['uid'])) { + $cells['locked'] = '' . + t3lib_iconWorks::getSpriteIcon('status-warning-in-use', array('title' => htmlspecialchars($lockInfo['msg']))) . + ''; } // Hook: Post-processing of single controls for specific child records: - foreach ($this->hookObjects as $hookObj) { - $hookObj->renderForeignRecordHeaderControl_postProcess($parentUid, $foreign_table, $rec, $config, $isVirtual, $cells); + foreach ($this->hookObjects as $hookObj) { + $hookObj->renderForeignRecordHeaderControl_postProcess($parentUid, $foreign_table, $rec, $config, $isVirtualRecord, $cells); } - // Compile items into a DIV-element: - return ' - -
'.implode('', $cells).'
'; + + return '' . implode('', $cells); } @@ -695,10 +732,10 @@ class t3lib_TCEforms_inline { * so two tables are combined (the intermediate table with attributes and the sub-embedded table). * -> This is a direct embedding over two levels! * - * @param array $rec: The table record of the child/embedded table (normaly post-processed by t3lib_transferData) - * @param string $appendFormFieldNames: The [][] of the parent record (the intermediate table) - * @param array $config: content of $PA['fieldConf']['config'] - * @return string A HTML string with
tag around. + * @param array $rec The table record of the child/embedded table (normaly post-processed by t3lib_transferData) + * @param string $appendFormFieldNames The [
][] of the parent record (the intermediate table) + * @param array $config content of $PA['fieldConf']['config'] + * @return string A HTML string with
tag around. */ function renderCombinationTable(&$rec, $appendFormFieldNames, $config = array()) { $foreign_table = $config['foreign_table']; @@ -709,53 +746,52 @@ class t3lib_TCEforms_inline { $comboRecord = array(); // If record does already exist, load it: - if ($rec[$foreign_selector] && t3lib_div::testInt($rec[$foreign_selector])) { + if ($rec[$foreign_selector] && t3lib_utility_Math::canBeInterpretedAsInteger($rec[$foreign_selector])) { $comboRecord = $this->getRecord( $this->inlineFirstPid, $comboConfig['foreign_table'], $rec[$foreign_selector] ); - $isNewRecord = false; - // It is a new record, create a new record virtually: + $isNewRecord = FALSE; + // It is a new record, create a new record virtually: } else { $comboRecord = $this->getNewRecord( $this->inlineFirstPid, $comboConfig['foreign_table'] ); - $isNewRecord = true; + $isNewRecord = TRUE; } - // get the TCEforms interpretation of the TCA of the child table + // Get the TCEforms interpretation of the TCA of the child table $out = $this->renderMainFields($comboConfig['foreign_table'], $comboRecord); $out = $this->wrapFormsSection($out, array(), array('class' => 'wrapperAttention')); - // if this is a new record, add a pid value to store this record and the pointer value for the intermediate table + // If this is a new record, add a pid value to store this record and the pointer value for the intermediate table if ($isNewRecord) { - $comboFormFieldName = $this->prependFormFieldNames.'['.$comboConfig['foreign_table'].']['.$comboRecord['uid'].'][pid]'; - $out .= ''; + $comboFormFieldName = $this->prependFormFieldNames . '[' . $comboConfig['foreign_table'] . '][' . $comboRecord['uid'] . '][pid]'; + $out .= ''; } - // if the foreign_selector field is also responsible for uniqueness, tell the browser the uid of the "other" side of the relation + // If the foreign_selector field is also responsible for uniqueness, tell the browser the uid of the "other" side of the relation if ($isNewRecord || $config['foreign_unique'] == $foreign_selector) { - $parentFormFieldName = $this->prependFormFieldNames.$appendFormFieldNames.'['.$foreign_selector.']'; - $out .= ''; + $parentFormFieldName = $this->prependFormFieldNames . $appendFormFieldNames . '[' . $foreign_selector . ']'; + $out .= ''; } } return $out; } - /** * 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 $uniqueIds: The uids that have already been used and should be unique - * @return string A HTML box with all possible records */ - function renderPossibleRecordsSelector($selItems, $conf, $uniqueIds=array()) { + function renderPossibleRecordsSelector($selItems, $conf, $uniqueIds = array()) { $foreign_table = $conf['foreign_table']; $foreign_selector = $conf['foreign_selector']; @@ -771,195 +807,197 @@ class t3lib_TCEforms_inline { 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 box with all possible records */ - function renderPossibleRecordsSelectorTypeSelect($selItems, $conf, &$PA, $uniqueIds=array()) { + 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 - $PA['fieldTSConfig'] = $this->fObj->setTSconfig($foreign_table,array(),$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 + $PA['fieldTSConfig'] = $this->fObj->setTSconfig($foreign_table, array(), $foreign_selector); $config = $PA['fieldConf']['config']; - if(!$disabled) { + //TODO: $disabled is not present - should be read from config? + $disabled = FALSE; + if (!$disabled) { // Create option tags: $opt = array(); $styleAttrValue = ''; - foreach($selItems as $p) { - if ($config['iconsInOptionTags']) { + foreach ($selItems as $p) { + if ($config['iconsInOptionTags']) { $styleAttrValue = $this->fObj->optionTagStyle($p[2]); } if (!in_array($p[1], $uniqueIds)) { - $opt[]= ''; + $opt[] = ''; } } // Put together the selector box: - $selector_itemListStyle = isset($config['itemListStyle']) ? ' style="'.htmlspecialchars($config['itemListStyle']).'"' : ' style="'.$this->fObj->defaultMultipleSelectorStyle.'"'; + $selector_itemListStyle = isset($config['itemListStyle']) ? ' style="' . htmlspecialchars($config['itemListStyle']) . '"' : ' style="' . $this->fObj->defaultMultipleSelectorStyle . '"'; $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']. self::Structure_Separator . $conf['foreign_table'] . "')"; + $size = $conf['autoSizeMax'] ? t3lib_utility_Math::forceIntegerInRange(count($selItems) + 1, t3lib_utility_Math::forceIntegerInRange($size, 1), $conf['autoSizeMax']) : $size; + $onChange = "return inline.importNewRecord('" . $this->inlineNames['object'] . self::Structure_Separator . $conf['foreign_table'] . "')"; $item = ' - fObj->insertDefStyle('select') . + ($size ? ' size="' . $size . '"' : '') . + ' onchange="' . htmlspecialchars($onChange) . '"' . + $PA['onFocus'] . + $selector_itemListStyle . + ($conf['foreign_unique'] ? ' isunique="isunique"' : '') . '> + ' . implode(' + ', $opt) . ' '; - // add a "Create new relation" link for adding new relations - // this is neccessary, if the size of the selector is "1" or if + // Add a "Create new relation" link for adding new relations + // This is neccessary, if the size of the selector is "1" or if // 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); + // The selector-box creates a new relation on using a onChange event (see some line above) + if (!empty($conf['appearance']['createNewRelationLinkTitle'])) { + $createNewRelationText = $GLOBALS['LANG']->sL($conf['appearance']['createNewRelationLinkTitle'], TRUE); + } else { + $createNewRelationText = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:cm.createNewRelation', 1); + } + $item .= - ''. - 'backPath,'gfx/edit2.gif','width="11" height="12"').' align="absmiddle" '.t3lib_BEfunc::titleAltAttrib($createNewRelationText).' /> '.$createNewRelationText. - ''; - // wrap the selector and add a spacer to the bottom - $item = '
'.$item.'
'; + '' . + t3lib_iconWorks::getSpriteIcon('actions-document-new', array('title' => $createNewRelationText)) . $createNewRelationText . + ''; + // Wrap the selector and add a spacer to the bottom + $item = '
' . $item . '
'; } return $item; } - /** * Generate a link that opens an element browser in a new window. * For group/db there is no way o use a "selector" like a -box. * - * @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 + * @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'] . self::Structure_Separator . $foreign_table; + $mode = 'db'; + + if (!empty($conf['appearance']['createNewRelationLinkTitle'])) { + $createNewRelationText = $GLOBALS['LANG']->sL($conf['appearance']['createNewRelationLinkTitle'], TRUE); + } else { + $createNewRelationText = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:cm.createNewRelation', 1); + } - $createNewRelationText = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:cm.createNewRelation',1); - $onClick = "setFormValueOpenBrowser('db','".('|||'.$allowed.'|'.$objectPrefix.'|inline.checkUniqueElement||inline.importElement')."'); return false;"; - $item = - ''. - 'backPath,'gfx/insert3.gif','width="14" height="14"').' align="absmiddle" '.t3lib_BEfunc::titleAltAttrib($createNewRelationText).' /> '.$createNewRelationText. + if (is_array($config['appearance'])) { + if (isset($config['appearance']['elementBrowserType'])) { + $mode = $config['appearance']['elementBrowserType']; + } + if (isset($config['appearance']['elementBrowserAllowed'])) { + $allowed = $config['appearance']['elementBrowserAllowed']; + } + } + + $browserParams = ('|||' . $allowed . '|' . $objectPrefix . '|inline.checkUniqueElement||inline.importElement'); + + $onClick = "setFormValueOpenBrowser('".$mode."', '" . $browserParams . "'); return false;"; + $item = '' . + t3lib_iconWorks::getSpriteIcon('actions-insert-record', array('title' => $createNewRelationText)) . $createNewRelationText . ''; return $item; } - /** * Creates the HTML code of a general link to be used on a level of inline children. * The possible keys for the parameter $type are 'newRecord', 'localize' and 'synchronize'. * - * @param string $type: The link type, values are 'newRecord', 'localize' and 'synchronize'. - * @param string $objectPrefix: The "path" to the child record to create (e.g. 'data-parentPageId-partenTable-parentUid-parentField-childTable]') - * @param array $conf: TCA configuration of the parent(!) field - * @return string The HTML code of the new link, wrapped in a div + * @param string $type The link type, values are 'newRecord', 'localize' and 'synchronize'. + * @param string $objectPrefix The "path" to the child record to create (e.g. 'data-parentPageId-partenTable-parentUid-parentField-childTable]') + * @param array $conf TCA configuration of the parent(!) field + * @return string The HTML code of the new link, wrapped in a div */ - protected function getLevelInteractionLink($type, $objectPrefix, $conf=array()) { + protected function getLevelInteractionLink($type, $objectPrefix, $conf = array()) { $nameObject = $this->inlineNames['object']; $attributes = array(); - switch($type) { + switch ($type) { case 'newRecord': $title = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:cm.createnew', 1); - $iconFile = 'gfx/new_el.gif'; - // $iconAddon = 'width="11" height="12"'; + $icon = 'actions-document-new'; $className = 'typo3-newRecordLink'; - $attributes['class'] = 'inlineNewButton '.$this->inlineData['config'][$nameObject]['md5']; - $attributes['onclick'] = "return inline.createNewRecord('$objectPrefix')"; + $attributes['class'] = 'inlineNewButton ' . $this->inlineData['config'][$nameObject]['md5']; + $attributes['onclick'] = "return inline.createNewRecord('" . $objectPrefix . "')"; if (isset($conf['inline']['inlineNewButtonStyle']) && $conf['inline']['inlineNewButtonStyle']) { $attributes['style'] = $conf['inline']['inlineNewButtonStyle']; } if (isset($conf['appearance']['newRecordLinkAddTitle']) && $conf['appearance']['newRecordLinkAddTitle']) { - $titleAddon = ' '.$GLOBALS['LANG']->sL($GLOBALS['TCA'][$conf['foreign_table']]['ctrl']['title'], 1); + $titleAddon = ' ' . $GLOBALS['LANG']->sL($GLOBALS['TCA'][$conf['foreign_table']]['ctrl']['title'], 1); } - break; + break; case 'localize': $title = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_misc.xml:localizeAllRecords', 1); - $iconFile = 'gfx/localize_el.gif'; + $icon = 'actions-document-localize'; $className = 'typo3-localizationLink'; - $attributes['onclick'] = "return inline.synchronizeLocalizeRecords('$objectPrefix', 'localize')"; - break; + $attributes['onclick'] = "return inline.synchronizeLocalizeRecords('" . $objectPrefix . "', 'localize')"; + break; case 'synchronize': $title = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_misc.xml:synchronizeWithOriginalLanguage', 1); - $iconFile = 'gfx/synchronize_el.gif'; + $icon = 'actions-document-synchronize'; $className = 'typo3-synchronizationLink'; - $attributes['class'] = 'inlineNewButton '.$this->inlineData['config'][$nameObject]['md5']; - $attributes['onclick'] = "return inline.synchronizeLocalizeRecords('$objectPrefix', 'synchronize')"; - break; + $attributes['class'] = 'inlineNewButton ' . $this->inlineData['config'][$nameObject]['md5']; + $attributes['onclick'] = "return inline.synchronizeLocalizeRecords('" . $objectPrefix . "', 'synchronize')"; + break; } // Create the link: - $icon = ($iconFile ? 'backPath, $iconFile, $iconAddon).' alt="'.htmlspecialchars($title.$titleAddon).'" />' : ''); - $link = $this->wrapWithAnchor($icon.$title.$titleAddon, '#', $attributes); - return ''.$link.''; - } - - - /** - * Creates a link/button to create new records - * - * @param string $objectPrefix: The "path" to the child record to create (e.g. 'data-parentPageId-partenTable-parentUid-parentField-childTable') - * @param array $conf: TCA configuration of the parent(!) field - * @return string The HTML code for the new record link - * @deprecated since TYPO3 4.2.0-beta1, this function will be removed in TYPO3 4.5. - */ - function getNewRecordLink($objectPrefix, $conf = array()) { - t3lib_div::logDeprecatedFunction(); - - return $this->getLevelInteractionLink('newRecord', $objectPrefix, $conf); + $icon = ($icon ? t3lib_iconWorks::getSpriteIcon($icon, array('title' => htmlspecialchars($title . $titleAddon))) : ''); + $link = $this->wrapWithAnchor($icon . $title . $titleAddon, '#', $attributes); + return '' . $link . ''; } /** * Add Sortable functionality using script.acolo.us "Sortable". * - * @param string $objectId: The container id of the object - elements inside will be sortable - * @return void + * @param string $objectId The container id of the object - elements inside will be sortable + * @return void */ function addJavaScriptSortable($objectId) { $this->fObj->additionalJS_post[] = ' - inline.createDragAndDropSorting("'.$objectId.'"); + inline.createDragAndDropSorting("' . $objectId . '"); '; } - /******************************************************* * * Handling of AJAX calls * *******************************************************/ - /** * General processor for AJAX requests concerning IRRE. * (called by typo3/ajax.php) * - * @param array $params: additional parameters (not used here) - * @param TYPO3AJAX $ajaxObj: the TYPO3AJAX object of this request - * @return void + * @param array $params Additional parameters (not used here) + * @param TYPO3AJAX $ajaxObj The TYPO3AJAX object of this request + * @return void */ public function processAjaxRequest($params, $ajaxObj) { + $ajaxArguments = t3lib_div::_GP('ajax'); $ajaxIdParts = explode('::', $GLOBALS['ajaxID'], 2); @@ -968,26 +1006,26 @@ class t3lib_TCEforms_inline { switch ($ajaxMethod) { case 'createNewRecord': case 'synchronizeLocalizeRecords': - $this->isAjaxCall = true; + case 'getRecordDetails': + $this->isAjaxCall = TRUE; // Construct runtime environment for Inline Relational Record Editing: $this->processAjaxRequestConstruct($ajaxArguments); // Parse the DOM identifier (string), add the levels to the structure stack (array) and load the TCA config: - $this->parseStructureString($ajaxArguments[0], true); + $this->parseStructureString($ajaxArguments[0], TRUE); // Render content: $ajaxObj->setContentFormat('jsonbody'); $ajaxObj->setContent( call_user_func_array(array(&$this, $ajaxMethod), $ajaxArguments) ); - break; + break; case 'setExpandedCollapsedState': $ajaxObj->setContentFormat('jsonbody'); call_user_func_array(array(&$this, $ajaxMethod), $ajaxArguments); - break; + break; } } } - /** * Construct runtime environment for Inline Relational Record Editing. * - creates an anoymous SC_alt_doc in $GLOBALS['SOBE'] @@ -995,59 +1033,56 @@ class t3lib_TCEforms_inline { * - sets ourself as reference to $GLOBALS['SOBE']->tceforms->inline * - sets $GLOBALS['SOBE']->tceforms->RTEcounter to the current situation on client-side * - * @param array &$ajaxArguments: The arguments to be processed by the AJAX request - * @return void + * @param array &$ajaxArguments The arguments to be processed by the AJAX request + * @return void */ protected function processAjaxRequestConstruct(&$ajaxArguments) { - global $SOBE, $BE_USER, $TYPO3_CONF_VARS; - - require_once(PATH_typo3.'template.php'); - $GLOBALS['LANG']->includeLLFile('EXT:lang/locallang_alt_doc.xml'); // Create a new anonymous object: - $SOBE = new stdClass(); - $SOBE->MOD_MENU = array( + $GLOBALS['SOBE'] = new stdClass(); + $GLOBALS['SOBE']->MOD_MENU = array( 'showPalettes' => '', 'showDescriptions' => '', 'disableRTE' => '' ); // Setting virtual document name - $SOBE->MCONF['name']='xMOD_alt_doc.php'; + $GLOBALS['SOBE']->MCONF['name'] = 'xMOD_alt_doc.php'; // CLEANSE SETTINGS - $SOBE->MOD_SETTINGS = t3lib_BEfunc::getModuleData( - $SOBE->MOD_MENU, + $GLOBALS['SOBE']->MOD_SETTINGS = t3lib_BEfunc::getModuleData( + $GLOBALS['SOBE']->MOD_MENU, t3lib_div::_GP('SET'), - $SOBE->MCONF['name'] + $GLOBALS['SOBE']->MCONF['name'] ); // Create an instance of the document template object - $SOBE->doc = t3lib_div::makeInstance('template'); - $SOBE->doc->backPath = $GLOBALS['BACK_PATH']; + $GLOBALS['SOBE']->doc = t3lib_div::makeInstance('template'); + $GLOBALS['SOBE']->doc->backPath = $GLOBALS['BACK_PATH']; // Initialize TCEforms (rendering the forms) - $SOBE->tceforms = t3lib_div::makeInstance('t3lib_TCEforms'); - $SOBE->tceforms->inline = $this; - $SOBE->tceforms->RTEcounter = intval(array_shift($ajaxArguments)); - $SOBE->tceforms->initDefaultBEMode(); - $SOBE->tceforms->palettesCollapsed = !$SOBE->MOD_SETTINGS['showPalettes']; - $SOBE->tceforms->disableRTE = $SOBE->MOD_SETTINGS['disableRTE']; - $SOBE->tceforms->enableClickMenu = TRUE; - $SOBE->tceforms->enableTabMenu = TRUE; + $GLOBALS['SOBE']->tceforms = t3lib_div::makeInstance('t3lib_TCEforms'); + $GLOBALS['SOBE']->tceforms->inline = $this; + $GLOBALS['SOBE']->tceforms->RTEcounter = intval(array_shift($ajaxArguments)); + $GLOBALS['SOBE']->tceforms->initDefaultBEMode(); + $GLOBALS['SOBE']->tceforms->palettesCollapsed = !$GLOBALS['SOBE']->MOD_SETTINGS['showPalettes']; + $GLOBALS['SOBE']->tceforms->disableRTE = $GLOBALS['SOBE']->MOD_SETTINGS['disableRTE']; + $GLOBALS['SOBE']->tceforms->enableClickMenu = TRUE; + $GLOBALS['SOBE']->tceforms->enableTabMenu = TRUE; // Clipboard is initialized: - $SOBE->tceforms->clipObj = t3lib_div::makeInstance('t3lib_clipboard'); // Start clipboard - $SOBE->tceforms->clipObj->initializeClipboard(); // Initialize - reads the clipboard content from the user session + // Start clipboard + $GLOBALS['SOBE']->tceforms->clipObj = t3lib_div::makeInstance('t3lib_clipboard'); + // Initialize - reads the clipboard content from the user session + $GLOBALS['SOBE']->tceforms->clipObj->initializeClipboard(); // Setting external variables: - if ($BE_USER->uc['edit_showFieldHelp']!='text' && $SOBE->MOD_SETTINGS['showDescriptions']) { - $SOBE->tceforms->edit_showFieldHelp = 'text'; + if ($GLOBALS['BE_USER']->uc['edit_showFieldHelp'] != 'text' && $GLOBALS['SOBE']->MOD_SETTINGS['showDescriptions']) { + $GLOBALS['SOBE']->tceforms->edit_showFieldHelp = 'text'; } } - /** * Determines and sets several script calls to a JSON array, that would have been executed if processed in non-AJAX mode. * - * @param array &$jsonArray: Reference of the array to be used for JSON - * @param array $config: The configuration of the IRRE field of the parent record - * @return void + * @param array &$jsonArray Reference of the array to be used for JSON + * @param array $config The configuration of the IRRE field of the parent record + * @return void */ protected function getCommonScriptCalls(&$jsonArray, $config) { // Add data that would have been added at the top of a regular TCEforms call: @@ -1055,10 +1090,10 @@ class t3lib_TCEforms_inline { $jsonArray['headData'] = $headTags; } // Add the JavaScript data that would have been added at the bottom of a regular TCEforms call: - $jsonArray['scriptCall'][] = $this->fObj->JSbottom($this->fObj->formName, true); + $jsonArray['scriptCall'][] = $this->fObj->JSbottom($this->fObj->formName, TRUE); // If script.aculo.us Sortable is used, update the Observer to know the record: if ($config['appearance']['useSortable']) { - $jsonArray['scriptCall'][] = "inline.createDragAndDropSorting('".$this->inlineNames['object']."_records');"; + $jsonArray['scriptCall'][] = "inline.createDragAndDropSorting('" . $this->inlineNames['object'] . "_records');"; } // if TCEforms has some JavaScript code to be executed, just do it if ($this->fObj->extJSCODE) { @@ -1066,34 +1101,15 @@ class t3lib_TCEforms_inline { } } - - /** - * Initialize environment for AJAX calls - * - * @param string $method: Name of the method to be called - * @param array $arguments: Arguments to be delivered to the method - * @return void - * @deprecated since TYPO3 4.2.0-alpha3, this function will be removed in TYPO3 4.5. - */ - function initForAJAX($method, &$arguments) { - t3lib_div::logDeprecatedFunction(); - - // Set t3lib_TCEforms::$RTEcounter to the given value: - if ($method == 'createNewRecord') { - $this->fObj->RTEcounter = intval(array_shift($arguments)); - } - } - - /** * Generates an error message that transferred as JSON for AJAX calls * - * @param string $message: The error message to be shown - * @return array The error message in a JSON array + * @param string $message The error message to be shown + * @return array The error message in a JSON array */ protected function getErrorMessageForAJAX($message) { $jsonArray = array( - 'data' => $message, + 'data' => $message, 'scriptCall' => array( 'alert("' . $message . '");' ) @@ -1101,21 +1117,20 @@ class t3lib_TCEforms_inline { return $jsonArray; } - /** * Handle AJAX calls to show a new inline-record of the given table. * Normally this method is never called from inside TYPO3. Always from outside by AJAX. * - * @param string $domObjectId: The calling object in hierarchy, that requested a new record. - * @param string $foreignUid: If set, the new record should be inserted after that one. - * @return array An array to be used for JSON + * @param string $domObjectId The calling object in hierarchy, that requested a new record. + * @param string $foreignUid If set, the new record should be inserted after that one. + * @return array An array to be used for JSON */ function createNewRecord($domObjectId, $foreignUid = 0) { - // the current table - for this table we should add/import records + // The current table - for this table we should add/import records $current = $this->inlineStructure['unstable']; - // the parent table - this table embeds the current table + // The parent table - this table embeds the current table $parent = $this->getStructureLevel(-1); - // get TCA 'config' of the parent table + // Get TCA 'config' of the parent table if (!$this->checkConfiguration($parent['config'])) { return $this->getErrorMessageForAJAX('Wrong configuration in table ' . $parent['table']); } @@ -1127,75 +1142,72 @@ class t3lib_TCEforms_inline { // Put the current level also to the dynNestedStack of TCEforms: $this->fObj->pushToDynNestedStack('inline', $this->inlineNames['object']); - // dynamically create a new record using t3lib_transferData - if (!$foreignUid || !t3lib_div::testInt($foreignUid) || $config['foreign_selector']) { + // Dynamically create a new record using t3lib_transferData + if (!$foreignUid || !t3lib_utility_Math::canBeInterpretedAsInteger($foreignUid) || $config['foreign_selector']) { $record = $this->getNewRecord($this->inlineFirstPid, $current['table']); // Set language of new child record to the language of the parent record: - if ($config['localizationMode']=='select') { + if ($config['localizationMode'] == 'select') { $parentRecord = $this->getRecord(0, $parent['table'], $parent['uid']); $parentLanguageField = $GLOBALS['TCA'][$parent['table']]['ctrl']['languageField']; $childLanguageField = $GLOBALS['TCA'][$current['table']]['ctrl']['languageField']; - if ($parentRecord[$languageField]>0) { - $record[$childLanguageField] = $parentRecord[$languageField]; + if ($parentRecord[$parentLanguageField] > 0) { + $record[$childLanguageField] = $parentRecord[$parentLanguageField]; } } - // dynamically import an existing record (this could be a call from a select box) + // Dynamically import an existing record (this could be a call from a select box) } else { $record = $this->getRecord($this->inlineFirstPid, $current['table'], $foreignUid); } - // now there is a foreign_selector, so there is a new record on the intermediate table, but + // Now there is a foreign_selector, so there is a new record on the intermediate table, but // 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) { $selConfig = $this->getPossibleRecordsSelectorConfig($config, $config['foreign_selector']); // For a selector of type group/db, prepend the tablename (_): - $record[$config['foreign_selector']] = $selConfig['type'] != 'groupdb' ? '' : $selConfig['table'].'_'; + $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 + // The HTML-object-id's prefix of the dynamically created record $objectPrefix = $this->inlineNames['object'] . self::Structure_Separator . $current['table']; $objectId = $objectPrefix . self::Structure_Separator . $record['uid']; - // render the foreign record that should passed back to browser + // Render the foreign record that should passed back to browser $item = $this->renderForeignRecord($parent['uid'], $record, $config); - if($item === false) { + if ($item === FALSE) { return $this->getErrorMessageForAJAX('Access denied'); } - // Encode TCEforms AJAX response with utf-8: - $item = $GLOBALS['LANG']->csConvObj->utf8_encode($item, $GLOBALS['LANG']->charSet); - if (!$current['uid']) { $jsonArray = array( - 'data' => $item, + 'data' => $item, 'scriptCall' => array( - "inline.domAddNewRecord('bottom','".$this->inlineNames['object']."_records','$objectPrefix',json.data);", - "inline.memorizeAddRecord('$objectPrefix','".$record['uid']."',null,'$foreignUid');" + "inline.domAddNewRecord('bottom','" . $this->inlineNames['object'] . "_records','" . $objectPrefix . "',json.data);", + "inline.memorizeAddRecord('" . $objectPrefix . "','" . $record['uid'] . "',null,'" . $foreignUid . "');" ) ); - // append the HTML data after an existing record in the container + // Append the HTML data after an existing record in the container } else { $jsonArray = array( - 'data' => $item, + 'data' => $item, 'scriptCall' => array( - "inline.domAddNewRecord('after','".$domObjectId.'_div'."','$objectPrefix',json.data);", - "inline.memorizeAddRecord('$objectPrefix','".$record['uid']."','".$current['uid']."','$foreignUid');" + "inline.domAddNewRecord('after','" . $domObjectId . '_div' . "','" . $objectPrefix. "',json.data);", + "inline.memorizeAddRecord('" . $objectPrefix . "','" . $record['uid'] . "','" . $current['uid'] . "','" . $foreignUid . "');" ) ); } $this->getCommonScriptCalls($jsonArray, $config); // Collapse all other records if requested: if (!$collapseAll && $expandSingle) { - $jsonArray['scriptCall'][] = "inline.collapseAllRecords('$objectId', '$objectPrefix', '".$record['uid']."');"; + $jsonArray['scriptCall'][] = "inline.collapseAllRecords('" . $objectId . "', '" . $objectPrefix . "', '" . $record['uid'] . "');"; } - // tell the browser to scroll to the newly created record - $jsonArray['scriptCall'][] = "Element.scrollTo('".$objectId."_div');"; - // fade out and fade in the new record in the browser view to catch the user's eye - $jsonArray['scriptCall'][] = "inline.fadeOutFadeIn('".$objectId."_div');"; + // Tell the browser to scroll to the newly created record + $jsonArray['scriptCall'][] = "Element.scrollTo('" . $objectId . "_div');"; + // Fade out and fade in the new record in the browser view to catch the user's eye + $jsonArray['scriptCall'][] = "inline.fadeOutFadeIn('" . $objectId . "_div');"; // Remove the current level also from the dynNestedStack of TCEforms: $this->fObj->popFromDynNestedStack(); @@ -1204,17 +1216,16 @@ class t3lib_TCEforms_inline { return $jsonArray; } - /** * Handle AJAX calls to localize all records of a parent, localize a single record or to synchronize with the original language parent. * - * @param string $domObjectId: The calling object in hierarchy, that requested a new record. - * @param mixed $type: Defines the type 'localize' or 'synchronize' (string) or a single uid to be localized (integer) - * @return array An array to be used for JSON + * @param string $domObjectId The calling object in hierarchy, that requested a new record. + * @param mixed $type Defines the type 'localize' or 'synchronize' (string) or a single uid to be localized (integer) + * @return array An array to be used for JSON */ protected function synchronizeLocalizeRecords($domObjectId, $type) { - $jsonArray = false; - if (t3lib_div::inList('localize,synchronize', $type) || t3lib_div::testInt($type)) { + $jsonArray = FALSE; + if (t3lib_div::inList('localize,synchronize', $type) || t3lib_utility_Math::canBeInterpretedAsInteger($type)) { // The current level: $current = $this->inlineStructure['unstable']; // The parent level: @@ -1222,11 +1233,11 @@ class t3lib_TCEforms_inline { $parentRecord = $this->getRecord(0, $parent['table'], $parent['uid']); $cmd = array(); - $cmd[$parent['table']][$parent['uid']]['inlineLocalizeSynchronize'] = $parent['field'].','.$type; + $cmd[$parent['table']][$parent['uid']]['inlineLocalizeSynchronize'] = $parent['field'] . ',' . $type; - /* @var t3lib_TCEmain */ + /** @var t3lib_TCEmain */ $tce = t3lib_div::makeInstance('t3lib_TCEmain'); - $tce->stripslashes_values = false; + $tce->stripslashes_values = FALSE; $tce->start(array(), $cmd); $tce->process_cmdmap(); $newItemList = $tce->registerDBList[$parent['table']][$parent['uid']][$parent['field']]; @@ -1238,15 +1249,75 @@ class t3lib_TCEforms_inline { return $jsonArray; } + /** + * Handle AJAX calls to dynamically load the form fields of a given record. + * (basically a copy of "createNewRecord") + * Normally this method is never called from inside TYPO3. Always from outside by AJAX. + * + * @param string $domObjectId The calling object in hierarchy, that requested a new record. + * @return array An array to be used for JSON + */ + function getRecordDetails($domObjectId) { + // The current table - for this table we should add/import records + $current = $this->inlineStructure['unstable']; + // The parent table - this table embeds the current table + $parent = $this->getStructureLevel(-1); + // Get TCA 'config' of the parent table + if (!$this->checkConfiguration($parent['config'])) { + return $this->getErrorMessageForAJAX('Wrong configuration in table ' . $parent['table']); + } + $config = $parent['config']; + // Set flag in config so that only the fields are rendered + $config['renderFieldsOnly'] = TRUE; + + $collapseAll = (isset($config['appearance']['collapseAll']) && $config['appearance']['collapseAll']); + $expandSingle = (isset($config['appearance']['expandSingle']) && $config['appearance']['expandSingle']); + + // Put the current level also to the dynNestedStack of TCEforms: + $this->fObj->pushToDynNestedStack('inline', $this->inlineNames['object']); + + $record = $this->getRecord($this->inlineFirstPid, $current['table'], $current['uid']); + + // The HTML-object-id's prefix of the dynamically created record + $objectPrefix = $this->inlineNames['object'] . self::Structure_Separator . $current['table']; + $objectId = $objectPrefix . self::Structure_Separator . $record['uid']; + + $item = $this->renderForeignRecord($parent['uid'], $record, $config); + if ($item === FALSE) { + return $this->getErrorMessageForAJAX('Access denied'); + } + + $jsonArray = array( + 'data' => $item, + 'scriptCall' => array( + 'inline.domAddRecordDetails(\'' . $domObjectId . '\',\'' . $objectPrefix . '\',' . ($expandSingle ? '1' : '0') . ',json.data);', + ) + ); + if ($config['foreign_unique']) { + $jsonArray['scriptCall'][] = 'inline.removeUsed(\'' . $objectPrefix . '\',\'' . $record['uid'] . '\');'; + } + $this->getCommonScriptCalls($jsonArray, $config); + // Collapse all other records if requested: + if (!$collapseAll && $expandSingle) { + $jsonArray['scriptCall'][] = 'inline.collapseAllRecords(\'' . $objectId . '\',\'' . $objectPrefix . '\',\'' . $record['uid'] . '\');'; + } + + // Remove the current level also from the dynNestedStack of TCEforms: + $this->fObj->popFromDynNestedStack(); + + // Return the JSON array: + return $jsonArray; + } /** * Generates a JSON array which executes the changes and thus updates the forms view. * - * @param string $oldItemList: List of related child reocrds before changes were made (old) - * @param string $newItemList: List of related child records after changes where made (new) - * @return array An array to be used for JSON + * @param string $oldItemList List of related child reocrds before changes were made (old) + * @param string $newItemList List of related child records after changes where made (new) + * @return array An array to be used for JSON */ protected function getExecuteChangesJsonArray($oldItemList, $newItemList) { + $data = ''; $parent = $this->getStructureLevel(-1); $current = $this->inlineStructure['unstable']; @@ -1258,7 +1329,7 @@ class t3lib_TCEforms_inline { // Get the name of the field pointing to the original record: $transOrigPointerField = $GLOBALS['TCA'][$current['table']]['ctrl']['transOrigPointerField']; // Get the name of the field used as foreign selector (if any): - $foreignSelector = (isset($parent['config']['foreign_selector']) && $parent['config']['foreign_selector'] ? $parent['config']['foreign_selector'] : false); + $foreignSelector = (isset($parent['config']['foreign_selector']) && $parent['config']['foreign_selector'] ? $parent['config']['foreign_selector'] : FALSE); // Convert lists to array with uids of child records: $oldItems = $this->getRelatedRecordsUidArray($oldItemList); $newItems = $this->getRelatedRecordsUidArray($newItemList); @@ -1267,92 +1338,88 @@ class t3lib_TCEforms_inline { $localizedItems = array_diff($newItems, $oldItems); // Set the items that should be removed in the forms view: foreach ($removedItems as $item) { - $jsonArrayScriptCall[] = "inline.deleteRecord('".$nameObjectForeignTable . self::Structure_Separator . $item . "', {forceDirectRemoval: true});"; + $jsonArrayScriptCall[] = "inline.deleteRecord('" . $nameObjectForeignTable . self::Structure_Separator . $item . "', {forceDirectRemoval: true});"; } // Set the items that should be added in the forms view: foreach ($localizedItems as $item) { $row = $this->getRecord($this->inlineFirstPid, $current['table'], $item); - $selectedValue = ($foreignSelector ? "'".$row[$foreignSelector]."'" : 'null'); - $data.= $this->renderForeignRecord($parent['uid'], $row, $parent['config']); - $jsonArrayScriptCall[] = "inline.memorizeAddRecord('$nameObjectForeignTable', '".$item."', null, $selectedValue);"; + $selectedValue = ($foreignSelector ? "'" . $row[$foreignSelector] . "'" : 'null'); + $data .= $this->renderForeignRecord($parent['uid'], $row, $parent['config']); + $jsonArrayScriptCall[] = "inline.memorizeAddRecord('" . $nameObjectForeignTable . "', '" . $item . "', null, " . $selectedValue . ');'; // Remove possible virtual records in the form which showed that a child records could be localized: if (isset($row[$transOrigPointerField]) && $row[$transOrigPointerField]) { $jsonArrayScriptCall[] = "inline.fadeAndRemove('" . $nameObjectForeignTable . self::Structure_Separator . $row[$transOrigPointerField] . '_div' . "');"; } } if ($data) { - $data = $GLOBALS['LANG']->csConvObj->utf8_encode($data, $GLOBALS['LANG']->charSet); $jsonArray['data'] = $data; array_unshift( $jsonArrayScriptCall, - "inline.domAddNewRecord('bottom', '".$nameObject."_records', '$nameObjectForeignTable', json.data);" + "inline.domAddNewRecord('bottom', '" . $nameObject . "_records', '" . $nameObjectForeignTable . "', json.data);" ); } return $jsonArray; } - /** * Save the expanded/collapsed state of a child record in the BE_USER->uc. * - * @param string $domObjectId: The calling object in hierarchy, that requested a new record. - * @param string $expand: Whether this record is expanded. - * @param string $collapse: Whether this record is collapsed. - * @return void + * @param string $domObjectId The calling object in hierarchy, that requested a new record. + * @param string $expand Whether this record is expanded. + * @param string $collapse Whether this record is collapsed. + * @return void */ function setExpandedCollapsedState($domObjectId, $expand, $collapse) { - // parse the DOM identifier (string), add the levels to the structure stack (array), but don't load TCA config - $this->parseStructureString($domObjectId, false); - // the current table - for this table we should add/import records + // Parse the DOM identifier (string), add the levels to the structure stack (array), but don't load TCA config + $this->parseStructureString($domObjectId, FALSE); + // The current table - for this table we should add/import records $current = $this->inlineStructure['unstable']; - // the top parent table - this table embeds the current table + // The top parent table - this table embeds the current table $top = $this->getStructureLevel(0); - // only do some action if the top record and the current record were saved before - if (t3lib_div::testInt($top['uid'])) { - $inlineView = (array)unserialize($GLOBALS['BE_USER']->uc['inlineView']); + // Only do some action if the top record and the current record were saved before + if (t3lib_utility_Math::canBeInterpretedAsInteger($top['uid'])) { + $inlineView = (array) unserialize($GLOBALS['BE_USER']->uc['inlineView']); $inlineViewCurrent =& $inlineView[$top['table']][$top['uid']]; $expandUids = t3lib_div::trimExplode(',', $expand); $collapseUids = t3lib_div::trimExplode(',', $collapse); - // set records to be expanded + // Set records to be expanded foreach ($expandUids as $uid) { $inlineViewCurrent[$current['table']][] = $uid; } - // set records to be collapsed + // Set records to be collapsed foreach ($collapseUids as $uid) { $inlineViewCurrent[$current['table']] = $this->removeFromArray($uid, $inlineViewCurrent[$current['table']]); } - // save states back to database + // Save states back to database if (is_array($inlineViewCurrent[$current['table']])) { - $inlineViewCurrent = array_unique($inlineViewCurrent); + $inlineViewCurrent[$current['table']] = array_unique($inlineViewCurrent[$current['table']]); $GLOBALS['BE_USER']->uc['inlineView'] = serialize($inlineView); $GLOBALS['BE_USER']->writeUC(); } } } - /******************************************************* * * Get data from database and handle relations * *******************************************************/ - /** * Get the related records of the embedding item, this could be 1:n, m:n. * Returns an associative array with the keys records and count. 'count' contains only real existing records on the current parent record. * - * @param string $table: The table name of the record - * @param string $field: The field name which this element is supposed to edit - * @param array $row: The record data array where the value(s) for the field can be found - * @param array $PA: An array with additional configuration options. - * @param array $config: (Redundant) content of $PA['fieldConf']['config'] (for convenience) - * @return array The records related to the parent item as associative array. + * @param string $table The table name of the record + * @param string $field The field name which this element is supposed to edit + * @param array $row The record data array where the value(s) for the field can be found + * @param array $PA An array with additional configuration options. + * @param array $config (Redundant) content of $PA['fieldConf']['config'] (for convenience) + * @return array The records related to the parent item as associative array. */ function getRelatedRecords($table, $field, $row, &$PA, $config) { $records = array(); @@ -1362,17 +1429,17 @@ class t3lib_TCEforms_inline { $localizationMode = t3lib_BEfunc::getInlineLocalizationMode($table, $config); - if ($localizationMode!=false) { + if ($localizationMode != FALSE) { $language = intval($row[$GLOBALS['TCA'][$table]['ctrl']['languageField']]); $transOrigPointer = intval($row[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']]); - if ($language>0 && $transOrigPointer) { + if ($language > 0 && $transOrigPointer) { // Localization in mode 'keep', isn't a real localization, but keeps the children of the original parent record: - if ($localizationMode=='keep') { + if ($localizationMode == 'keep') { $transOrigRec = $this->getRecord(0, $table, $transOrigPointer); $elements = $transOrigRec[$field]; $pid = $transOrigRec['pid']; - // Localization in modes 'select', 'all' or 'sync' offer a dynamic localization and synchronization with the original language record: - } elseif ($localizationMode=='select') { + // Localization in modes 'select', 'all' or 'sync' offer a dynamic localization and synchronization with the original language record: + } elseif ($localizationMode == 'select') { $transOrigRec = $this->getRecord(0, $table, $transOrigPointer); $pid = $transOrigRec['pid']; $recordsOriginal = $this->getRelatedRecordsArray($pid, $foreignTable, $transOrigRec[$field]); @@ -1397,20 +1464,19 @@ class t3lib_TCEforms_inline { return $relatedRecords; } - /** * Gets the related records of the embedding item, this could be 1:n, m:n. * - * @param integer $pid: The pid of the parent record - * @param string $table: The table name of the record - * @param string $itemList: The list of related child records - * @return array The records related to the parent item + * @param integer $pid The pid of the parent record + * @param string $table The table name of the record + * @param string $itemList The list of related child records + * @return array The records related to the parent item */ protected function getRelatedRecordsArray($pid, $table, $itemList) { $records = array(); $itemArray = $this->getRelatedRecordsUidArray($itemList); // Perform modification of the selected items array: - foreach($itemArray as $uid) { + foreach ($itemArray as $uid) { // Get the records for this uid using t3lib_transferdata: if ($record = $this->getRecord($pid, $table, $uid)) { $records[$uid] = $record; @@ -1419,36 +1485,35 @@ class t3lib_TCEforms_inline { return $records; } - /** * Gets an array with the uids of related records out of a list of items. * This list could contain more information than required. This methods just * extracts the uids. * - * @param string $itemList: The list of related child records - * @return array An array with uids + * @param string $itemList The list of related child records + * @return array An array with uids */ protected function getRelatedRecordsUidArray($itemList) { $itemArray = t3lib_div::trimExplode(',', $itemList, 1); // Perform modification of the selected items array: - foreach($itemArray as $key => &$value) { + foreach ($itemArray as $key => &$value) { $parts = explode('|', $value, 2); $value = $parts[0]; } + unset($value); return $itemArray; } - /** * Gets the difference between current localized structure and the original language structure. * If there are records which once were localized but don't exist in the original version anymore, the record row is marked with '__remove'. * If there are records which can be localized and exist only in the original version, the record row is marked with '__create' and '__virtual'. * - * @param string $table: The table name of the parent records - * @param array $options: Options defining what kind of records to display - * @param array $recordsOriginal: The uids of the child records of the original language - * @param array $recordsLocalization: The uids of the child records of the current localization - * @return array Merged array of uids of the child records of both versions + * @param string $table The table name of the parent records + * @param array $options Options defining what kind of records to display + * @param array $recordsOriginal The uids of the child records of the original language + * @param array $recordsLocalization The uids of the child records of the current localization + * @return array Merged array of uids of the child records of both versions */ protected function getLocalizationDifferences($table, array $options, array $recordsOriginal, array $recordsLocalization) { $records = array(); @@ -1456,12 +1521,12 @@ class t3lib_TCEforms_inline { // Compare original to localized version of the records: foreach ($recordsLocalization as $uid => $row) { // If the record points to a original translation which doesn't exist anymore, it could be removed: - if (isset($row[$transOrigPointerField]) && $row[$transOrigPointerField]>0) { + if (isset($row[$transOrigPointerField]) && $row[$transOrigPointerField] > 0) { $transOrigPointer = $row[$transOrigPointerField]; if (isset($recordsOriginal[$transOrigPointer])) { unset($recordsOriginal[$transOrigPointer]); } elseif ($options['showRemoved']) { - $row['__remove'] = true; + $row['__remove'] = TRUE; } } $records[$uid] = $row; @@ -1469,27 +1534,26 @@ class t3lib_TCEforms_inline { // Process the remaining records in the original unlocalized parent: if ($options['showPossible']) { foreach ($recordsOriginal as $uid => $row) { - $row['__create'] = true; - $row['__virtual'] = true; + $row['__create'] = TRUE; + $row['__virtual'] = TRUE; $records[$uid] = $row; } } return $records; } - /** * Get possible records. * Copied from TCEform and modified. * - * @param string The table name of the record - * @param string The field name which this element is supposed to edit - * @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 mixed Array of possible record items; false if type is "group/db", then everything could be "possible" + * @param string $table The table name of the record + * @param string $field The field name which this element is supposed to edit + * @param array $row The record data array where the value(s) for the field can be found + * @param array $conf An array with additional configuration options. + * @param string $checkForConfField For which field in the foreign_table the possible records should be fetched + * @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') { + function getPossibleRecords($table, $field, $row, $conf, $checkForConfField = 'foreign_selector') { // ctrl configuration from TCA: $tcaTableCtrl = $GLOBALS['TCA'][$table]['ctrl']; // Field configuration from TCA: @@ -1502,43 +1566,43 @@ class t3lib_TCEforms_inline { 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 - ); - // Possibly filter some items: - $keepItemsFunc = create_function('$value', 'return $value[1];'); - $selItems = t3lib_div::keepItemsInArray($selItems, $PA['fieldTSConfig']['keepItems'], $keepItemsFunc); - // Possibly add some items: - $selItems = $this->fObj->addItems($selItems, $PA['fieldTSConfig']['addItems.']); - if (isset($config['itemsProcFunc']) && $config['itemsProcFunc']) { - $selItems = $this->fObj->procItems($selItems, $PA['fieldTSConfig']['itemsProcFunc.'], $config, $table, $row, $field); - } + $selItems = $this->fObj->addSelectOptionsToItemArray( + $this->fObj->initItemArray($PA['fieldConf']), + $PA['fieldConf'], + $this->fObj->setTSconfig($table, $row), + $field + ); + // Possibly filter some items: + $keepItemsFunc = create_function('$value', 'return $value[1];'); + $selItems = t3lib_div::keepItemsInArray($selItems, $PA['fieldTSConfig']['keepItems'], $keepItemsFunc); + // Possibly add some items: + $selItems = $this->fObj->addItems($selItems, $PA['fieldTSConfig']['addItems.']); + if (isset($config['itemsProcFunc']) && $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) { + $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) { + $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]]); + $selItems[$tk][0] = htmlspecialchars($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 (($table === 'pages' || $table === 'pages_language_overlay') && $field === 'doktype') { + if (!($GLOBALS['BE_USER']->isAdmin() || t3lib_div::inList($GLOBALS['BE_USER']->groupData['pagetypes_select'], $p[1]))) { unset($selItems[$tk]); } } } } else { - $selItems = false; + $selItems = FALSE; } return $selItems; @@ -1547,12 +1611,12 @@ class t3lib_TCEforms_inline { /** * Gets the uids of a select/selector that should be unique an have already been used. * - * @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 + * @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(), $splitValue=false) { + function getUniqueIds($records, $conf = array(), $splitValue = FALSE) { $uniqueIds = array(); if (isset($conf['foreign_unique']) && $conf['foreign_unique'] && count($records)) { @@ -1577,57 +1641,61 @@ class t3lib_TCEforms_inline { return $uniqueIds; } - /** * Determines the corrected pid to be used for a new record. * The pid to be used can be defined by a Page TSconfig. * - * @param string $table: The table name - * @param integer $parentPid: The pid of the parent record - * @return integer The corrected pid to be used for a new record + * @param string $table The table name + * @param integer $parentPid The pid of the parent record + * @return integer The corrected pid to be used for a new record */ - protected function getNewRecordPid($table, $parentPid=null) { + protected function getNewRecordPid($table, $parentPid = NULL) { $newRecordPid = $this->inlineFirstPid; - $pageTS = t3lib_beFunc::getPagesTSconfig($parentPid, true); - if (isset($pageTS['TCAdefaults.'][$table.'.']['pid']) && t3lib_div::testInt($pageTS['TCAdefaults.'][$table.'.']['pid'])) { - $newRecordPid = $pageTS['TCAdefaults.'][$table.'.']['pid']; - } elseif (isset($parentPid) && t3lib_div::testInt($parentPid)) { + $pageTS = t3lib_beFunc::getPagesTSconfig($parentPid, TRUE); + if (isset($pageTS['TCAdefaults.'][$table . '.']['pid']) && t3lib_utility_Math::canBeInterpretedAsInteger($pageTS['TCAdefaults.'][$table . '.']['pid'])) { + $newRecordPid = $pageTS['TCAdefaults.'][$table . '.']['pid']; + } elseif (isset($parentPid) && t3lib_utility_Math::canBeInterpretedAsInteger($parentPid)) { $newRecordPid = $parentPid; } return $newRecordPid; } - /** * Get a single record row for a TCA table from the database. * t3lib_transferData is used for "upgrading" the values, especially the relations. * - * @param integer $pid: The pid of the page the record should be stored (only relevant for NEW records) - * @param string $table: The table to fetch data from (= foreign_table) - * @param string $uid: The uid of the record to fetch, or the pid if a new record should be created - * @param string $cmd: The command to perform, empty or 'new' - * @return array A record row from the database post-processed by t3lib_transferData + * @param integer $pid The pid of the page the record should be stored (only relevant for NEW records) + * @param string $table The table to fetch data from (= foreign_table) + * @param string $uid The uid of the record to fetch, or the pid if a new record should be created + * @param string $cmd The command to perform, empty or 'new' + * @return array A record row from the database post-processed by t3lib_transferData */ - function getRecord($pid, $table, $uid, $cmd='') { + function getRecord($pid, $table, $uid, $cmd = '') { + // Fetch workspace version of a record (if any): + if ($cmd !== 'new' && $GLOBALS['BE_USER']->workspace !== 0) { + $workspaceVersion = t3lib_BEfunc::getWorkspaceVersionOfRecord($GLOBALS['BE_USER']->workspace, $table, $uid, 'uid'); + if ($workspaceVersion !== FALSE) { + $uid = $workspaceVersion['uid']; + } + } + $trData = t3lib_div::makeInstance('t3lib_transferData'); $trData->addRawData = TRUE; - $trData->lockRecords=1; + $trData->lockRecords = 1; $trData->disableRTE = $GLOBALS['SOBE']->MOD_SETTINGS['disableRTE']; - // if a new record should be created + // If a new record should be created $trData->fetchRecord($table, $uid, ($cmd === 'new' ? 'new' : '')); - reset($trData->regTableItems_data); - $rec = current($trData->regTableItems_data); + $rec = reset($trData->regTableItems_data); return $rec; } - /** * Wrapper. Calls getRecord in case of a new record should be created. * - * @param integer $pid: The pid of the page the record should be stored (only relevant for NEW records) - * @param string $table: The table to fetch data from (= foreign_table) - * @return array A record row from the database post-processed by t3lib_transferData + * @param integer $pid The pid of the page the record should be stored (only relevant for NEW records) + * @param string $table The table to fetch data from (= foreign_table) + * @return array A record row from the database post-processed by t3lib_transferData */ function getNewRecord($pid, $table) { $rec = $this->getRecord($pid, $table, $pid, 'new'); @@ -1636,27 +1704,25 @@ class t3lib_TCEforms_inline { return $rec; } - /******************************************************* * * Structure stack for handling inline objects/levels * *******************************************************/ - /** * Add a new level on top of the structure stack. Other functions can access the * stack and determine, if there's possibly a endless loop. * - * @param string $table: The table name of the record - * @param string $uid: The uid of the record that embeds the inline data - * @param string $field: The field name which this element is supposed to edit - * @param array $config: The TCA-configuration of the inline field - * @return void + * @param string $table The table name of the record + * @param string $uid The uid of the record that embeds the inline data + * @param string $field The field name which this element is supposed to edit + * @param array $config The TCA-configuration of the inline field + * @return void */ function pushStructure($table, $uid, $field = '', $config = array()) { $this->inlineStructure['stable'][] = array( - 'table' => $table, + 'table' => $table, 'uid' => $uid, 'field' => $field, 'config' => $config, @@ -1665,11 +1731,10 @@ class t3lib_TCEforms_inline { $this->updateStructureNames(); } - /** * Remove the item on top of the structure stack and return it. * - * @return array The top item of the structure stack - array(
,,,) + * @return array The top item of the structure stack - array(
,,,) */ function popStructure() { if (count($this->inlineStructure['stable'])) { @@ -1679,36 +1744,34 @@ class t3lib_TCEforms_inline { return $popItem; } - /** * For common use of DOM object-ids and form field names of a several inline-level, * these names/identifiers are preprocessed and set to $this->inlineNames. * This function is automatically called if a level is pushed to or removed from the * inline structure stack. * - * @return void + * @return void */ function updateStructureNames() { $current = $this->getStructureLevel(-1); - // if there are still more inline levels available - if ($current !== false) { + // If there are still more inline levels available + if ($current !== FALSE) { $this->inlineNames = array( 'form' => $this->prependFormFieldNames . $this->getStructureItemName($current, self::Disposal_AttributeName), 'object' => $this->prependNaming . self::Structure_Separator . $this->inlineFirstPid . self::Structure_Separator . $this->getStructurePath(), ); - // if there are no more inline levels available + // If there are no more inline levels available } else { $this->inlineNames = array(); } } - /** * Create a name/id for usage in HTML output of a level of the structure stack to be used in form names. * - * @param array $levelData: Array of a level of the structure stack (containing the keys table, uid and field) - * @param string $disposal: How the structure name is used (e.g. as
or ) - * @return string The name/id of that level, to be used for HTML output + * @param array $levelData Array of a level of the structure stack (containing the keys table, uid and field) + * @param string $disposal How the structure name is used (e.g. as
or ) + * @return string The name/id of that level, to be used for HTML output */ function getStructureItemName($levelData, $disposal = self::Disposal_AttributeId) { if (is_array($levelData)) { @@ -1720,7 +1783,7 @@ class t3lib_TCEforms_inline { // Use in name attributes: if ($disposal === self::Disposal_AttributeName) { $name = '[' . implode('][', $parts) . ']'; - // Use in id attributes: + // Use in id attributes: } else { $name = implode(self::Structure_Separator, $parts); } @@ -1728,30 +1791,33 @@ class t3lib_TCEforms_inline { return $name; } - /** * Get a level from the stack and return the data. * If the $level value is negative, this function works top-down, * if the $level value is positive, this function works bottom-up. * - * @param integer $level: Which level to return - * @return array The item of the stack at the requested level + * @param integer $level Which level to return + * @return array The item of the stack at the requested level */ function getStructureLevel($level) { $inlineStructureCount = count($this->inlineStructure['stable']); - if ($level < 0) $level = $inlineStructureCount+$level; - if ($level >= 0 && $level < $inlineStructureCount) + if ($level < 0) { + $level = $inlineStructureCount + $level; + } + if ($level >= 0 && $level < $inlineStructureCount) { return $this->inlineStructure['stable'][$level]; + } else - return false; + { + return FALSE; + } } - /** * Get the identifiers of a given depth of level, from the top of the stack to the bottom. * An identifier looks like "
--". * - * @param integer $structureDepth: How much levels to output, beginning from the top of the stack + * @param integer $structureDepth How much levels to output, beginning from the top of the stack * @return string The path of identifiers */ function getStructurePath($structureDepth = -1) { @@ -1775,7 +1841,6 @@ class t3lib_TCEforms_inline { return implode(self::Structure_Separator, $structureLevels); } - /** * Convert the DOM object-id of an inline container to an array. * The object-id could look like 'data-parentPageId-tx_mmftest_company-1-employees'. @@ -1784,11 +1849,11 @@ class t3lib_TCEforms_inline { * - 'stable': Containing full qualified identifiers (table, uid and field) * - 'unstable': Containting partly filled data (e.g. only table and possibly field) * - * @param string $domObjectId: The DOM object-id - * @param boolean $loadConfig: Load the TCA configuration for that level (default: true) - * @return void + * @param string $domObjectId The DOM object-id + * @param boolean $loadConfig Load the TCA configuration for that level (default: TRUE) + * @return void */ - function parseStructureString($string, $loadConfig=true) { + function parseStructureString($string, $loadConfig = TRUE) { $unstable = array(); $vector = array('table', 'uid', 'field'); $pattern = '/^' . $this->prependNaming . self::Structure_Separator . '(.+?)' . self::Structure_Separator . '(.+)$/'; @@ -1798,7 +1863,7 @@ class t3lib_TCEforms_inline { $partsCnt = count($parts); for ($i = 0; $i < $partsCnt; $i++) { if ($i > 0 && $i % 3 == 0) { - // load the TCA configuration of the table field and store it in the stack + // Load the TCA configuration of the table field and store it in the stack if ($loadConfig) { t3lib_div::loadTCA($unstable['table']); $unstable['config'] = $GLOBALS['TCA'][$unstable['table']]['columns'][$unstable['field']]['config']; @@ -1820,43 +1885,38 @@ class t3lib_TCEforms_inline { $unstable[$vector[$i % 3]] = $parts[$i]; } $this->updateStructureNames(); - if (count($unstable)) $this->inlineStructure['unstable'] = $unstable; + if (count($unstable)) { + $this->inlineStructure['unstable'] = $unstable; + } } } - /******************************************************* * * Helper functions * *******************************************************/ - /** * Does some checks on the TCA configuration of the inline field to render. * - * @param array $config: Reference to the TCA field configuration - * @param string $table: The table name of the record - * @param string $field: The field name which this element is supposed to edit - * @param array $row: The record data array of the parent - * @return boolean If critical configuration errors were found, false is returned + * @param array $config Reference to the TCA field configuration + * @param string $table The table name of the record + * @param string $field The field name which this element is supposed to edit + * @param array $row The record data array of the parent + * @return boolean If critical configuration errors were found, FALSE is returned */ function checkConfiguration(&$config) { $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])) { - return false; + return FALSE; } // Init appearance if not set: if (!isset($config['appearance']) || !is_array($config['appearance'])) { $config['appearance'] = array(); } - // 'newRecordLinkPosition' is deprecated since TYPO3 4.2.0-beta1, this is for backward compatibility: - if (!isset($config['appearance']['levelLinksPosition']) && isset($config['appearance']['newRecordLinkPosition']) && $config['appearance']['newRecordLinkPosition']) { - t3lib_div::deprecationLog('TCA contains a deprecated definition using "newRecordLinkPosition"'); - $config['appearance']['levelLinksPosition'] = $config['appearance']['newRecordLinkPosition']; - } // Set the position/appearance of the "Create new record" link: if (isset($config['foreign_selector']) && $config['foreign_selector'] && (!isset($config['appearance']['useCombination']) || !$config['appearance']['useCombination'])) { $config['appearance']['levelLinksPosition'] = 'none'; @@ -1865,13 +1925,13 @@ class t3lib_TCEforms_inline { } // Defines which controls should be shown in header of each record: $enabledControls = array( - 'info' => true, - 'new' => true, - 'dragdrop' => true, - 'sort' => true, - 'hide' => true, - 'delete' => true, - 'localize' => true, + 'info' => TRUE, + 'new' => TRUE, + 'dragdrop' => TRUE, + 'sort' => TRUE, + 'hide' => TRUE, + 'delete' => TRUE, + 'localize' => TRUE, ); if (isset($config['appearance']['enabledControls']) && is_array($config['appearance']['enabledControls'])) { $config['appearance']['enabledControls'] = array_merge($enabledControls, $config['appearance']['enabledControls']); @@ -1879,18 +1939,17 @@ class t3lib_TCEforms_inline { $config['appearance']['enabledControls'] = $enabledControls; } - return true; + return TRUE; } - /** * Checks the page access rights (Code for access check mostly taken from alt_doc.php) * as well as the table access rights of the user. * - * @param string $cmd: The command that sould be performed ('new' or 'edit') - * @param string $table: The table to check access for - * @param string $theUid: The record uid of the table - * @return boolean Returns true is the user has access, or false if not + * @param string $cmd The command that sould be performed ('new' or 'edit') + * @param string $table The table to check access for + * @param string $theUid The record uid of the table + * @return boolean Returns TRUE is the user has access, or FALSE if not */ function checkAccess($cmd, $table, $theUid) { // Checking if the user has permissions? (Only working as a precaution, because the final permission check is always down in TCE. But it's good to notify the user on beforehand...) @@ -1900,68 +1959,73 @@ class t3lib_TCEforms_inline { // Admin users always have acces: if ($GLOBALS['BE_USER']->isAdmin()) { - return true; + return TRUE; } // If the command is to create a NEW record...: - if ($cmd=='new') { + if ($cmd == 'new') { // If the pid is numerical, check if it's possible to write to this page: - if (t3lib_div::testInt($this->inlineFirstPid)) { + if (t3lib_utility_Math::canBeInterpretedAsInteger($this->inlineFirstPid)) { $calcPRec = t3lib_BEfunc::getRecord('pages', $this->inlineFirstPid); - if(!is_array($calcPRec)) { - return false; + if (!is_array($calcPRec)) { + return FALSE; } - $CALC_PERMS = $GLOBALS['BE_USER']->calcPerms($calcPRec); // Permissions for the parent page - if ($table=='pages') { // If pages: - $hasAccess = $CALC_PERMS&8 ? 1 : 0; // Are we allowed to create new subpages? + // Permissions for the parent page + $CALC_PERMS = $GLOBALS['BE_USER']->calcPerms($calcPRec); + // If pages: + if ($table == 'pages') { + // Are we allowed to create new subpages? + $hasAccess = $CALC_PERMS & 8 ? 1 : 0; } else { - $hasAccess = $CALC_PERMS&16 ? 1 : 0; // Are we allowed to edit content on this page? + // Are we allowed to edit content on this page? + $hasAccess = $CALC_PERMS & 16 ? 1 : 0; } - // If the pid is a NEW... value, the access will be checked on creating the page: - // (if the page with the same NEW... value could be created in TCEmain, this child record can neither) + // If the pid is a NEW... value, the access will be checked on creating the page: + // (if the page with the same NEW... value could be created in TCEmain, this child record can neither) } else { $hasAccess = 1; } - } else { // Edit: - $calcPRec = t3lib_BEfunc::getRecord($table,$theUid); - t3lib_BEfunc::fixVersioningPid($table,$calcPRec); - if (is_array($calcPRec)) { - if ($table=='pages') { // If pages: + } else { // Edit: + $calcPRec = t3lib_BEfunc::getRecord($table, $theUid); + t3lib_BEfunc::fixVersioningPid($table, $calcPRec); + if (is_array($calcPRec)) { + // If pages: + if ($table == 'pages') { $CALC_PERMS = $GLOBALS['BE_USER']->calcPerms($calcPRec); - $hasAccess = $CALC_PERMS&2 ? 1 : 0; + $hasAccess = $CALC_PERMS & 2 ? 1 : 0; } else { - $CALC_PERMS = $GLOBALS['BE_USER']->calcPerms(t3lib_BEfunc::getRecord('pages',$calcPRec['pid'])); // Fetching pid-record first. - $hasAccess = $CALC_PERMS&16 ? 1 : 0; + // Fetching pid-record first. + $CALC_PERMS = $GLOBALS['BE_USER']->calcPerms(t3lib_BEfunc::getRecord('pages', $calcPRec['pid'])); + $hasAccess = $CALC_PERMS & 16 ? 1 : 0; } // Check internals regarding access: - if ($hasAccess) { + if ($hasAccess) { $hasAccess = $GLOBALS['BE_USER']->recordEditAccessInternals($table, $calcPRec); } } } - if(!$GLOBALS['BE_USER']->check('tables_modify', $table)) { + if (!$GLOBALS['BE_USER']->check('tables_modify', $table)) { $hasAccess = 0; } - if(!$hasAccess) { + if (!$hasAccess) { $deniedAccessReason = $GLOBALS['BE_USER']->errorMsg; - if($deniedAccessReason) { + if ($deniedAccessReason) { debug($deniedAccessReason); } } - return $hasAccess ? true : false; + return $hasAccess ? TRUE : FALSE; } - /** * Check the keys and values in the $compare array against the ['config'] part of the top level of the stack. * A boolean value is return depending on how the comparison was successful. * - * @param array $compare: keys and values to compare to the ['config'] part of the top level of the stack - * @return boolean Whether the comparison was successful - * @see arrayCompareComplex + * @param array $compare Keys and values to compare to the ['config'] part of the top level of the stack + * @return boolean Whether the comparison was successful + * @see arrayCompareComplex */ function compareStructureConfiguration($compare) { $level = $this->getStructureLevel(-1); @@ -1970,93 +2034,99 @@ class t3lib_TCEforms_inline { return $result; } - /** * Normalize a relation "uid" published by transferData, like "1|Company%201" * - * @param string $string: A transferData reference string, containing the uid - * @return string The normalized uid + * @param string $string A transferData reference string, containing the uid + * @return string The normalized uid */ function normalizeUid($string) { $parts = explode('|', $string); return $parts[0]; } - /** * Wrap the HTML code of a section with a table tag. * - * @param string $section: The HTML code to be wrapped - * @param array $styleAttrs: Attributes for the style argument in the table tag - * @param array $tableAttrs: Attributes for the table tag (like width, border, etc.) - * @return string The wrapped HTML code + * @param string $section The HTML code to be wrapped + * @param array $styleAttrs Attributes for the style argument in the table tag + * @param array $tableAttrs Attributes for the table tag (like width, border, etc.) + * @return string The wrapped HTML code */ function wrapFormsSection($section, $styleAttrs = array(), $tableAttrs = array()) { - if (!$styleAttrs['margin-right']) $styleAttrs['margin-right'] = $this->inlineStyles['margin-right'].'px'; + $style = ''; + $table = ''; - foreach ($styleAttrs as $key => $value) $style .= ($style?' ':'').$key.': '.htmlspecialchars($value).'; '; - if ($style) $style = ' style="'.$style.'"'; + foreach ($styleAttrs as $key => $value) { + $style .= ($style ? ' ' : '') . $key . ': ' . htmlspecialchars($value) . '; '; + } + if ($style) { + $style = ' style="' . $style . '"'; + } - if (!$tableAttrs['background'] && $this->fObj->borderStyle[2]) $tableAttrs['background'] = $this->backPath.$this->borderStyle[2]; - if (!$tableAttrs['cellspacing']) $tableAttrs['cellspacing'] = '0'; - if (!$tableAttrs['cellpadding']) $tableAttrs['cellpadding'] = '0'; - if (!$tableAttrs['border']) $tableAttrs['border'] = '0'; - if (!$tableAttrs['width']) $tableAttrs['width'] = '100%'; - if (!$tableAttrs['class'] && $this->borderStyle[3]) $tableAttrs['class'] = $this->borderStyle[3]; + if (!$tableAttrs['background'] && $this->fObj->borderStyle[2]) { + $tableAttrs['background'] = $this->backPath . $this->borderStyle[2]; + } - foreach ($tableAttrs as $key => $value) $table .= ($table?' ':'').$key.'="'.htmlspecialchars($value).'"'; + if (!$tableAttrs['class'] && $this->borderStyle[3]) { + $tableAttrs['class'] = $this->borderStyle[3]; + } - $out = '
'.$section.'
'; + foreach ($tableAttrs as $key => $value) { + $table .= ($table ? ' ' : '') . $key . '="' . htmlspecialchars($value) . '"'; + } + + $out = '' . $section . '
'; return $out; } - /** * Checks if the $table is the child of a inline type AND the $field is the label field of this table. * This function is used to dynamically update the label while editing. This has no effect on labels, * that were processed by a TCEmain-hook on saving. * - * @param string $table: The table to check - * @param string $field: The field on this table to check - * @return boolean is inline child and field is responsible for the label + * @param string $table The table to check + * @param string $field The field on this table to check + * @return boolean Is inline child and field is responsible for the label */ function isInlineChildAndLabelField($table, $field) { $level = $this->getStructureLevel(-1); - if ($level['config']['foreign_label']) + if ($level['config']['foreign_label']) { $label = $level['config']['foreign_label']; + } else + { $label = $GLOBALS['TCA'][$table]['ctrl']['label']; - return $level['config']['foreign_table'] === $table && $label == $field ? true : false; + } + return $level['config']['foreign_table'] === $table && $label == $field ? TRUE : FALSE; } - /** * Get the depth of the stable structure stack. * (count($this->inlineStructure['stable']) * - * @return integer The depth of the structure stack + * @return integer The depth of the structure stack */ function getStructureDepth() { return count($this->inlineStructure['stable']); } - /** * Handles complex comparison requests on an array. * A request could look like the following: * * $searchArray = array( - * '%AND' => array( - * 'key1' => 'value1', - * 'key2' => 'value2', - * '%OR' => array( - * 'subarray' => array( - * 'subkey' => 'subvalue' - * ), - * 'key3' => 'value3', - * 'key4' => 'value4' - * ) - * ) + * '%AND' => array( + * 'key1' => 'value1', + * 'key2' => 'value2', + * '%OR' => array( + * 'subarray' => array( + * 'subkey' => 'subvalue' + * ), + * 'key3' => 'value3', + * 'key4' => 'value4' + * ) + * ) * ); * * It is possible to use the array keys '%AND.1', '%AND.2', etc. to prevent @@ -2068,43 +2138,43 @@ class t3lib_TCEforms_inline { * It is also possible to compare parts of a sub-array (e.g. "subarray"), so this * function recurses down one level in that sub-array. * - * @param array $subjectArray: The array to search in - * @param array $searchArray: The array with keys and values to search for - * @param string $type: Use '%AND' or '%OR' for comparision - * @return boolean The result of the comparison + * @param array $subjectArray The array to search in + * @param array $searchArray The array with keys and values to search for + * @param string $type Use '%AND' or '%OR' for comparision + * @return boolean The result of the comparison */ function arrayCompareComplex($subjectArray, $searchArray, $type = '') { $localMatches = 0; $localEntries = 0; if (is_array($searchArray) && count($searchArray)) { - // if no type was passed, try to determine + // If no type was passed, try to determine if (!$type) { reset($searchArray); $type = key($searchArray); $searchArray = current($searchArray); } - // we use '%AND' and '%OR' in uppercase + // We use '%AND' and '%OR' in uppercase $type = strtoupper($type); - // split regular elements from sub elements + // Split regular elements from sub elements foreach ($searchArray as $key => $value) { $localEntries++; - // process a sub-group of OR-conditions + // Process a sub-group of OR-conditions if ($key == '%OR') { $localMatches += $this->arrayCompareComplex($subjectArray, $value, '%OR') ? 1 : 0; - // process a sub-group of AND-conditions + // Process a sub-group of AND-conditions } elseif ($key == '%AND') { $localMatches += $this->arrayCompareComplex($subjectArray, $value, '%AND') ? 1 : 0; - // a part of an associative array should be compared, so step down in the array hierarchy + // A part of an associative array should be compared, so step down in the array hierarchy } elseif (is_array($value) && $this->isAssociativeArray($searchArray)) { $localMatches += $this->arrayCompareComplex($subjectArray[$key], $value, $type) ? 1 : 0; - // it is a normal array that is only used for grouping and indexing + // It is a normal array that is only used for grouping and indexing } elseif (is_array($value)) { $localMatches += $this->arrayCompareComplex($subjectArray, $value, $type) ? 1 : 0; - // directly compare a value + // Directly compare a value } else { if (isset($subjectArray[$key]) && isset($value)) { // Boolean match: @@ -2120,84 +2190,93 @@ class t3lib_TCEforms_inline { } } - // if one or more matches are required ('OR'), return true after the first successful match - if ($type == '%OR' && $localMatches > 0) return true; - // if all matches are required ('AND') and we have no result after the first run, return false - if ($type == '%AND' && $localMatches == 0) return false; + // If one or more matches are required ('OR'), return TRUE after the first successful match + if ($type == '%OR' && $localMatches > 0) { + return TRUE; + } + // If all matches are required ('AND') and we have no result after the first run, return FALSE + if ($type == '%AND' && $localMatches == 0) { + return FALSE; + } } } - // return the result for '%AND' (if nothing was checked, true is returned) - return $localEntries == $localMatches ? true : false; + // Return the result for '%AND' (if nothing was checked, TRUE is returned) + return $localEntries == $localMatches ? TRUE : FALSE; } - /** * Checks whether an object is an associative array. * - * @param mixed $object: The object to be checked - * @return boolean Returns true, if the object is an associative array + * @param mixed $object The object to be checked + * @return boolean Returns TRUE, if the object is an associative array */ function isAssociativeArray($object) { return is_array($object) && count($object) && (array_keys($object) !== range(0, sizeof($object) - 1)) - ? true - : false; + ? TRUE + : FALSE; } - /** * Remove an element from an array. * - * @param mixed $needle: The element to be removed. - * @param array $haystack: The array the element should be removed from. - * @param mixed $strict: Search elements strictly. - * @return array The array $haystack without the $needle + * @param mixed $needle The element to be removed. + * @param array $haystack The array the element should be removed from. + * @param mixed $strict Search elements strictly. + * @return array The array $haystack without the $needle */ - function removeFromArray($needle, $haystack, $strict=null) { + function removeFromArray($needle, $haystack, $strict = NULL) { $pos = array_search($needle, $haystack, $strict); - if ($pos !== false) unset($haystack[$pos]); + if ($pos !== FALSE) { + unset($haystack[$pos]); + } return $haystack; } - /** * Makes a flat array from the $possibleRecords array. * The key of the flat array is the value of the record, * the value of the flat array is the label of the record. * - * @param array $possibleRecords: The possibleRecords array (for select fields) - * @return mixed A flat array with key=uid, value=label; if $possibleRecords isn't an array, false is returned. + * @param array $possibleRecords The possibleRecords array (for select fields) + * @return mixed A flat array with key=uid, value=label; if $possibleRecords isn't an array, FALSE is returned. */ function getPossibleRecordsFlat($possibleRecords) { - $flat = false; + $flat = FALSE; if (is_array($possibleRecords)) { $flat = array(); - foreach ($possibleRecords as $record) $flat[$record[1]] = $record[0]; + foreach ($possibleRecords as $record) { + $flat[$record[1]] = $record[0]; + } } return $flat; } - /** * 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. + * @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; - $selector = false; + $PA = FALSE; + $type = FALSE; + $table = FALSE; + $selector = 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); + + if ($PA['fieldConf'] && $conf['foreign_selector_fieldTcaOverride']) { + $PA['fieldConf'] = t3lib_div::array_merge_recursive_overrule($PA['fieldConf'], $conf['foreign_selector_fieldTcaOverride']); + } + + $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); @@ -2221,11 +2300,11 @@ class t3lib_TCEforms_inline { /** * 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 + * @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; + $type = FALSE; if ($config['type'] == 'select') { $type = 'select'; } elseif ($config['type'] == 'group' && $config['internal_type'] == 'db') { @@ -2234,19 +2313,18 @@ class t3lib_TCEforms_inline { return $type; } - /** * Check, if a field should be skipped, that was defined to be handled as foreign_field or foreign_sortby of * the parent record of the "inline"-type - if so, we have to skip this field - the rendering is done via "inline" as hidden field * - * @param string $table: The table name - * @param string $field: The field name - * @param array $row: The record row from the database - * @param array $config: TCA configuration of the field - * @return boolean Determines whether the field should be skipped. + * @param string $table The table name + * @param string $field The field name + * @param array $row The record row from the database + * @param array $config TCA configuration of the field + * @return boolean Determines whether the field should be skipped. */ function skipField($table, $field, $row, $config) { - $skipThisField = false; + $skipThisField = FALSE; if ($this->getStructureDepth()) { $searchArray = array( @@ -2257,7 +2335,7 @@ class t3lib_TCEforms_inline { 'foreign_table' => $table, '%OR' => array( '%AND' => array( - 'appearance' => array('useCombination' => true), + 'appearance' => array('useCombination' => TRUE), 'foreign_selector' => $field, ), 'MM' => $config['MM'] @@ -2274,7 +2352,7 @@ class t3lib_TCEforms_inline { ), ); - // get the parent record from structure stack + // 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: @@ -2287,55 +2365,38 @@ class t3lib_TCEforms_inline { $searchArray['%OR']['config'][0]['%AND']['%OR']['foreign_sortby'] = $field; } - $skipThisField = $this->compareStructureConfiguration($searchArray, true); + $skipThisField = $this->compareStructureConfiguration($searchArray, TRUE); } return $skipThisField; } - - /** - * Creates recursively a JSON literal from a mulidimensional associative array. - * Uses Services_JSON (http://mike.teczno.com/JSON/doc/) - * - * @param array $jsonArray: The array (or part of) to be transformed to JSON - * @return string If $level>0: part of JSON literal; if $level==0: whole JSON literal wrapped with