TYPO3 CMS  TYPO3_7-6
FrontendEditingController.php
Go to the documentation of this file.
1 <?php
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
19 
24 {
31  public $TSFE_EDIT;
32 
36  protected $tce;
37 
43  public function initConfigOptions()
44  {
45  $this->TSFE_EDIT = GeneralUtility::_GP('TSFE_EDIT');
46  // Include classes for editing IF editing module in Admin Panel is open
47  if ($GLOBALS['BE_USER']->isFrontendEditingActive()) {
48  if ($this->isEditAction()) {
49  $this->editAction();
50  }
51  }
52  }
53 
65  public function displayEditPanel($content, array $conf, $currentRecord, array $dataArray)
66  {
67  if ($conf['newRecordFromTable']) {
68  $currentRecord = $conf['newRecordFromTable'] . ':NEW';
69  $conf['allow'] = 'new';
70  $checkEditAccessInternals = false;
71  } else {
72  $checkEditAccessInternals = true;
73  }
74  list($table, $uid) = explode(':', $currentRecord);
75  // Page ID for new records, 0 if not specified
76  $newRecordPid = (int)$conf['newRecordInPid'];
77  if (!$conf['onlyCurrentPid'] || $dataArray['pid'] == $GLOBALS['TSFE']->id) {
78  if ($table == 'pages') {
79  $newUid = $uid;
80  } else {
81  if ($conf['newRecordFromTable']) {
82  $newUid = $GLOBALS['TSFE']->id;
83  if ($newRecordPid) {
84  $newUid = $newRecordPid;
85  }
86  } else {
87  $newUid = -1 * $uid;
88  }
89  }
90  }
91  if ($GLOBALS['TSFE']->displayEditIcons && $table && $this->allowedToEdit($table, $dataArray, $conf, $checkEditAccessInternals) && $this->allowedToEditLanguage($table, $dataArray)) {
92  $editClass = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/classes/class.frontendedit.php']['edit'];
93  if ($editClass) {
94  $edit = GeneralUtility::getUserObj($editClass);
95  if (is_object($edit)) {
96  $allowedActions = $this->getAllowedEditActions($table, $conf, $dataArray['pid']);
97  $content = $edit->editPanel($content, $conf, $currentRecord, $dataArray, $table, $allowedActions, $newUid, $this->getHiddenFields($dataArray));
98  }
99  }
100  }
101  return $content;
102  }
103 
116  public function displayEditIcons($content, $params, array $conf = [], $currentRecord = '', array $dataArray = [], $addUrlParamStr = '')
117  {
118  // Check incoming params:
119  list($currentRecordTable, $currentRecordUID) = explode(':', $currentRecord);
120  list($fieldList, $table) = array_reverse(GeneralUtility::trimExplode(':', $params, true));
121  // Reverse the array because table is optional
122  if (!$table) {
123  $table = $currentRecordTable;
124  } elseif ($table != $currentRecordTable) {
125  // If the table is set as the first parameter, and does not match the table of the current record, then just return.
126  return $content;
127  }
128  $editUid = $dataArray['_LOCALIZED_UID'] ?: $currentRecordUID;
129  // Edit icons imply that the editing action is generally allowed, assuming page and content element permissions permit it.
130  if (!array_key_exists('allow', $conf)) {
131  $conf['allow'] = 'edit';
132  }
133  if ($GLOBALS['TSFE']->displayFieldEditIcons && $table && $this->allowedToEdit($table, $dataArray, $conf) && $fieldList && $this->allowedToEditLanguage($table, $dataArray)) {
134  $editClass = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/classes/class.frontendedit.php']['edit'];
135  if ($editClass) {
136  $edit = GeneralUtility::getUserObj($editClass);
137  if (is_object($edit)) {
138  $content = $edit->editIcons($content, $params, $conf, $currentRecord, $dataArray, $addUrlParamStr, $table, $editUid, $fieldList);
139  }
140  }
141  }
142  return $content;
143  }
144 
145  /*****************************************************
146  *
147  * Frontend Editing
148  *
149  ****************************************************/
156  public function isEditAction()
157  {
158  if (is_array($this->TSFE_EDIT)) {
159  if ($this->TSFE_EDIT['cancel']) {
160  unset($this->TSFE_EDIT['cmd']);
161  } else {
162  $cmd = (string)$this->TSFE_EDIT['cmd'];
163  if (($cmd != 'edit' || is_array($this->TSFE_EDIT['data']) && ($this->TSFE_EDIT['doSave'] || $this->TSFE_EDIT['update'] || $this->TSFE_EDIT['update_close'])) && $cmd != 'new') {
164  // $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.
165  return true;
166  }
167  }
168  }
169  return false;
170  }
171 
179  public function isEditFormShown()
180  {
181  if (is_array($this->TSFE_EDIT)) {
182  $cmd = (string)$this->TSFE_EDIT['cmd'];
183  if ($cmd == 'edit' || $cmd == 'new') {
184  return true;
185  }
186  }
187  }
188 
197  public function editAction()
198  {
199  // Commands
200  list($table, $uid) = explode(':', $this->TSFE_EDIT['record']);
201  $uid = (int)$uid;
202  $cmd = $this->TSFE_EDIT['cmd'];
203  // Look for some TSFE_EDIT data that indicates we should save.
204  if (($this->TSFE_EDIT['doSave'] || $this->TSFE_EDIT['update'] || $this->TSFE_EDIT['update_close']) && is_array($this->TSFE_EDIT['data'])) {
205  $cmd = 'save';
206  }
207  if ($cmd == 'save' || $cmd && $table && $uid && isset($GLOBALS['TCA'][$table])) {
208  // Hook for defining custom editing actions. Naming is incorrect, but preserves compatibility.
209  if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['extEditAction'])) {
210  $_params = [];
211  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['extEditAction'] as $_funcRef) {
212  GeneralUtility::callUserFunction($_funcRef, $_params, $this);
213  }
214  }
215  // Perform the requested editing command.
216  $cmdAction = 'do' . ucwords($cmd);
217  if (is_callable([$this, $cmdAction])) {
218  $this->{$cmdAction}($table, $uid);
219  } else {
220  throw new \UnexpectedValueException('The specified frontend edit command (' . $cmd . ') is not valid.', 1225818120);
221  }
222  }
223  }
224 
232  public function doHide($table, $uid)
233  {
234  $hideField = $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['disabled'];
235  if ($hideField) {
236  $recData = [];
237  $recData[$table][$uid][$hideField] = 1;
238  $this->initializeTceMain();
239  $this->tce->start($recData, []);
240  $this->tce->process_datamap();
241  }
242  }
243 
251  public function doUnhide($table, $uid)
252  {
253  $hideField = $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['disabled'];
254  if ($hideField) {
255  $recData = [];
256  $recData[$table][$uid][$hideField] = 0;
257  $this->initializeTceMain();
258  $this->tce->start($recData, []);
259  $this->tce->process_datamap();
260  }
261  }
262 
270  public function doUp($table, $uid)
271  {
272  $this->move($table, $uid, 'up');
273  }
274 
282  public function doDown($table, $uid)
283  {
284  $this->move($table, $uid, 'down');
285  }
286 
294  public function doMoveAfter($table, $uid)
295  {
296  $afterUID = $GLOBALS['BE_USER']->frontendEdit->TSFE_EDIT['moveAfter'];
297  $this->move($table, $uid, '', $afterUID);
298  }
299 
309  protected function move($table, $uid, $direction = '', $afterUID = 0)
310  {
311  $cmdData = [];
312  $sortField = $GLOBALS['TCA'][$table]['ctrl']['sortby'];
313  if ($sortField) {
314  // Get self
315  $fields = array_unique(GeneralUtility::trimExplode(',', $GLOBALS['TCA'][$table]['ctrl']['copyAfterDuplFields'] . ',uid,pid,' . $sortField, true));
316  $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(implode(',', $fields), $table, 'uid=' . $uid);
317  if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
318  // Record before or after
319  if ($GLOBALS['BE_USER']->adminPanel instanceof \TYPO3\CMS\Frontend\View\AdminPanelView && $GLOBALS['BE_USER']->adminPanel->extGetFeAdminValue('preview')) {
320  $ignore = ['starttime' => 1, 'endtime' => 1, 'disabled' => 1, 'fe_group' => 1];
321  }
322  $copyAfterFieldsQuery = '';
323  if ($GLOBALS['TCA'][$table]['ctrl']['copyAfterDuplFields']) {
324  $cAFields = GeneralUtility::trimExplode(',', $GLOBALS['TCA'][$table]['ctrl']['copyAfterDuplFields'], true);
325  foreach ($cAFields as $fieldName) {
326  $copyAfterFieldsQuery .= ' AND ' . $fieldName . '="' . $row[$fieldName] . '"';
327  }
328  }
329  if (!empty($direction)) {
330  if ($direction == 'up') {
331  $operator = '<';
332  $order = 'DESC';
333  } else {
334  $operator = '>';
335  $order = 'ASC';
336  }
337  $sortCheck = ' AND ' . $sortField . $operator . (int)$row[$sortField];
338  }
339  $GLOBALS['TYPO3_DB']->sql_free_result($res);
340  $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid,pid', $table, 'pid=' . (int)$row['pid'] . $sortCheck . $copyAfterFieldsQuery . $GLOBALS['TSFE']->sys_page->enableFields($table, '', $ignore), '', $sortField . ' ' . $order, '2');
341  if ($row2 = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
342  if ($afterUID) {
343  $cmdData[$table][$uid]['move'] = -$afterUID;
344  } elseif ($direction == 'down') {
345  $cmdData[$table][$uid]['move'] = -$row2['uid'];
346  } elseif ($row3 = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
347  // Must take the second record above...
348  $cmdData[$table][$uid]['move'] = -$row3['uid'];
349  } else {
350  // ... and if that does not exist, use pid
351  $cmdData[$table][$uid]['move'] = $row['pid'];
352  }
353  } elseif ($direction == 'up') {
354  $cmdData[$table][$uid]['move'] = $row['pid'];
355  }
356  $GLOBALS['TYPO3_DB']->sql_free_result($res);
357  }
358  if (!empty($cmdData)) {
359  $this->initializeTceMain();
360  $this->tce->start([], $cmdData);
361  $this->tce->process_cmdmap();
362  }
363  }
364  }
365 
373  public function doDelete($table, $uid)
374  {
375  $cmdData[$table][$uid]['delete'] = 1;
376  if (!empty($cmdData)) {
377  $this->initializeTceMain();
378  $this->tce->start([], $cmdData);
379  $this->tce->process_cmdmap();
380  }
381  }
382 
390  public function doSave($table, $uid)
391  {
392  $data = $this->TSFE_EDIT['data'];
393  if (!empty($data)) {
394  $this->initializeTceMain();
395  $this->tce->start($data, []);
396  $this->tce->process_uploads($_FILES);
397  $this->tce->process_datamap();
398  // Save the new UID back into TSFE_EDIT
399  $newUID = $this->tce->substNEWwithIDs['NEW'];
400  if ($newUID) {
401  $GLOBALS['BE_USER']->frontendEdit->TSFE_EDIT['newUID'] = $newUID;
402  }
403  }
404  }
405 
414  public function doSaveAndClose($table, $uid)
415  {
416  $this->doSave($table, $uid);
417  }
418 
427  public function doClose($table, $uid)
428  {
429  }
430 
439  protected function allowedToEditLanguage($table, array $currentRecord)
440  {
441  // If no access right to record languages, return immediately
442  if ($table === 'pages') {
443  $lang = $GLOBALS['TSFE']->sys_language_uid;
444  } elseif ($table === 'tt_content') {
445  $lang = $GLOBALS['TSFE']->sys_language_content;
446  } elseif ($GLOBALS['TCA'][$table]['ctrl']['languageField']) {
447  $lang = $currentRecord[$GLOBALS['TCA'][$table]['ctrl']['languageField']];
448  } else {
449  $lang = -1;
450  }
451  if ($GLOBALS['BE_USER']->checkLanguageAccess($lang)) {
452  $languageAccess = true;
453  } else {
454  $languageAccess = false;
455  }
456  return $languageAccess;
457  }
458 
468  protected function allowedToEdit($table, array $dataArray, array $conf, $checkEditAccessInternals = true)
469  {
470  // Unless permissions specifically allow it, editing is not allowed.
471  $mayEdit = false;
472  if ($checkEditAccessInternals) {
473  $editAccessInternals = $GLOBALS['BE_USER']->recordEditAccessInternals($table, $dataArray, false, false);
474  } else {
475  $editAccessInternals = true;
476  }
477  if ($editAccessInternals) {
478  if ($table == 'pages') {
479  // 2 = permission to edit the page
480  if ($GLOBALS['BE_USER']->isAdmin() || $GLOBALS['BE_USER']->doesUserHaveAccess($dataArray, 2)) {
481  $mayEdit = true;
482  }
483  } else {
484  // 16 = permission to edit content on the page
485  if ($GLOBALS['BE_USER']->isAdmin() || $GLOBALS['BE_USER']->doesUserHaveAccess(\TYPO3\CMS\Backend\Utility\BackendUtility::getRecord('pages', $dataArray['pid']), 16)) {
486  $mayEdit = true;
487  }
488  }
489  if (!$conf['onlyCurrentPid'] || $dataArray['pid'] == $GLOBALS['TSFE']->id) {
490  // Permissions:
491  $types = GeneralUtility::trimExplode(',', GeneralUtility::strtolower($conf['allow']), true);
492  $allow = array_flip($types);
493  $perms = $GLOBALS['BE_USER']->calcPerms($GLOBALS['TSFE']->page);
494  if ($table == 'pages') {
495  $allow = $this->getAllowedEditActions($table, $conf, $dataArray['pid'], $allow);
496  // Can only display editbox if there are options in the menu
497  if (!empty($allow)) {
498  $mayEdit = true;
499  }
500  } else {
501  $mayEdit = !empty($allow) && $perms & Permission::CONTENT_EDIT;
502  }
503  }
504  }
505  return $mayEdit;
506  }
507 
517  protected function getAllowedEditActions($table, array $conf, $pid, $allow = '')
518  {
519  if (!$allow) {
520  $types = GeneralUtility::trimExplode(',', GeneralUtility::strtolower($conf['allow']), true);
521  $allow = array_flip($types);
522  }
523  if (!$conf['onlyCurrentPid'] || $pid == $GLOBALS['TSFE']->id) {
524  // Permissions
525  $types = GeneralUtility::trimExplode(',', GeneralUtility::strtolower($conf['allow']), true);
526  $allow = array_flip($types);
527  $perms = $GLOBALS['BE_USER']->calcPerms($GLOBALS['TSFE']->page);
528  if ($table == 'pages') {
529  // Rootpage
530  if (count($GLOBALS['TSFE']->config['rootLine']) === 1) {
531  unset($allow['move']);
532  unset($allow['hide']);
533  unset($allow['delete']);
534  }
535  if (!($perms & Permission::PAGE_EDIT) || !$GLOBALS['BE_USER']->checkLanguageAccess(0)) {
536  unset($allow['edit']);
537  unset($allow['move']);
538  unset($allow['hide']);
539  }
540  if (!($perms & Permission::PAGE_DELETE)) {
541  unset($allow['delete']);
542  }
543  if (!($perms & Permission::PAGE_NEW)) {
544  unset($allow['new']);
545  }
546  }
547  }
548  return $allow;
549  }
550 
556  public function getJavascriptIncludes()
557  {
558  // No extra JS includes needed
559  return '';
560  }
561 
569  public function getHiddenFields(array $dataArray)
570  {
571  // No special hidden fields needed.
572  return [];
573  }
574 
580  protected function initializeTceMain()
581  {
582  if (!isset($this->tce)) {
583  $this->tce = GeneralUtility::makeInstance(\TYPO3\CMS\Core\DataHandling\DataHandler::class);
584  $this->tce->stripslashes_values = 0;
585  }
586  }
587 }
displayEditIcons($content, $params, array $conf=[], $currentRecord='', array $dataArray=[], $addUrlParamStr='')
displayEditPanel($content, array $conf, $currentRecord, array $dataArray)
static trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
static callUserFunction($funcName, &$params, &$ref, $checkPrefix='', $errorMode=0)
allowedToEdit($table, array $dataArray, array $conf, $checkEditAccessInternals=true)
$uid
Definition: server.php:38
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']