Cleanup: Updated NEWS.txt
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_frontendedit.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2008-2009 Jeff Segars <jeff@webempoweredchurch.org>
6 * (c) 2008-2009 David Slayback <dave@webempoweredchurch.org>
7 * All rights reserved
8 *
9 * This script is part of the TYPO3 project. The TYPO3 project is
10 * free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * The GNU General Public License can be found at
16 * http://www.gnu.org/copyleft/gpl.html.
17 * A copy is found in the textfile GPL.txt and important notices to the license
18 * from the author is found in LICENSE.txt distributed with these scripts.
19 *
20 *
21 * This script is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * This copyright notice MUST APPEAR in all copies of the script!
27 ***************************************************************/
28 /**
29 * Controller class for frontend editing.
30 *
31 * $Id$
32 *
33 * @author Jeff Segars <jeff@webempoweredchurch.org>
34 * @author David Slayback <dave@webempoweredchurch.org>
35 * @package TYPO3
36 * @subpackage t3lib
37 */
38 class t3lib_frontendedit {
39
40 /**
41 * TCEmain object.
42 *
43 * @var t3lib_tcemain
44 */
45 protected $tce;
46
47
48 /**
49 * Force preview?
50 *
51 * @var boolean
52 */
53 protected $ext_forcePreview = false;
54
55 /**
56 * Comma separated list of page UIDs to be published.
57 *
58 * @var string
59 */
60 protected $extPublishList = '';
61
62 /**
63 * Creates and initializes the TCEmain object.
64 *
65 * @return void
66 */
67 public function __construct() {
68 $this->tce = t3lib_div::makeInstance('t3lib_TCEmain');
69 $this->tce->stripslashes_values=0;
70 }
71
72 /**
73 * Initializes configuration options.
74 *
75 * @return void
76 */
77 public function initConfigOptions() {
78 $this->saveConfigOptions();
79 $this->TSFE_EDIT = t3lib_div::_POST('TSFE_EDIT');
80
81 // Setting some values based on the admin panel
82 $GLOBALS['TSFE']->forceTemplateParsing = $this->extGetFeAdminValue('tsdebug', 'forceTemplateParsing');
83 $GLOBALS['TSFE']->displayEditIcons = $this->extGetFeAdminValue('edit', 'displayIcons');
84 $GLOBALS['TSFE']->displayFieldEditIcons = $this->extGetFeAdminValue('edit', 'displayFieldIcons');
85
86 if ($this->extGetFeAdminValue('tsdebug', 'displayQueries')) {
87 if ($GLOBALS['TYPO3_DB']->explainOutput == 0) { // do not override if the value is already set in t3lib_db
88 // Enable execution of EXPLAIN SELECT queries
89 $GLOBALS['TYPO3_DB']->explainOutput = 3;
90 }
91 }
92
93 if (t3lib_div::_GP('ADMCMD_editIcons')) {
94 $GLOBALS['TSFE']->displayFieldEditIcons=1;
95 $GLOBALS['BE_USER']->uc['TSFE_adminConfig']['edit_editNoPopup']=1;
96 }
97
98 if (t3lib_div::_GP('ADMCMD_simUser')) {
99 $GLOBALS['BE_USER']->uc['TSFE_adminConfig']['preview_simulateUserGroup']=intval(t3lib_div::_GP('ADMCMD_simUser'));
100 $this->ext_forcePreview = true;
101 }
102
103 if (t3lib_div::_GP('ADMCMD_simTime')) {
104 $GLOBALS['BE_USER']->uc['TSFE_adminConfig']['preview_simulateDate']=intval(t3lib_div::_GP('ADMCMD_simTime'));
105 $this->ext_forcePreview = true;
106 }
107
108 // Include classes for editing IF editing module in Admin Panel is open
109 if (($this->isAdminModuleEnabled('edit') && $this->isAdminModuleOpen('edit')) || $GLOBALS['TSFE']->displayEditIcons == 1) {
110 $GLOBALS['TSFE']->includeTCA();
111 if ($this->isEditAction()) {
112 require_once (PATH_t3lib . 'class.t3lib_tcemain.php');
113 $this->editAction();
114 }
115
116 if ($this->isEditFormShown()) {
117 require_once(PATH_t3lib . 'class.t3lib_tceforms.php');
118 require_once(PATH_t3lib . 'class.t3lib_iconworks.php');
119 require_once(PATH_t3lib . 'class.t3lib_loaddbgroup.php');
120 require_once(PATH_t3lib . 'class.t3lib_transferdata.php');
121 }
122 }
123
124 if ($GLOBALS['TSFE']->forceTemplateParsing || $GLOBALS['TSFE']->displayEditIcons || $GLOBALS['TSFE']->displayFieldEditIcons) {
125 $GLOBALS['TSFE']->set_no_cache();
126 }
127 }
128
129
130 /**
131 * Delegates to the appropriate view and renders the admin panel content.
132 *
133 * @return string.
134 */
135 public function displayAdmin() {
136 $content = '';
137 $adminClass = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/classes/class.frontendedit.php']['admin'];
138 if ($adminClass && !$GLOBALS['BE_USER']->extAdminConfig['hide'] && $GLOBALS['TSFE']->config['config']['admPanel']) {
139 $admin = &t3lib_div::getUserObj($adminClass);
140 if (is_object($admin)) {
141 $content = $admin->display();
142 }
143 }
144
145 return $content;
146 }
147
148 /**
149 * Generates the "edit panels" which can be shown for a page or records on a page when the Admin Panel is enabled for a backend users surfing the frontend.
150 * With the "edit panel" the user will see buttons with links to editing, moving, hiding, deleting the element
151 * This function is used for the cObject EDITPANEL and the stdWrap property ".editPanel"
152 *
153 * @param string A content string containing the content related to the edit panel. For cObject "EDITPANEL" this is empty but not so for the stdWrap property. The edit panel is appended to this string and returned.
154 * @param array TypoScript configuration properties for the editPanel
155 * @param string The "table:uid" of the record being shown. If empty string then $this->currentRecord is used. For new records (set by $conf['newRecordFromTable']) it's auto-generated to "[tablename]:NEW"
156 * @param array Alternative data array to use. Default is $this->data
157 * @return string The input content string with the editPanel appended. This function returns only an edit panel appended to the content string if a backend user is logged in (and has the correct permissions). Otherwise the content string is directly returned.
158 * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=375&cHash=7d8915d508
159 */
160 public function displayEditPanel($content, array $conf, $currentRecord, array $dataArray) {
161 if ($conf['newRecordFromTable']) {
162 $currentRecord = $conf['newRecordFromTable'] . ':NEW';
163 $conf['allow'] = 'new';
164 }
165
166 list($table, $uid) = explode(':', $currentRecord);
167
168 // Page ID for new records, 0 if not specified
169 $newRecordPid = intval($conf['newRecordInPid']);
170 if (!$conf['onlyCurrentPid'] || $dataArray['pid'] == $GLOBALS['TSFE']->id) {
171 if ($table=='pages') {
172 $newUid = $uid;
173 } else {
174 if ($conf['newRecordFromTable']) {
175 $newUid = $GLOBALS['TSFE']->id;
176 if ($newRecordPid) {
177 $newUid = $newRecordPid;
178 }
179 } else {
180 $newUid = -1 * $uid;
181 }
182 }
183 }
184
185 if ($GLOBALS['TSFE']->displayEditIcons && $table && $this->allowedToEdit($table, $dataArray, $conf) && $this->allowedToEditLanguage($table, $dataArray)) {
186 $editClass = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/classes/class.frontendedit.php']['edit'];
187 if ($editClass) {
188 $edit = &t3lib_div::getUserObj($editClass, false);
189 if (is_object($edit)) {
190 $allowedActions = $this->getAllowedEditActions($table, $conf, $dataArray['pid']);
191 $content = $edit->editPanel($content, $conf, $currentRecord, $dataArray, $table, $allowedActions, $newUid, $this->getHiddenFields($dataArray));
192 }
193 }
194 }
195
196 return $content;
197 }
198
199 /**
200 * Adds an edit icon to the content string. The edit icon links to alt_doc.php with proper parameters for editing the table/fields of the context.
201 * This implements TYPO3 context sensitive editing facilities. Only backend users will have access (if properly configured as well).
202 *
203 * @param string The content to which the edit icons should be appended
204 * @param string The parameters defining which table and fields to edit. Syntax is [tablename]:[fieldname],[fieldname],[fieldname],... OR [fieldname],[fieldname],[fieldname],... (basically "[tablename]:" is optional, default table is the one of the "current record" used in the function). The fieldlist is sent as "&columnsOnly=" parameter to alt_doc.php
205 * @param array TypoScript properties for configuring the edit icons.
206 * @param string The "table:uid" of the record being shown. If empty string then $this->currentRecord is used. For new records (set by $conf['newRecordFromTable']) it's auto-generated to "[tablename]:NEW"
207 * @param array Alternative data array to use. Default is $this->data
208 * @param string Additional URL parameters for the link pointing to alt_doc.php
209 * @return string The input content string, possibly with edit icons added (not necessarily in the end but just after the last string of normal content.
210 */
211
212 public function displayEditIcons($content, $params, array $conf=array(), $currentRecord = '', array $dataArray = array(), $addUrlParamStr = '') {
213 // Check incoming params:
214 list($currentRecordTable, $currentRecordUID) = explode(':', $currentRecord);
215 list($fieldList, $table) = array_reverse(t3lib_div::trimExplode(':', $params, 1)); // Reverse the array because table is optional
216 if (!$table) {
217 $table = $currentRecordTable;
218 } elseif ($table != $currentRecordTable) {
219 return $content; // If the table is set as the first parameter, and does not match the table of the current record, then just return.
220 }
221
222 $editUid = $dataArray['_LOCALIZED_UID'] ? $dataArray['_LOCALIZED_UID'] : $currentRecordUID;
223
224 // Edit icons imply that the editing action is generally allowed, assuming page and content element permissions permit it.
225 if (!array_key_exists('allow', $conf)) {
226 $conf['allow'] = 'edit';
227 }
228
229 if ($GLOBALS['TSFE']->displayFieldEditIcons && $table && $this->allowedToEdit($table, $dataArray, $conf) && $fieldList && $this->allowedToEditLanguage($table, $dataArray)) {
230 $editClass = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/classes/class.frontendedit.php']['edit'];
231 if ($editClass) {
232 $edit = &t3lib_div::getUserObj($editClass);
233 if (is_object($edit)) {
234 $content = $edit->editIcons($content, $params, $conf, $currentRecord, $dataArray, $addURLParamStr, $table, $editUid, $fieldList);
235 }
236 }
237 }
238
239 return $content;
240 }
241
242 /**
243 * Checks if a Admin Panel section ("module") is available for the user. If so, true is returned.
244 *
245 * @param string The module key, eg. "edit", "preview", "info" etc.
246 * @return boolean
247 */
248 public function isAdminModuleEnabled($key) {
249 // Returns true if the module checked is "preview" and the forcePreview flag is set.
250 if ($key=='preview' && $this->ext_forcePreview) {
251 return true;
252 }
253
254 // If key is not set, only "all" is checked
255 if ($GLOBALS['BE_USER']->extAdminConfig['enable.']['all']) {
256 return true;
257 }
258
259 if ($GLOBALS['BE_USER']->extAdminConfig['enable.'][$key]) {
260 return true;
261 }
262 }
263
264 /**
265 * Saves any change in settings made in the Admin Panel.
266 * Called from index_ts.php right after access check for the Admin Panel
267 *
268 * @return void
269 */
270 public function saveConfigOptions() {
271 $input = t3lib_div::_GP('TSFE_ADMIN_PANEL');
272 if (is_array($input)) {
273 // Setting
274 $GLOBALS['BE_USER']->uc['TSFE_adminConfig'] = array_merge(!is_array($GLOBALS['BE_USER']->uc['TSFE_adminConfig']) ? array() : $GLOBALS['BE_USER']->uc['TSFE_adminConfig'], $input); // Candidate for t3lib_div::array_merge() if integer-keys will some day make trouble...
275 unset($GLOBALS['BE_USER']->uc['TSFE_adminConfig']['action']);
276
277 // Actions:
278 if ($input['action']['clearCache'] && $this->isAdminModuleEnabled('cache')) {
279 $GLOBALS['BE_USER']->extPageInTreeInfo=array();
280 $theStartId = intval($input['cache_clearCacheId']);
281 $GLOBALS['TSFE']->clearPageCacheContent_pidList($GLOBALS['BE_USER']->extGetTreeList($theStartId, $this->extGetFeAdminValue('cache', 'clearCacheLevels'), 0, $GLOBALS['BE_USER']->getPagePermsClause(1)) . $theStartId);
282 }
283 if ($input['action']['publish'] && $this->isAdminModuleEnabled('publish')) {
284 $theStartId = intval($input['publish_id']);
285 $this->extPublishList = $GLOBALS['BE_USER']->extGetTreeList($theStartId, $this->extGetFeAdminValue('publish', 'levels'), 0, $GLOBALS['BE_USER']->getPagePermsClause(1)) . $theStartId;
286 }
287
288 // Saving
289 $GLOBALS['BE_USER']->writeUC();
290 }
291 $GLOBALS['TT']->LR = $this->extGetFeAdminValue('tsdebug', 'LR');
292
293 if ($this->extGetFeAdminValue('cache', 'noCache')) {
294 $GLOBALS['TSFE']->set_no_cache();
295 }
296
297 // Hook for post processing the frontend admin configuration. Added with TYPO3 4.2, so naming is now incorrect but preserves compatibility.
298 // @deprecated since TYPO3 4.3
299 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['extSaveFeAdminConfig-postProc'])) {
300 $_params = array('input' => &$input, 'pObj' => &$this);
301 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['extSaveFeAdminConfig-postProc'] as $_funcRef) {
302 t3lib_div::callUserFunction($_funcRef, $_params, $this);
303 }
304 }
305 }
306
307 /**
308 * Returns the value for a Admin Panel setting. You must specify both the module-key and the internal setting key.
309 *
310 * @param string Module key
311 * @param string Setting key
312 * @return string The setting value
313 */
314 public function extGetFeAdminValue($pre, $val='') {
315 // Check if module is enabled.
316 if ($this->isAdminModuleEnabled($pre)) {
317 // Exceptions where the values can be overridden from backend:
318 // deprecated
319 if ($pre . '_' . $val == 'edit_displayIcons' && $GLOBALS['BE_USER']->extAdminConfig['module.']['edit.']['forceDisplayIcons']) {
320 return true;
321 }
322 if ($pre . '_' . $val == 'edit_displayFieldIcons' && $GLOBALS['BE_USER']->extAdminConfig['module.']['edit.']['forceDisplayFieldIcons']) {
323 return true;
324 }
325
326 // override all settings with user TSconfig
327 if ($GLOBALS['BE_USER']->extAdminConfig['override.'][$pre . '.'][$val] && $val) {
328 return $GLOBALS['BE_USER']->extAdminConfig['override.'][$pre . '.'][$val];
329 }
330 if ($GLOBALS['BE_USER']->extAdminConfig['override.'][$pre]) {
331 return $GLOBALS['BE_USER']->extAdminConfig['override.'][$pre];
332 }
333
334 $retVal = $val ? $GLOBALS['BE_USER']->uc['TSFE_adminConfig'][$pre . '_' . $val] : 1;
335
336 if ($pre=='preview' && $this->ext_forcePreview) {
337 if (!$val) {
338 return true;
339 } else {
340 return $retVal;
341 }
342 }
343 // regular check:
344 if ($this->isAdminModuleOpen($pre)) { // See if the menu is expanded!
345 return $retVal;
346 }
347
348 // Hook for post processing the frontend admin configuration. Added with TYPO3 4.2, so naming is now incorrect but preserves compatibility.
349 // @deprecated since TYPO3 4.3
350 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['extEditAction-postProc'])) {
351 $_params = array('cmd' => &$cmd, 'tce' => &$this->tce, 'pObj' => &$this);
352 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['extEditAction-postProc'] as $_funcRef) {
353 t3lib_div::callUserFunction($_funcRef, $_params, $this);
354 }
355 }
356 }
357 }
358
359 /**
360 * Enables the force preview option.
361 *
362 * @return void
363 */
364 public function forcePreview() {
365 $this->ext_forcePreview = true;
366 }
367
368 /**
369 * Returns the comma-separated list of page UIDs to be published.
370 *
371 * @return string
372 */
373 public function getExtPublishList() {
374 return $this->extPublishList;
375 }
376
377 /**
378 * Returns true if admin panel module is open
379 *
380 * @param string Module key
381 * @return boolean True, if the admin panel is open for the specified admin panel module key.
382 */
383 public function isAdminModuleOpen($pre) {
384 return $GLOBALS['BE_USER']->uc['TSFE_adminConfig']['display_top'] && $GLOBALS['BE_USER']->uc['TSFE_adminConfig']['display_' . $pre];
385 }
386
387 /*****************************************************
388 *
389 * Frontend Editing
390 *
391 ****************************************************/
392
393 /**
394 * Returns true if an edit-action is sent from the Admin Panel
395 *
396 * @return boolean
397 * @see index_ts.php
398 */
399 public function isEditAction() {
400 if (is_array($this->TSFE_EDIT)) {
401 if ($this->TSFE_EDIT['cancel']) {
402 unset($this->TSFE_EDIT['cmd']);
403 } else {
404 $cmd = (string) $this->TSFE_EDIT['cmd'];
405 if (($cmd != 'edit' || (is_array($this->TSFE_EDIT['data']) && ($this->TSFE_EDIT['doSave'] || $this->TSFE_EDIT['update'] || $this->TSFE_EDIT['update_close']))) && $cmd != 'new') {
406 // $cmd can be a command like "hide" or "move". If $cmd is "edit" or "new" it's an indication to show the formfields. But if data is sent with update-flag then $cmd = edit is accepted because edit may be sent because of .keepGoing flag.
407 return true;
408 }
409 }
410 }
411 return false;
412 }
413
414 /**
415 * Returns true if an edit form is shown on the page.
416 * Used from index_ts.php where a true return-value will result in classes etc. being included.
417 *
418 * @return boolean
419 * @see index_ts.php
420 */
421 public function isEditFormShown() {
422 if (is_array($this->TSFE_EDIT)) {
423 $cmd = (string) $this->TSFE_EDIT['cmd'];
424 if ($cmd == 'edit' || $cmd == 'new') {
425 return true;
426 }
427 }
428 }
429
430 /**
431 * Management of the on-page frontend editing forms and edit panels.
432 * Basically taking in the data and commands and passes them on to the proper classes as they should be.
433 *
434 * @return void
435 * @throws UnexpectedValueException if TSFE_EDIT[cmd] is not a valid command
436 * @see index_ts.php
437 */
438 public function editAction() {
439 // Commands:
440 list($table, $uid) = explode(':', $this->TSFE_EDIT['record']);
441 $cmd = $this->TSFE_EDIT['cmd'];
442
443 // Look for some TSFE_EDIT data that indicates we should save.
444 if (($this->TSFE_EDIT['doSave'] || $this->TSFE_EDIT['update'] || $this->TSFE_EDIT['update_close']) && is_array($this->TSFE_EDIT['data'])) {
445 $cmd = 'save';
446 }
447
448 if (($cmd == 'save') || ($cmd && $table && $uid && isset($GLOBALS['TCA'][$table]))) {
449 // Hook for defining custom editing actions. Naming is incorrect, but preserves compatibility.
450 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['extEditAction'])) {
451 $_params = array();
452 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['extEditAction'] as $_funcRef) {
453 t3lib_div::callUserFunction($_funcRef, $_params, $this);
454 }
455 }
456
457 // Perform the requested editing command.
458 $cmdAction = 'do' . ucwords($cmd);
459 if (is_callable(array($this, $cmdAction))) {
460 $this->$cmdAction($table, $uid);
461 } else {
462 throw new UnexpectedValueException(
463 'The specified frontend edit command (' . $cmd . ') is not valid.',
464 1225818120
465 );
466 }
467 }
468 }
469
470 /**
471 * Hides a specific record.
472 *
473 * @param string The table name for the record to hide.
474 * @param integer The UID for the record to hide.
475 * @return void
476 */
477 public function doHide($table, $uid) {
478 $hideField = $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['disabled'];
479 if ($hideField) {
480 $recData = array();
481 $recData[$table][$uid][$hideField] = 1;
482 $this->tce->start($recData, array());
483 $this->tce->process_datamap();
484 }
485 }
486
487 /**
488 * Unhides (shows) a specific record.
489 *
490 * @param string The table name for the record to unhide.
491 * @param integer The UID for the record to unhide.
492 * @return void
493 */
494 public function doUnhide($table, $uid) {
495 $hideField = $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['disabled'];
496 if ($hideField) {
497 $recData = array();
498 $recData[$table][$uid][$hideField] = 0;
499 $this->tce->start($recData, array());
500 $this->tce->process_datamap();
501 }
502 }
503
504 /**
505 * Moves a record up.
506 *
507 * @param string The table name for the record to move.
508 * @param integer The UID for the record to hide.
509 * @return void
510 */
511 public function doUp($table, $uid) {
512 $this->move($table, $uid, 'up');
513 }
514
515 /**
516 * Moves a record down.
517 *
518 * @param string The table name for the record to move.
519 * @param integer The UID for the record to move.
520 * @return void
521 */
522 public function doDown($table, $uid) {
523 $this->move($table, $uid, 'down');
524 }
525
526 /**
527 * Moves a record after a given element. Used for drag.
528 *
529 * @param string The table name for the record to move.
530 * @param integer The UID for the record to move.
531 * @return void
532 */
533 public function doMoveAfter($table, $uid) {
534 $afterUID = $GLOBALS['BE_USER']->frontendEdit->TSFE_EDIT['moveAfter'];
535 $this->move($table, $uid, '', $afterUID);
536 }
537
538 /**
539 * Moves a record
540 *
541 * @param string The table name for the record to move.
542 * @param integer The UID for the record to move.
543 * @param string The direction to move, either 'up' or 'down'.
544 * @param integer The UID of record to move after. This is specified for dragging only.
545 * @return void
546 */
547 protected function move($table, $uid, $direction='', $afterUID=0) {
548 $cmdData = array();
549 $sortField = $GLOBALS['TCA'][$table]['ctrl']['sortby'];
550 if ($sortField) {
551 // Get self:
552 $fields = array_unique(t3lib_div::trimExplode(',', $GLOBALS['TCA'][$table]['ctrl']['copyAfterDuplFields'] . ',uid,pid,' . $sortField, true));
553 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(implode(',', $fields), $table, 'uid=' . $uid);
554 if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
555 // record before or after
556 $preview = $this->extGetFeAdminValue('preview');
557 $copyAfterFieldsQuery = '';
558 if ($preview) {
559 $ignore = array('starttime'=>1, 'endtime'=>1, 'disabled'=>1, 'fe_group'=>1);
560 }
561 if ($GLOBALS['TCA'][$table]['ctrl']['copyAfterDuplFields']) {
562 $cAFields = t3lib_div::trimExplode(',', $GLOBALS['TCA'][$table]['ctrl']['copyAfterDuplFields'], true);
563 foreach($cAFields as $fieldName) {
564 $copyAfterFieldsQuery .= ' AND ' . $fieldName . '="' . $row[$fieldName] . '"';
565 }
566 }
567 if (!empty($direction)) {
568 if ($direction == 'up') {
569 $operator = '<';
570 $order = 'DESC';
571 } else {
572 $operator = '>';
573 $order = 'ASC';
574 }
575 $sortCheck = ' AND ' . $sortField . $operator . intval($row[$sortField]);
576 }
577 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
578 'uid,pid',
579 $table,
580 'pid=' . intval($row['pid']) .
581 $sortCheck .
582 $copyAfterFieldsQuery .
583 $GLOBALS['TSFE']->sys_page->enableFields($table, '', $ignore),
584 '',
585 $sortField . ' ' . $order,
586 '2'
587 );
588 if ($row2 = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
589 if ($afterUID) {
590 $cmdData[$table][$uid]['move'] = -$afterUID;
591 }
592 elseif ($direction == 'down') {
593 $cmdData[$table][$uid]['move'] = -$row2['uid'];
594 }
595 elseif ($row3 = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { // Must take the second record above...
596 $cmdData[$table][$uid]['move'] = -$row3['uid'];
597 }
598 else { // ... and if that does not exist, use pid
599 $cmdData[$table][$uid]['move'] = $row['pid'];
600 }
601 } elseif ($direction == 'up') {
602 $cmdData[$table][$uid]['move'] = $row['pid'];
603 }
604 }
605 if (!empty($cmdData)) {
606 $this->tce->start(array(), $cmdData);
607 $this->tce->process_cmdmap();
608 }
609 }
610 }
611
612 /**
613 * Deletes a specific record.
614 *
615 * @param string The table name for the record to delete.
616 * @param integer The UID for the record to delete.
617 * @return void
618 */
619 public function doDelete($table, $uid) {
620 $cmdData[$table][$uid]['delete'] = 1;
621 if (count($cmdData)) {
622 $this->tce->start(array(), $cmdData);
623 $this->tce->process_cmdmap();
624 }
625 }
626
627 /**
628 * Saves a record based on its data array.
629 *
630 * @param string The table name for the record to save.
631 * @param integer The UID for the record to save.
632 * @return void
633 */
634 public function doSave($table, $uid) {
635 $data = $this->TSFE_EDIT['data'];
636
637 if (!empty($data)) {
638 $this->tce->start($data, array());
639 $this->tce->process_uploads($_FILES);
640 $this->tce->process_datamap();
641
642 // Save the new UID back into TSFE_EDIT
643 $newUID = $this->tce->substNEWwithIDs['NEW'];
644 if ($newUID) {
645 $GLOBALS['BE_USER']->frontendEdit->TSFE_EDIT['newUID'] = $newUID;
646 }
647 }
648 }
649
650 /**
651 * Stub for closing a record. No real functionality needed since content
652 * element rendering will take care of everything.
653 *
654 * @param string The table name for the record to close.
655 * @param integer The UID for the record to close.
656 * @return void
657 */
658 public function doClose($table, $uid) {
659 // Do nothing.
660 }
661
662 /**
663 * Checks whether the user has access to edit the language for the
664 * requested record.
665 *
666 * @param string The name of the table.
667 * @param array The record.
668 * @return boolean
669 */
670 protected function allowedToEditLanguage($table, array $currentRecord) {
671 // If no access right to record languages, return immediately
672 if ($table === 'pages') {
673 $lang = $GLOBALS['TSFE']->sys_language_uid;
674 } elseif ($table === 'tt_content') {
675 $lang = $GLOBALS['TSFE']->sys_language_content;
676 } elseif ($GLOBALS['TCA'][$table]['ctrl']['languageField']) {
677 $lang = $currentRecord[$GLOBALS['TCA'][$table]['ctrl']['languageField']];
678 } else {
679 $lang = -1;
680 }
681
682 if ($GLOBALS['BE_USER']->checkLanguageAccess($lang)) {
683 $languageAccess = true;
684 } else {
685 $languageAccess = false;
686 }
687
688 return $languageAccess;
689 }
690
691 /**
692 * Checks whether the user is allowed to edit the requested table.
693 *
694 * @param string The name of the table.
695 * @param array The data array.
696 * @param array The configuration array for the edit panel.
697 * @return boolean
698 */
699 protected function allowedToEdit($table, array $dataArray, array $conf) {
700
701 // Unless permissions specifically allow it, editing is not allowed.
702 $mayEdit = false;
703
704 if ($table=='pages') {
705 // 2 = permission to edit the page
706 if ($GLOBALS['BE_USER']->isAdmin() || $GLOBALS['BE_USER']->doesUserHaveAccess($dataArray, 2)) {
707 $mayEdit = true;
708 }
709 } else {
710 // 16 = permission to edit content on the page
711 if ($GLOBALS['BE_USER']->isAdmin() || $GLOBALS['BE_USER']->doesUserHaveAccess(t3lib_BEfunc::getRecord('pages', $dataArray['pid']), 16)) {
712 $mayEdit = true;
713 }
714 }
715
716 if (!$conf['onlyCurrentPid'] || ($dataArray['pid'] == $GLOBALS['TSFE']->id)) {
717 // Permissions:
718 $types = t3lib_div::trimExplode(',', t3lib_div::strtolower($conf['allow']),1);
719 $allow = array_flip($types);
720
721 $perms = $GLOBALS['BE_USER']->calcPerms($GLOBALS['TSFE']->page);
722 if ($table == 'pages') {
723 $allow = $this->getAllowedEditActions($table, $conf, $dataArray['pid'], $allow);
724
725 // Can only display editbox if there are options in the menu
726 if (count($allow)) {
727 $mayEdit = true;
728 }
729 } else {
730 $mayEdit = count($allow) && ($perms & 16);
731 }
732 }
733
734 return $mayEdit;
735 }
736
737 /**
738 * Takes an array of generally allowed actions and filters that list based on page and content permissions.
739 *
740 * @param string The name of the table.
741 * @param array The configuration array.
742 * @param integer The PID where editing will occur.
743 * @param string Comma-separated list of actions that are allowed in general.
744 * @return array
745 */
746 protected function getAllowedEditActions($table, array $conf, $pid, $allow = '') {
747
748 if (!$allow) {
749 $types = t3lib_div::trimExplode(',', t3lib_div::strtolower($conf['allow']), true);
750 $allow = array_flip($types);
751 }
752
753 if (!$conf['onlyCurrentPid'] || $pid == $GLOBALS['TSFE']->id) {
754 // Permissions:
755 $types = t3lib_div::trimExplode(',', t3lib_div::strtolower($conf['allow']), true);
756 $allow = array_flip($types);
757
758 $perms = $GLOBALS['BE_USER']->calcPerms($GLOBALS['TSFE']->page);
759 if ($table=='pages') {
760 // rootpage!
761 if (count($GLOBALS['TSFE']->config['rootLine']) == 1) {
762 unset($allow['move']);
763 unset($allow['hide']);
764 unset($allow['delete']);
765 }
766 if (!($perms & 2)){
767 unset($allow['edit']);
768 unset($allow['move']);
769 unset($allow['hide']);
770 }
771 if (!($perms & 4)) {
772 unset($allow['delete']);
773 }
774 if (!($perms&8)) {
775 unset($allow['new']);
776 }
777 }
778 }
779
780 return $allow;
781 }
782
783 /**
784 * Adds any extra Javascript includes needed for Front-end editing
785 *
786 * @param none
787 * @return string
788 */
789 public function getJavascriptIncludes() {
790 // No extra JS includes needed
791 return '';
792 }
793
794 /**
795 * Gets the hidden fields (array key=field name, value=field value) to be used in the edit panel for a particular content element.
796 * In the normal case, no hidden fields are needed but special controllers such as TemplaVoila need to track flexform pointers, etc.
797 *
798 * @param array The data array for a specific content element.
799 * @return array
800 */
801 public function getHiddenFields(array $dataArray) {
802 // No special hidden fields needed.
803 return array();
804 }
805 }
806
807 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_frontendedit.php']) {
808 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_frontendedit.php']);
809 }
810
811 ?>