diff --git t3lib/class.t3lib_tceforms.php t3lib/class.t3lib_tceforms.php index dea8e6c..317b08d 100644 --- t3lib/class.t3lib_tceforms.php +++ t3lib/class.t3lib_tceforms.php @@ -171,18 +171,6 @@ - - - - - - - - - - - - /** * 'TCEforms' - Class for creating the backend editing forms. * @@ -361,6 +349,10 @@ class t3lib_TCEforms { if (!isset($GLOBALS['ajaxID']) || strpos($GLOBALS['ajaxID'], 't3lib_TCEforms_inline::')!==0) { $this->inline = t3lib_div::makeInstance('t3lib_TCEforms_inline'); } + // Create instance of t3lib_TCEforms_suggest only if this a non-Suggest-AJAX call: + if (!isset($GLOBALS['ajaxID']) || strpos($GLOBALS['ajaxID'], 't3lib_TCEforms_suggest::')!==0) { + $this->suggest = t3lib_div::makeInstance('t3lib_TCEforms_suggest'); + } // Prepare user defined objects (if any) for hooks which extend this function: $this->hookObjectsMainFields = array(); @@ -395,6 +387,7 @@ class t3lib_TCEforms { $this->titleLen = $BE_USER->uc['titleLen']; // @deprecated since TYPO3 4.1 $this->inline->init($this); + $this->suggest->init($this); } @@ -3806,6 +3799,13 @@ class t3lib_TCEforms { $sOnChange = $assignValue.';this.blur();this.selectedIndex=0;'.implode('',$fieldChangeFunc); $outArr[] = ''; break; + case 'suggest': + if (isset($PA['fieldTSConfig']['wizards.']['suggest.']['hide']) && ((bool)$PA['fieldTSConfig']['wizards.']['suggest.']['hide'] == TRUE)) { + break; + } + + $outArr[] = $this->suggest->renderSuggestSelector($PA['itemFormElName'], $table, $field, $row, $PA, $this); + break; } // Color wizard colorbox: @@ -5141,6 +5141,12 @@ class t3lib_TCEforms { '; } + // if Suggest fields were processed, add the JS functions + if ($this->suggest->suggestCount > 0) { + $GLOBALS['SOBE']->doc->loadScriptaculous(); + $this->loadJavascriptLib('../t3lib/js/jsfunc.tceforms_suggest.js'); + } + // Toggle icons: $toggleIcon_open = 'backPath,'gfx/pil2down.gif','width="12" height="7"').' hspace="2" alt="Open" title="Open" />'; $toggleIcon_close = 'backPath,'gfx/pil2right.gif','width="7" height="12"').' hspace="2" alt="Close" title="Close" />'; diff --git t3lib/config_default.php t3lib/config_default.php index 7526f33..cf26275 100644 --- t3lib/config_default.php +++ t3lib/config_default.php @@ -244,6 +244,7 @@ $TYPO3_CONF_VARS = Array( 't3lib_TCEforms_inline::createNewRecord' => 't3lib/class.t3lib_tceforms_inline.php:t3lib_TCEforms_inline->processAjaxRequest', 't3lib_TCEforms_inline::synchronizeLocalizeRecords' => 't3lib/class.t3lib_tceforms_inline.php:t3lib_TCEforms_inline->processAjaxRequest', 't3lib_TCEforms_inline::setExpandedCollapsedState' => 't3lib/class.t3lib_tceforms_inline.php:t3lib_TCEforms_inline->processAjaxRequest', + 't3lib_TCEforms_suggest::searchRecord' => 't3lib/tceforms/class.t3lib_tceforms_suggest.php:t3lib_TCEforms_suggest->processAjaxRequest', 'ShortcutMenu::getGroups' => 'typo3/classes/class.shortcutmenu.php:ShortcutMenu->getAjaxShortcutGroups', 'ShortcutMenu::saveShortcut' => 'typo3/classes/class.shortcutmenu.php:ShortcutMenu->setAjaxShortcut', 'ShortcutMenu::render' => 'typo3/classes/class.shortcutmenu.php:ShortcutMenu->renderAjax', diff --git t3lib/core_autoload.php t3lib/core_autoload.php index fd13dbe..3455e56 100644 --- t3lib/core_autoload.php +++ t3lib/core_autoload.php @@ -60,6 +60,8 @@ return array( 't3lib_tceforms' => PATH_t3lib . 'class.t3lib_tceforms.php', 't3lib_tceforms_fe' => PATH_t3lib . 'class.t3lib_tceforms_fe.php', 't3lib_tceforms_inline' => PATH_t3lib . 'class.t3lib_tceforms_inline.php', + 't3lib_tceforms_suggest' => PATH_t3lib . 'tceforms/class.t3lib_tceforms_suggest.php', + 't3lib_tceforms_suggest_defaultreceiver' => PATH_t3lib . 'tceforms/class.t3lib_tceforms_suggest_defaultreceiver.php', 't3lib_tcemain' => PATH_t3lib . 'class.t3lib_tcemain.php', 't3lib_timetrack' => PATH_t3lib . 'class.t3lib_timetrack.php', 't3lib_transferdata' => PATH_t3lib . 'class.t3lib_transferdata.php', diff --git t3lib/js/jsfunc.tceforms_suggest.js t3lib/js/jsfunc.tceforms_suggest.js new file mode 100644 index 0000000..22e8dcf --- /dev/null +++ t3lib/js/jsfunc.tceforms_suggest.js @@ -0,0 +1,104 @@ +/*************************************************************** +* AJAX selectors for TCEforms +* +* $Id:$ +* +* Copyright notice +* +* (c) 2007-2009 Andreas Wolf +* 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. +* +* 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! +***************************************************************/ + +/** + * Class for JS handling of suggest fields in TCEforms. + * + * @author Andreas Wolf + * @author Benni Mack + */ +if (!TCEForms) { + var TCEForms = {}; +} + +TCEForms.Suggest = Class.create({ + objectId: '', + suggestField: '', + suggestResultList: '', + minimumCharacters: 2, + defaultValue: '', + + /** + * Wrapper for script.aculo.us' Autocompleter functionality: Assigns a new autocompletion object to + * the input field of a given Suggest selector. + * + * @param string objectId The ID of the object to assign the completer to + * @param string table The table of the record which is currently edited + * @param string field The field which is currently edited + * @param integer uid The uid of the record which is currently edited + * @param integer pid The pid of the record which is currently edited + * @param integer minimumCharacters the minimum characaters that is need to trigger the initial search + */ + initialize: function(objectId, table, field, uid, pid, minimumCharacters) { + this.objectId = objectId; + this.suggestField = objectId + 'Suggest'; + this.suggestResultList = objectId + 'SuggestChoices'; + + new Ajax.Autocompleter(this.suggestField, this.suggestResultList, top.TS.PATH_typo3 + 'ajax.php', { + paramName: 'value', + minChars: (minimumCharacters ? minimumCharacters : this.minimumCharacters), + updateElement: this.addElementToList.bind(this), + parameters: 'ajaxID=t3lib_TCEforms_suggest::searchRecord&table=' + table + '&field=' + field + '&formfield=' + objectId + '&uid=' + uid + '&pid=' + pid + } + ); + + $(this.suggestField).observe('focus', this.checkDefaultValue.bind(this)); + $(this.suggestField).observe('keydown', this.checkDefaultValue.bind(this)); + }, + + /** + * check for default value of the input field and set it to empty once somebody wants to type something in + */ + checkDefaultValue: function() { + if ($(this.suggestField).value == this.defaultValue) { + $(this.suggestField).value = ''; + } + }, + + /** + * Adds an element to the list of items in a group selector. + * + * @param object item The item to add to the list (usually an li element) + * @return void + */ + addElementToList: function(item) { + if (item.className.indexOf('noresults') == -1) { + var arr = item.id.split('-'); + ins_table = arr[0]; + ins_uid = arr[1]; + rec_table = arr[2]; + rec_uid = arr[3]; + rec_field = arr[4]; + + var formEl = 'data[' + rec_table + '][' + rec_uid + '][' + rec_field + ']'; + setFormValueFromBrowseWin(formEl, ins_table + '_' + ins_uid, item.firstChild.textContent); + TBE_EDITOR.fieldChanged(rec_table, rec_uid, rec_field, formEl); + + $(this.suggestField).value = this.defaultValue; + } + } +}); \ No newline at end of file diff --git t3lib/tceforms/class.t3lib_tceforms_suggest.php t3lib/tceforms/class.t3lib_tceforms_suggest.php new file mode 100644 index 0000000..24cbe9f --- /dev/null +++ t3lib/tceforms/class.t3lib_tceforms_suggest.php @@ -0,0 +1,219 @@ + +* 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! +***************************************************************/ +/** + * TCEforms wizard for rendering an AJAX selector for records + * + * $Id:$ + * + * @author Andreas Wolf + * @author Benjamin Mack + */ + +class t3lib_TCEforms_Suggest { + // count the number of ajax selectors used + public $suggestCount = 0; + public $cssClass = 'typo3-TCEforms-suggest'; + + + /** + * Initialize an instance of t3lib_TCEforms_suggest + * + * @param t3lib_TCEforms $tceForms Reference to an TCEforms instance + * @return void + */ + public function init(&$tceForms) { + $this->TCEformsObj =& $tceForms; + $this->backPath =& $tceForms->backPath; + } + + /** + * Renders an ajax-enabled text field. Also adds required JS + * + * @param string $fieldname The fieldname in the form + * @param string $table The table we render this selector for + * @param string $field The field we render this selector for + * @param array $row The row which is currently edited + * @param array $config The TSconfig of the field + * @param boolean $hideByDefault Whether or not to hide the selector by default + * @return string The HTML code for the selector + */ + public function renderSuggestSelector($fieldname, $table, $field, array $row, array $config, $hideByDefault) { + $this->suggestCount++; + + $position = $config['fieldTSConfig']['suggest.']['position']; + if (!$position) { + $position = 'right'; + } + + $containerCssClass = $this->cssClass . ' ' . $this->cssClass . '-position-' . $position; + $suggestId = 'suggest-' . $table . '-' . $field . '-' . $row['uid']; + + $selector = ' +
+ + +
'; + + // replace "-" with ucwords for the JS object name + $jsObj = str_replace(' ', '', ucwords(str_replace('-', ' ', t3lib_div::strtolower($suggestId)))); + $this->TCEformsObj->additionalJS_post[] = ' + var ' . $jsObj . ' = new TCEForms.Suggest("' . $fieldname . '", "' . $table . '", "' . $field . '", "' . $row['uid'] . '", ' . $row['pid'] . ', ' . (intval($config['fieldTSConfig']['suggest.']['minimumCharacters']) > 0 ? intval($config['fieldTSConfig']['suggest.']['minimumCharacters']) : 2) . '); + ' . $jsObj . '.defaultValue = "' . t3lib_div::slashJS($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:labels.findRecord')) . '"; + '; + + return $selector; + } + + /** + * Ajax handler for the "suggest" feature in TCEforms + * compiles together the different results from + * + * @param string $search The string to search for in the database + * @param string $table The table which is currently edited + * @param string $field The field which is currently edited + * @param integer $uid The uid of the record which is currently edited (may be NEWxxxxxx) + * @param integer $pid The pid of the record which is currently edited (always numeric + * @param string $formfield The field which is edited + * @return void + */ + public function processAjaxRequest($params, &$ajaxObj) { + + // get parameters from $_GET/$_POST + $search = t3lib_div::_GP('value'); + $table = t3lib_div::_GP('table'); + $field = t3lib_div::_GP('field'); + $uid = t3lib_div::_GP('uid'); + $pageId = t3lib_div::_GP('pid'); + $formfield = t3lib_div::_GP('formfield'); + + t3lib_div::loadTCA($table); + + // If the $uid is numeric, we have an already existing element, so get the + // TSconfig of the page itself or the element container (for non-page elements) + // otherwise it's a new element, so use given id of parent page (i.e., don't modify it here) + if (is_numeric($uid)) { + if ($table == 'pages') { + $pageId = $uid; + } else { + $row = t3lib_BEfunc::getRecord($table, $uid); + $pageId = $row['pid']; + } + } + + $TSconfig = t3lib_BEfunc::getPagesTSconfig($pageId); + $wizardConfig = $GLOBALS['TCA'][$table]['columns'][$field]['config']['wizards']['suggest']['config']; + $queryTables = t3lib_div::trimExplode(',', $GLOBALS['TCA'][$table]['columns'][$field]['config']['allowed']); + $resultRows = array(); + + // fetch the records for each query table. A query table is a table from which records are allowed to + // be added to the TCEForm selector, originally fetched from the "allowed" config option in the TCA + foreach ($queryTables as $queryTable) { + t3lib_div::loadTCA($queryTable); + + // if the table does not exist, skip it + if (!is_array($GLOBALS['TCA'][$queryTable]) || !count($GLOBALS['TCA'][$queryTable])) { + continue; + } + + $config = (array)$wizardConfig['default']; + if (is_array($wizardConfig[$queryTable])) { + $config = t3lib_div::array_merge_recursive_overrule($config, $wizardConfig[$queryTable]); + } + + // merge the configurations of different "levels" to get the working configuration for this table and + // field (i.e., go from the most general to the most special configuration) + if (is_array($TSconfig['TCEFORM.']['default.']['suggest.'])) { + $config = t3lib_div::array_merge_recursive_overrule($config, $TSconfig['TCEFORM.']['default.']['suggest.']); + } + if (is_array($TSconfig['TCEFORM.'][$queryTable.'.']['suggest.'])) { + $config = t3lib_div::array_merge_recursive_overrule($config, $TSconfig['TCEFORM.'][$queryTable.'.']['suggest.']); + } + + // use $table instead of $queryTable here because we overlay a config + // for the input-field here, not for the queried table + if (is_array($TSconfig['TCEFORM.'][$table.'.'][$field.'.']['suggest.']['default.'])) { + $config = t3lib_div::array_merge_recursive_overrule($config, $TSconfig['TCEFORM.'][$table.'.'][$field.'.']['suggest.']['default.']); + } + if (is_array($TSconfig['TCEFORM.'][$table.'.'][$field.'.']['suggest.'][$queryTable.'.'])) { + $config = t3lib_div::array_merge_recursive_overrule($config, $TSconfig['TCEFORM.'][$table.'.'][$field.'.']['suggest.'][$queryTable.'.']); + } + + // instantiate the class that should fetch the records for this $queryTable + $receiverClassName = $config['receiverClass']; + if (!class_exists($receiverClassName)) { + $receiverClassName = 't3lib_TCEforms_Suggest_DefaultReceiver'; + } + $receiverObj = t3lib_div::makeInstance($receiverClassName, $queryTable, $config); + + $params = array('value' => $search); + $rows = $receiverObj->queryTable($params, $this); + + if (!$rows) { + continue; + } + $resultRows = t3lib_div::array_merge($resultRows, $rows); + unset($rows); + } + + $listItems = array(); + if (count($resultRows) > 0) { + // traverse all found records and sort them + $rowsSort = array(); + foreach ($resultRows as $key => $row) { + $rowsSort[$key] = $row['text']; + } + asort($rowsSort); + $rowsSort = array_keys($rowsSort); + + // Limit the number of items in the result list + $maxItems = $config['maxItemsInResultList'] ? $config['maxItemsInResultList'] : 10; + $maxItems = min(count($resultRows), $maxItems); + + // put together the selector entry + for ($i = 0; $i < $maxItems; $i++) { + $row = $resultRows[$rowsSort[$i]]; + $rowId = $row['table'] . '-' . $row['uid'] . '-' . $table . '-' . $uid . '-' . $field; + $listItems[] = '' . $row['text'] . ''; + } + } + + if (count($listItems) > 0) { + $list = implode('', $listItems); + } else { + $list = '
  • ' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:labels.noRecordFound') . '
  • '; + } + + $list = '
      ' . $list . '
    '; + $ajaxObj->addContent(0, $list); + } +} + + +if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['classes/t3lib/tceforms/class.t3lib_tceforms_suggest.php']) { + include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['classes/t3lib/tceforms/class.t3lib_tceforms_suggest.php']); +} diff --git t3lib/tceforms/class.t3lib_tceforms_suggest_defaultreceiver.php t3lib/tceforms/class.t3lib_tceforms_suggest_defaultreceiver.php new file mode 100644 index 0000000..e6a5aaa --- /dev/null +++ t3lib/tceforms/class.t3lib_tceforms_suggest_defaultreceiver.php @@ -0,0 +1,410 @@ + +* 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! +***************************************************************/ + +/** + * Default implementation of a handler class for an ajax record selector. + * + * Normally other implementations should be inherited from this one. + * queryTable() should not be overwritten under normal circumstances. + * + * @author Andreas Wolf + * @author Benjamin Mack + * + */ +class t3lib_TCEforms_Suggest_DefaultReceiver { + /** + * The name of the table to query + * + * @var string + */ + protected $table = ''; + + /** + * The name of the foreign table to query (records from this table will be used for displaying instead of the ones + * from $table) + * + * @var string + */ + protected $mmForeignTable = ''; + + /** + * Counter to limit the recursions when querying the table; also needed to choose the range of records to select + * + * @var integer + */ + protected $recursionCounter = 0; + + /** + * The select-clause to use when selecting the records (is manipulated and used by different functions, so it has to + * be a global var) + * + * @var string + */ + protected $selectClause = ''; + + /** + * The statement by which records will be ordered + * + * @var string + */ + protected $orderByStatement = ''; + + /** + * Additional WHERE clause to be appended to the SQL + * + * @var string + */ + protected $addWhere = ''; + + /** + * Configuration for this selector from TSconfig + * + * @var array + */ + protected $config = array(); + + /** + * The list of pages that are allowed to perform the search for records on + * + * @var array of PIDs + */ + protected $allowedPages = array(); + + /** + * The maximum number of items to select. + * + * @var integer + */ + protected $maxItems = 10; + + + /** + * The constructor of this class + * + * @param string $table + * @param array $config The configuration (TCA overlayed with TSconfig) to use for this selector + * @return void + */ + public function __construct($table, $config) { + $this->table = $table; + $this->config = $config; + + // get a list of all the pages that should be looked on + if (isset($config['pidList'])) { + $allowedPages = $pageIds = t3lib_div::trimExplode(',', $config['pidList']); + $depth = intval($config['pidDepth']); + foreach ($pageIds as $pageId) { + if ($pageId > 0) { + $allowedPages = t3lib_div::array_merge_recursive_overrule($allowedPages, $this->getAllSubpagesOfPage($pageId, $depth)); + } + } + $this->allowedPages = array_unique($allowedPages); + } + + if (isset($config['maxItemsInResultList'])) { + $this->maxItems = $config['maxItemsInResultList']; + } + + if ($this->table == 'pages') { + $this->addWhere = ' AND ' . $GLOBALS['BE_USER']->getPagePermsClause(1); + } + + // if table is versionized, only get the records from the Live Workspace + // the overlay itself of WS-records is done below + if ($GLOBALS['TCA'][$this->table]['ctrl']['versioningWS'] == true) { + $this->addWhere .= ' AND t3ver_wsid = 0'; + } + } + + /** + * Queries a table for records and completely processes them + * + * Returns a two-dimensional array of almost finished records; the only need to be put into a
  • -structure + * + * If you subclass this class, you will most likely only want to overwrite the functions called from here, but not + * this function itself + * + * @param array $params + * @param object $ref the parent object + * @return array The fetched and processed rows + */ + public function queryTable(&$params, &$ref) { + $rows = array(); + + $this->params = &$params; + $this->start = $this->recursionCounter * 50; + + $this->prepareSelectStatement(); + $this->prepareOrderByStatement(); + $result = $this->selectRecords(); + + + if ($result) { + while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) { + + // check if we already have collected the maximum number of records + if (count($rows) > $this->maxItems) break; + + $this->manipulateRecord($row); + $this->makeWorkspaceOverlay($row); + + // check if the user has access to the record + if (!$this->checkRecordAccess($row, $row['uid'])) { + continue; + } + + $iconPath = $this->getIcon($row); + $uid = ($row['t3ver_oid'] > 0 ? $row['t3ver_oid'] : $row['uid']); + + $croppedPath = $path = $this->getRecordPath($row, $uid); + if (strlen($croppedPath) > 30) { + $croppedPath = $GLOBALS['LANG']->csConvObj->crop($GLOBALS['LANG']->charSet, $path, 10) . '...' . $GLOBALS['LANG']->csConvObj->crop($GLOBALS['LANG']->charSet, $path, -20); + } + + $label = $this->getLabel($row); + $entry = array( + 'text' => '' . $label . '(' . $uid . ')
    ' . $croppedPath . '', + 'table' => ($this->mmForeignTable ? $this->mmForeignTable : $this->table), + 'label' => $label, + 'path' => $path, + 'uid' => $uid, + 'icon' => $iconPath, + 'style' => 'background-image:url(' . $iconPath . ');', + 'class' => (isset($this->config['cssClass']) ? $this->config['cssClass'] : ''), + ); + + $rows[$table . '_' . $uid] = $this->renderRecord($row, $entry); + } + + // if there are less records than we need, call this function again to get more records + if (count($rows) < $maxItems && $GLOBALS['TYPO3_DB']->sql_num_rows($result) >= 50 && $recursionCounter < $maxItems) { + $tmp = self::queryTable($this->params['value'], ++$recursionCounter); + $rows = array_merge($tmp, $rows); + } + return $rows; + } else { + return false; + } + } + + /** + * Prepare the statement for selecting the records which will be returned to the selector. May also return some + * other records (e.g. from a mm-table) which will be used later on to select the real records + * + * @return void + */ + protected function prepareSelectStatement() { + $searchWholePhrase = $this->config['searchWholePhrase']; + + $searchString = $this->params['value']; + $searchUid = intval($searchString); + if (strlen($searchString)) { + $this->selectClause = $GLOBALS['TCA'][$this->table]['ctrl']['label'] . ' LIKE \'' . ($searchWholePhrase ? '%' : '') . $GLOBALS['TYPO3_DB']->escapeStrForLike($searchString, $this->table).'%\''; + if ($searchUid > 0 && $searchUid == $searchString) { + $this->selectClause = '(' . $this->selectClause . ' OR uid = ' . $searchUid . ')'; + } + } + if (isset($GLOBALS['TCA'][$this->table]['ctrl']['delete'])) { + $this->selectClause .= ' AND ' . $GLOBALS['TCA'][$this->table]['ctrl']['delete'] . ' = 0'; + } + + if (count($this->allowedPages)) { + $pidList = $GLOBALS['TYPO3_DB']->cleanIntArray($this->allowedPages); + if (count($pidList)) { + $this->selectClause .= ' AND pid IN (' . implode(', ', $pidList) . ') '; + } + } + + // add an additional search condition comment + if (isset($this->config['searchCondition']) && strlen($this->config['searchCondition']) > 0) { + $this->selectClause .= ' AND ' . $this->config['searchCondition']; + } + + // add the global clauses to the where-statement + $this->selectClause .= $this->addWhere; + } + + /** + * Selects all subpages of one page, optionally only upto a certain level + * + * @param integer $uid + * @param integer $depth + */ + protected function getAllSubpagesOfPage($uid, $depth = 99) { + $pageIds = array($uid); + $level = 0; + + $pages = array($uid); + + // fetch all + while (($depth - $level) > 0 && !empty($pageIds)) { + ++$level; + + $pidList = $GLOBALS['TYPO3_DB']->cleanIntArray($pageIds); + $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid', 'pages', 'pid IN (' . implode(', ', $pidList) . ')', '', '', '', 'uid'); + if (count($rows) > 0) { + $pageIds = array_keys($rows); + $pageIdsString = implode(',', $pageIds); + + $pages = array_merge($pages, $pageIds); + } else { + break; + } + } + + return $pages; + } + + /** + * Prepares the clause by which the result elements are sorted. See description of ORDER BY in + * SQL standard for reference. + * + * @return void + */ + protected function prepareOrderByStatement() { + if ($GLOBALS['TCA'][$this->table]['ctrl']['label']) { + $this->orderByStatement = $GLOBALS['TCA'][$this->table]['ctrl']['label']; + } + } + + /** + * Manipulate a record before using it to render the selector; may be used to replace a MM-relation etc. + * + * @param array $row + */ + protected function manipulateRecord(&$row) { + } + + /** + * Select the recrods from the table (uses the statement prepared in $this->selectClause) + * + * @return resource The SQL resource which holds the records or FALSE if there was an error + */ + protected function selectRecords() { + $result = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $this->table, $this->selectClause, '', $this->orderByStatement, $this->start . ', 50'); + return ($result ? $result : false); + } + + /** + * Selects whether the logged in Backend User is allowed to read a specific record + */ + protected function checkRecordAccess($row, $uid) { + $retValue = true; + if (($this->mmForeignTable ? $this->mmForeignTable : $this->table) == 'pages') { + if (!t3lib_BEfunc::readPageAccess($uid, $GLOBALS['BE_USER']->getPagePermsClause(1))) { + $retValue = false; + } + } else { + if (!is_array(t3lib_BEfunc::readPageAccess($row['pid'], $GLOBALS['BE_USER']->getPagePermsClause(1)))) { + $retValue = false; + } + } + return $retValue; + } + + /** + * Overlay the given record with its workspace-version, if any + * + * @param array the record to get the workspace version for + * @return void (passed by reference) + */ + protected function makeWorkspaceOverlay(&$row) { + // check for workspace-versions + if ($GLOBALS['BE_USER']->workspace != 0 && $GLOBALS['TCA'][$this->table]['ctrl']['versioningWS'] == true) { + t3lib_BEfunc::workspaceOL(($this->mmForeignTable ? $this->mmForeignTable : $this->table), $row); + } + } + + /** + * Return the icon for a record - just a wrapper for two functions from t3lib_iconWorks + * + * @param array $row The record to get the icon for + * @return string The path to the icon + */ + protected function getIcon($row) { + $icon = t3lib_iconWorks::getIcon(($this->mmForeignTable ? $this->mmForeignTable : $this->table), $row); + return t3lib_iconWorks::skinImg('', $icon, '', 1); + } + + /** + * Returns the path for a record. Is the whole path for all records except pages - for these the last part is cut + * off, because it contains the pagetitle itself, which would be double information + * + * The path is returned uncut, cutting has to be done by calling function. + * + * @param array $row The row + * @param integer $uid The records uid + * @return string The record-path + */ + protected function getRecordPath(&$row, $uid) { + $titleLimit = max($this->config['maxPathTitleLength'], 0); + + if (($this->mmForeignTable ? $this->mmForeignTable : $this->table) == 'pages') { + $path = t3lib_BEfunc::getRecordPath($uid, '', $titleLimit); + // for pages we only want the first (n-1) parts of the path, because the n-th part is the page itself + $path = substr($path, 0, strrpos($path, '/', -2)) . '/'; + } else { + $path = t3lib_BEfunc::getRecordPath($row['pid'], '', $titleLimit); + } + + return $path; + } + + /** + * Returns a label for a given record; usually only a wrapper for t3lib_BEfunc::getRecordTitle + * + * @param array $row + * @return The label for the record + */ + protected function getLabel($row) { + return t3lib_BEfunc::getRecordTitle(($this->mmForeignTable ? $this->mmForeignTable : $this->table), $row, true); + } + + /** + * Calls a user function for rendering the page. + * + * This user function should manipulate $entry, especially $entry['text'] + * + * @param array $row The row + * @param array $entry The entry to render + * @return array The rendered entry (will be put into a
  • later on + */ + protected function renderRecord($row, $entry) { + // call renderlet if available (normal pages etc. usually don't have one) + if ($this->config['renderFunc'] != '') { + $params = array( + 'table' => $this->table, + 'uid' => $row['uid'], + 'row' => $row, + 'entry' => &$entry + ); + t3lib_div::callUserFunction($this->config['renderFunc'], $params, $this, ''); + } + + return $entry; + } +} diff --git typo3/gfx/group_suggest.gif typo3/gfx/group_suggest.gif new file mode 100644 index 0000000..6a39a4c Binary files /dev/null and typo3/gfx/group_suggest.gif differ diff --git typo3/stylesheet.css typo3/stylesheet.css index 74a00d3..ca72a7d 100644 --- typo3/stylesheet.css +++ typo3/stylesheet.css @@ -1078,6 +1078,65 @@ table.typo3-TCEforms div.typo3-dyntabmenu-tabs { margin-top: 10px; } +div.typo3-TCEforms-suggest-position-right { + margin-left: 10px; + margin-top: 5px; +} + +div.typo3-TCEforms-suggest label { + margin-right: 5px; +} + +input.typo3-TCEforms-suggest-search { + width: 200px; + background-image: url(gfx/zoom.gif); + background-position: 2px center; + background-repeat: no-repeat; + padding-left: 16px; +} + +div.typo3-TCEforms-suggest-choices { + position: absolute; + width: 250px; + background-color: white; + border: 1px solid #888; +} +div.typo3-TCEforms-suggest-choices UL { + list-style-type:none; + margin: 0; + padding: 0; +} +div.typo3-TCEforms-suggest-choices LI.selected { background-color: #ffb !important;} +div.typo3-TCEforms-suggest-choices LI { + list-style-type:none; + display:block; + margin:0; + padding:2px; + padding-left:24px; + height:32px; + cursor:pointer; + background-color:#EFEFF4; + background-repeat:no-repeat; + background-position:4px center; +} +div.typo3-TCEforms-suggest-choices LI.suggest-noresults { + height: auto; +} +div.typo3-TCEforms-suggest-choices LI.pages { + background-color:#FCC; +} +div.typo3-TCEforms-suggest-choices SPAN.suggest-label { + font-weight:bold; +} +div.typo3-TCEforms-suggest-choices SPAN.suggest-uid { + font-size:0.9em; + margin-left:0.3em; +} +div.typo3-TCEforms-suggest-choices SPAN.suggest-path { + font-size:0.9em; + margin-top:0.3em; +} + /* - - - - - - - - - - - - - - - - - - - - - @@ -2824,13 +2883,3 @@ div { border: 1px dotted #666; } */ - - - - - - - - - - diff --git typo3/sysext/fe_edit/view/class.tx_feedit_adminpanel.php typo3/sysext/fe_edit/view/class.tx_feedit_adminpanel.php new file mode 100644 index 0000000..efc4d66 --- /dev/null +++ typo3/sysext/fe_edit/view/class.tx_feedit_adminpanel.php @@ -0,0 +1,640 @@ + +* (c) 2008-2009 David Slayback +* 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! +***************************************************************/ +/** + * View class for the admin panel in frontend editing. + * + * $Id$ + * + * @author Jeff Segars + * @author David Slayback + * @package TYPO3 + * @subpackage fe_edit + */ +class tx_feedit_adminpanel { + + /** + * Determines whether the update button should be shown. + * + * @var boolean + */ + protected $extNeedUpdate = false; + + /** + * Creates and returns the HTML code for the Admin Panel in the TSFE frontend. + * + * @return string HTML for the Admin Panel + */ + public function display() { + $out = ''; + //CSS + $GLOBALS['TSFE']->additionalHeaderData['admPanelCSS'] = ''; + if(!empty($GLOBALS['TBE_STYLES']['stylesheets']['admPanel'])) { + $GLOBALS['TSFE']->additionalHeaderData['admPanelCSS-Skin'] = ' + + '; + } + + if ($GLOBALS['BE_USER']->uc['TSFE_adminConfig']['display_top']) { + if ($GLOBALS['BE_USER']->frontendEdit->isAdminModuleEnabled('preview')) { + $out .= $this->getPreviewModule(); + } + if ($GLOBALS['BE_USER']->frontendEdit->isAdminModuleEnabled('cache')) { + $out .= $this->getCacheModule(); + } + if ($GLOBALS['BE_USER']->frontendEdit->isAdminModuleEnabled('publish')) { + $out .= $this->getPublishModule(); + } + if ($GLOBALS['BE_USER']->frontendEdit->isAdminModuleEnabled('edit')){ + $out .= $this->getEditModule(); + } + if ($GLOBALS['BE_USER']->frontendEdit->isAdminModuleEnabled('tsdebug')) { + $out .= $this->getTSDebugModule(); + } + if ($GLOBALS['BE_USER']->frontendEdit->isAdminModuleEnabled('info')) { + $out .= $this->getInfoModule(); + } + } + + $row = ''; + $row .= ''; + $row .= '' . $this->extFw($this->extGetLL('adminOptions')) . ''; + $row .= $this->extFw(': ' . $GLOBALS['BE_USER']->user['username']); + + $header = ' + + ' . + $this->extItemLink('top',$row) . ' + + ' . ($this->extNeedUpdate ? '' : '') . ' + '; + + $query = !t3lib_div::_GET('id') ? ('' . chr(10)) : ''; + // the dummy field is needed for Firefox: to force a page reload on submit with must change the form value with JavaScript (see "onsubmit" attribute of the "form" element") + $query .= ''; + foreach (t3lib_div::_GET() as $key => $value) { + if ($key != 'TSFE_ADMIN_PANEL') { + if (is_array($value)) { + $query .= $this->getHiddenFields($key, $value); + } else { + $query .= '' . chr(10); + } + } + } + + $out = ' + + +
    ' . +$query . ' + ' . + $header . + $out . ' +
    +
    '; + + if ($GLOBALS['BE_USER']->uc['TSFE_adminConfig']['display_top']) { + $out .= ''; + $out .= ' + + '; + } + + $out = ' +
    + ' . $out . ' +
    + '; + + return $out; + } + + /** + * Fetches recursively all GET parameters as hidden fields. + * Called from display() + * + * @param string current key + * @param mixed current value + * @return string hidden fields + * @see display() + */ + protected function getHiddenFields($key, &$val) { + $out = ''; + foreach ($val as $k => $v) { + if (is_array($v)) { + $out .= $this->getHiddenFields($key . '[' . $k . ']', $v); + } else { + $out .= '' . chr(10); + } + } + return $out; + } + + /***************************************************** + * + * Creating sections of the Admin Panel + * + ****************************************************/ + + /** + * Creates the content for the "preview" section ("module") of the Admin Panel + * + * @param string Optional start-value; The generated content is added to this variable. + * @return string HTML content for the section. Consists of a string with table-rows with four columns. + * @see display() + */ + protected function getPreviewModule($out = '') { + $out .= $this->extGetHead('preview'); + if ($GLOBALS['BE_USER']->uc['TSFE_adminConfig']['display_preview']) { + $this->extNeedUpdate = true; + $out .= $this->extGetItem('preview_showHiddenPages', 'uc['TSFE_adminConfig']['preview_showHiddenPages'] ? ' checked="checked"' : '') . ' />'); + $out .= $this->extGetItem('preview_showHiddenRecords', 'uc['TSFE_adminConfig']['preview_showHiddenRecords'] ? ' checked="checked"' : '') . ' />'); + + // Simulate date + $out .= $this->extGetItem('preview_simulateDate', ''); + $this->extJSCODE .= 'TSFEtypo3FormFieldSet("TSFE_ADMIN_PANEL[preview_simulateDate]", "datetime", "", 1,0);'; + + // Simulate fe_user: + $options = ''; + $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery( + 'fe_groups.uid, fe_groups.title', + 'fe_groups,pages', + 'pages.uid=fe_groups.pid AND pages.deleted=0 ' . t3lib_BEfunc::deleteClause('fe_groups') . ' AND ' . $GLOBALS['BE_USER']->getPagePermsClause(1) + ); + while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { + $options .= ''; + } + $out .= $this->extGetItem('preview_simulateUserGroup', ''); + } + + return $out; + } + + /** + * Creates the content for the "cache" section ("module") of the Admin Panel + * + * @param string Optional start-value; The generated content is added to this variable. + * @return string HTML content for the section. Consists of a string with table-rows with four columns. + * @see display() + */ + protected function getCacheModule($out = '') { + $out.= $this->extGetHead('cache'); + if ($GLOBALS['BE_USER']->uc['TSFE_adminConfig']['display_cache']) { + $this->extNeedUpdate = true; + $out .= $this->extGetItem('cache_noCache', 'uc['TSFE_adminConfig']['cache_noCache'] ? ' checked="checked"' : '') . ' />'); + $options = ''; + $options .= ''; + $options .= ''; + $options .= ''; + $out .= $this->extGetItem('cache_clearLevels', '' . + ''); + + // Generating tree: + $depth = $GLOBALS['BE_USER']->frontendEdit->extGetFeAdminValue('cache', 'clearCacheLevels'); + $outTable = ''; + $GLOBALS['BE_USER']->extPageInTreeInfo = array(); + $GLOBALS['BE_USER']->extPageInTreeInfo[] = array($GLOBALS['TSFE']->page['uid'], htmlspecialchars($GLOBALS['TSFE']->page['title']), $depth+1); + $GLOBALS['BE_USER']->extGetTreeList($GLOBALS['TSFE']->id, $depth, 0, $GLOBALS['BE_USER']->getPagePermsClause(1)); + foreach ($GLOBALS['BE_USER']->extPageInTreeInfo as $row) { + $outTable .= ' + + ' . $this->extFw($row[1]) . ' + + ' . $this->extFw($GLOBALS['BE_USER']->extGetNumberOfCachedPages($row[0])) . ' + '; + } + + $outTable = '
    ' . $outTable . '
    '; + $outTable .= ''; + + $out .= $this->extGetItem('cache_cacheEntries', $outTable); + } + + return $out; + } + + /** + * Creates the content for the "publish" section ("module") of the Admin Panel + * + * @param string Optional start-value; The generated content is added to this variable. + * @return string HTML content for the section. Consists of a string with table-rows with four columns. + * @see display() + */ + protected function getPublishModule($out = '') { + $out .= $this->extGetHead('publish'); + if ($GLOBALS['BE_USER']->uc['TSFE_adminConfig']['display_publish']) { + $this->extNeedUpdate = true; + $options = ''; + $options .= ''; + $options .= ''; + $options .= ''; + $out .= $this->extGetItem('publish_levels', '' . + ' '); + + // Generating tree: + $depth = $GLOBALS['BE_USER']->frontendEdit->extGetFeAdminValue('publish', 'levels'); + $outTable = ''; + $GLOBALS['BE_USER']->extPageInTreeInfo = array(); + $GLOBALS['BE_USER']->extPageInTreeInfo[] = array($GLOBALS['TSFE']->page['uid'], htmlspecialchars($GLOBALS['TSFE']->page['title']), $depth+1); + $GLOBALS['BE_USER']->extGetTreeList($GLOBALS['TSFE']->id, $depth, 0, $GLOBALS['BE_USER']->getPagePermsClause(1)); + foreach ($GLOBALS['BE_USER']->extPageInTreeInfo as $row) { + $outTable.= ' + + ' . $this->extFw($row[1]) . ' + + ' . $this->extFw('...') . ' + '; + } + $outTable = '
    ' . $outTable . '
    '; + $outTable .= ''; + + $out .= $this->extGetItem('publish_tree', $outTable); + } + + return $out; + } + + /** + * Creates the content for the "edit" section ("module") of the Admin Panel + * + * @param string Optional start-value; The generated content is added to this variable. + * @return string HTML content for the section. Consists of a string with table-rows with four columns. + * @see display() + */ + protected function getEditModule($out = '') { + $out .= $this->extGetHead('edit'); + if ($GLOBALS['BE_USER']->uc['TSFE_adminConfig']['display_edit']) { + + // If another page module was specified, replace the default Page module with the new one + $newPageModule = trim($GLOBALS['BE_USER']->getTSConfigVal('options.overridePageModule')); + $pageModule = t3lib_BEfunc::isModuleSetInTBE_MODULES($newPageModule) ? $newPageModule : 'web_layout'; + + $this->extNeedUpdate = true; + $out .= $this->extGetItem('edit_displayFieldIcons', 'uc['TSFE_adminConfig']['edit_displayFieldIcons'] ? ' checked="checked"' : '') . ' />'); + $out .= $this->extGetItem('edit_displayIcons', 'uc['TSFE_adminConfig']['edit_displayIcons'] ? ' checked="checked"' : '') . ' />'); + $out .= $this->extGetItem('edit_editFormsOnPage', 'uc['TSFE_adminConfig']['edit_editFormsOnPage'] ? ' checked="checked"':'') . ' />'); + $out .= $this->extGetItem('edit_editNoPopup', 'uc['TSFE_adminConfig']['edit_editNoPopup'] ? ' checked="checked"' : '') . ' />'); + $out .= $this->extGetItem('', $this->ext_makeToolBar()); + + if (!t3lib_div::_GP('ADMCMD_view')) { + $out .= $this->extGetItem('', 'page['uid']) . '; + if (parent.opener.top.content && parent.opener.top.content.nav_frame && parent.opener.top.content.nav_frame.refresh_nav) { + parent.opener.top.content.nav_frame.refresh_nav(); + } + parent.opener.top.goToModule("' . $pageModule . '"); + parent.opener.top.focus(); + } else { + vHWin=window.open(\'' . TYPO3_mainDir.t3lib_BEfunc::getBackendScript() . '\',\'' . md5('Typo3Backend-' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename']) . '\',\'status=1,menubar=1,scrollbars=1,resizable=1\'); + vHWin.focus(); + } + return false; + '). + '">' . $this->extFw($this->extGetLL('edit_openAB')) . ''); + } + } + + return $out; + } + + /** + * Creates the content for the "tsdebug" section ("module") of the Admin Panel + * + * @param string Optional start-value; The generated content is added to this variable. + * @return string HTML content for the section. Consists of a string with table-rows with four columns. + * @see display() + */ + protected function getTSDebugModule($out = '') { + $out .= $this->extGetHead('tsdebug'); + if ($GLOBALS['BE_USER']->uc['TSFE_adminConfig']['display_tsdebug']) { + $this->extNeedUpdate = true; + + $out .= $this->extGetItem('tsdebug_tree', 'uc['TSFE_adminConfig']['tsdebug_tree'] ? ' checked="checked"' : '') . ' />'); + $out .= $this->extGetItem('tsdebug_displayTimes', 'uc['TSFE_adminConfig']['tsdebug_displayTimes'] ? ' checked="checked"' : '') . ' />'); + $out .= $this->extGetItem('tsdebug_displayMessages', 'uc['TSFE_adminConfig']['tsdebug_displayMessages'] ? ' checked="checked"':'') . ' />'); + $out .= $this->extGetItem('tsdebug_LR', 'uc['TSFE_adminConfig']['tsdebug_LR'] ? ' checked="checked"' : '') . ' />'); + $out .= $this->extGetItem('tsdebug_displayContent', 'uc['TSFE_adminConfig']['tsdebug_displayContent'] ? ' checked="checked"' : '') . ' />'); + $out .= $this->extGetItem('tsdebug_displayQueries', 'uc['TSFE_adminConfig']['tsdebug_displayQueries'] ? ' checked="checked"' : '') . ' />'); + $out .= $this->extGetItem('tsdebug_forceTemplateParsing', 'uc['TSFE_adminConfig']['tsdebug_forceTemplateParsing'] ? ' checked="checked"' : '') . ' />'); + + $GLOBALS['TT']->printConf['flag_tree'] = $GLOBALS['BE_USER']->frontendEdit->extGetFeAdminValue('tsdebug', 'tree'); + $GLOBALS['TT']->printConf['allTime'] = $GLOBALS['BE_USER']->frontendEdit->extGetFeAdminValue('tsdebug', 'displayTimes'); + $GLOBALS['TT']->printConf['flag_messages'] = $GLOBALS['BE_USER']->frontendEdit->extGetFeAdminValue('tsdebug', 'displayMessages'); + $GLOBALS['TT']->printConf['flag_content'] = $GLOBALS['BE_USER']->frontendEdit->extGetFeAdminValue('tsdebug', 'displayContent'); + $GLOBALS['TT']->printConf['flag_queries'] = $GLOBALS['BE_USER']->frontendEdit->extGetFeAdminValue('tsdebug', 'displayQueries'); + + $out.= ' + + + ' . $GLOBALS['TT']->printTSlog() . ' + '; + } + + return $out; + } + + /** + * Creates the content for the "info" section ("module") of the Admin Panel + * + * @param string Optional start-value; The generated content is added to this variable. + * @return string HTML content for the section. Consists of a string with table-rows with four columns. + * @see display() + */ + protected function getInfoModule($out = '') { + $out .= $this->extGetHead('info'); + if ($GLOBALS['BE_USER']->uc['TSFE_adminConfig']['display_info']) { + $tableArr = array(); + + if ($GLOBALS['BE_USER']->frontendEdit->extGetFeAdminValue('cache', 'noCache')) { + $theBytes = 0; + $count = 0; + + if (count($GLOBALS['TSFE']->imagesOnPage)) { + $tableArr[] = array('*Images on this page:*', ''); + foreach ($GLOBALS['TSFE']->imagesOnPage as $file) { + $fs = @filesize($file); + $tableArr[] = array('– ' . $file, t3lib_div::formatSize($fs)); + $theBytes+= $fs; + $count++; + } + } + $tableArr[] = array('', ''); // Add an empty line + + $tableArr[] = array('*Total number of images:*', $count); + $tableArr[] = array('*Total image file sizes:*', t3lib_div::formatSize($theBytes)); + $tableArr[] = array('*Document size:*', t3lib_div::formatSize(strlen($GLOBALS['TSFE']->content))); + $tableArr[] = array('*Total page load:*', t3lib_div::formatSize(strlen($GLOBALS['TSFE']->content)+$theBytes)); + $tableArr[] = array('', ''); + } + + $tableArr[] = array('id:', $GLOBALS['TSFE']->id); + $tableArr[] = array('type:', $GLOBALS['TSFE']->type); + $tableArr[] = array('gr_list:', $GLOBALS['TSFE']->gr_list); + $tableArr[] = array('no_cache:', $GLOBALS['TSFE']->no_cache ? 1 : 0); + $tableArr[] = array('USER_INT objects:', count($GLOBALS['TSFE']->config['INTincScript'])); + $tableArr[] = array('fe_user, name:', $GLOBALS['TSFE']->fe_user->user['username']); + $tableArr[] = array('fe_user, uid:', $GLOBALS['TSFE']->fe_user->user['uid']); + $tableArr[] = array('', ''); // Add an empty line + + // parsetime: + $tableArr[] = array('*Total parsetime:*', $GLOBALS['TSFE']->scriptParseTime . ' ms'); + + $table = ''; + foreach ($tableArr as $arr) { + if (strlen($arr[0])) { // Put text wrapped by "*" between tags + $value1 = preg_replace('/^\*(.*)\*$/', '$1', $arr[0], -1, $count); + $value1 = ($count?'':'') . $this->extFw($value1) . ($count?'':''); + } else { + $value1 = $this->extFw(' '); + } + + $value2 = strlen($arr[1]) ? $arr[1] : ' '; + $value2 = $this->extFw($value2); + + $table .= ' + + ' . $value1 . ' + ' . $value2 . ' + '; + } + + $table = '' . $table . '
    '; + + $out .= ' + + + ' . $table . ' + '; + } + + return $out; + } + + /***************************************************** + * + * Admin Panel Layout Helper functions + * + ****************************************************/ + + /** + * Returns a row (with colspan=4) which is a header for a section in the Admin Panel. + * It will have a plus/minus icon and a label which is linked so that it submits the form which surrounds the whole Admin Panel when clicked, alterting the TSFE_ADMIN_PANEL[display_' . $pre . '] value + * See the functions get*Module + * + * @param string The suffix to the display_ label. Also selects the label from the LOCAL_LANG array. + * @return string HTML table row. + * @access private + * @see extGetItem() + */ + protected function extGetHead($pre) { + $out = ''; + $out .= ''; + $out .= $this->extFw($this->extGetLL($pre)); + + $out = $this->extItemLink($pre,$out); + return ' + + ' . $out . ' + '; + } + + /** + * Wraps a string in a link which will open/close a certain part of the Admin Panel + * + * @param string The code for the display_ label/key + * @param string Input string + * @return string Linked input string + * @access private + * @see extGetHead() + */ + protected function extItemLink($pre, $str) { + return '' . $str . ''; + } + + /** + * Returns a row (with 4 columns) for content in a section of the Admin Panel. + * It will take $pre as a key to a label to display and $element as the content to put into the forth cell. + * + * @param string Key to label + * @param string The HTML content for the forth table cell. + * @return string HTML table row. + * @access private + * @see extGetHead() + */ + protected function extGetItem($pre, $element) { + $out = ' + + + ' . ($pre ? $this->extFw($this->extGetLL($pre)) : ' ') . ' + + ' . $element . ' + '; + + return $out; + } + + /** + * Wraps a string in a span-tag with black verdana font + * + * @param string The string to wrap + * @return string + */ + protected function extFw($str) { + return '' . $str . ''; + } + + /** + * Creates the tool bar links for the "edit" section of the Admin Panel. + * + * @return string A string containing images wrapped in -tags linking them to proper functions. + */ + public function ext_makeToolBar() { + // If mod.web_list.newContentWiz.overrideWithExtension is set, use that extension's create new content wizard instead: + $tmpTSc = t3lib_BEfunc::getModTSconfig($this->pageinfo['uid'],'mod.web_list'); + $tmpTSc = $tmpTSc ['properties']['newContentWiz.']['overrideWithExtension']; + $newContentWizScriptPath = t3lib_extMgm::isLoaded($tmpTSc) ? (t3lib_extMgm::extRelPath($tmpTSc) . 'mod1/db_new_content_el.php') : (TYPO3_mainDir . 'sysext/cms/layout/db_new_content_el.php'); + + $perms = $GLOBALS['BE_USER']->calcPerms($GLOBALS['TSFE']->page); + $langAllowed = $GLOBALS['BE_USER']->checkLanguageAccess($GLOBALS['TSFE']->sys_language_uid); + + $toolBar = ''; + $id = $GLOBALS['TSFE']->id; + $toolBar .= '' . + ''; + + if ($perms&16 && $langAllowed) { + $params = ''; + if ($GLOBALS['TSFE']->sys_language_uid) { + $params = '&sys_language_uid=' . $GLOBALS['TSFE']->sys_language_uid; + } + $toolBar .= '' . + ''; + } + if ($perms&2) { + $toolBar .= '' . + ''; + } + if ($perms&8) { + $toolBar .= '' . + ''; + } + if ($perms&2) { + $params = '&edit[pages][' . $id . ']=edit'; + $toolBar .= '' . + ''; + + if ($GLOBALS['TSFE']->sys_language_uid && $langAllowed) { + $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery( + 'uid,pid,t3ver_state', 'pages_language_overlay', + 'pid=' . intval($id) . ' AND sys_language_uid=' . $GLOBALS['TSFE']->sys_language_uid . $GLOBALS['TSFE']->sys_page->enableFields('pages_language_overlay'), + '', '', '1'); + $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res); + $GLOBALS['TSFE']->sys_page->versionOL('pages_language_overlay',$row); + if (is_array($row)) { + $params = '&edit[pages_language_overlay][' . $row['uid'] . ']=edit'; + $toolBar .= '' . + ''; + } + } + } + if ($GLOBALS['BE_USER']->check('modules', 'web_list')) { + $toolBar .= '' . + ''; + } + + return $toolBar; + } + + /** + * Returns the label for key, $key. If a translation for the language set in $GLOBALS['BE_USER']->uc['lang'] is found that is returned, otherwise the default value. + * IF the global variable $LOCAL_LANG is NOT an array (yet) then this function loads the global $LOCAL_LANG array with the content of "sysext/lang/locallang_tsfe.php" so that the values therein can be used for labels in the Admin Panel + * + * @param string Key for a label in the $LOCAL_LANG array of "sysext/lang/locallang_tsfe.php" + * @return string The value for the $key + */ + protected function extGetLL($key) { + global $LOCAL_LANG; + if (!is_array($LOCAL_LANG)) { + $GLOBALS['LANG']->includeLLFile('EXT:lang/locallang_tsfe.php'); + if (!is_array($LOCAL_LANG)) { + $LOCAL_LANG = array(); + } + } + + $labelStr = htmlspecialchars($GLOBALS['LANG']->getLL($key)); // Label string in the default backend output charset. + + // Convert to utf-8, then to entities: + if ($GLOBALS['LANG']->charSet!='utf-8') { + $labelStr = $GLOBALS['LANG']->csConvObj->utf8_encode($labelStr,$GLOBALS['LANG']->charSet); + } + $labelStr = $GLOBALS['LANG']->csConvObj->utf8_to_entities($labelStr); + + // Return the result: + return $labelStr; + } +} + +if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/fe_edit/view/class.tx_feedit_adminpanel.php']) { + include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/fe_edit/view/class.tx_feedit_adminpanel.php']); +} + +?> \ No newline at end of file diff --git typo3/sysext/lang/locallang_core.xml typo3/sysext/lang/locallang_core.xml index b9bd047..b25ca21 100755 --- typo3/sysext/lang/locallang_core.xml +++ typo3/sysext/lang/locallang_core.xml @@ -101,6 +101,8 @@ Do you want to continue WITHOUT saving? + + diff --git typo3/sysext/t3skin/stylesheets/typo3-TCEforms.css typo3/sysext/t3skin/stylesheets/typo3-TCEforms.css index 4c47b39..727e65d 100644 --- typo3/sysext/t3skin/stylesheets/typo3-TCEforms.css +++ typo3/sysext/t3skin/stylesheets/typo3-TCEforms.css @@ -211,3 +211,12 @@ TABLE.typo3-TCEforms td.thumbnails { .typo3-TCEforms-palette SELECT.select { margin-top: 2px; } + +input.typo3-TCEforms-suggest-search { + width: 200px; + background-image: url(../icons/gfx/zoom.gif); + background-position: 2px center; + background-repeat: no-repeat; + padding-left: 20px; + vertical-align: middle; +}