TYPO3 CMS  TYPO3_7-6
ExtDirectServer.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 
23 
28 {
32  protected $gridDataService;
33 
37  protected $stagesService;
38 
42  protected $differenceHandler;
43 
50  public function checkIntegrity(\stdClass $parameters)
51  {
52  $integrity = $this->createIntegrityService($this->getAffectedElements($parameters));
53  $integrity->check();
54  $response = [
55  'result' => $integrity->getStatusRepresentation()
56  ];
57  return $response;
58  }
59 
66  public function getWorkspaceInfos($parameter)
67  {
68  // To avoid too much work we use -1 to indicate that every page is relevant
69  $pageId = $parameter->id > 0 ? $parameter->id : -1;
70  if (!isset($parameter->language) || !\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($parameter->language)) {
71  $parameter->language = null;
72  }
73  $versions = $this->getWorkspaceService()->selectVersionsInWorkspace($this->getCurrentWorkspace(), 0, -99, $pageId, $parameter->depth, 'tables_select', $parameter->language);
74  $data = $this->getGridDataService()->generateGridListFromVersions($versions, $parameter, $this->getCurrentWorkspace());
75  return $data;
76  }
77 
84  public function getHistory($parameters)
85  {
87  $historyService = GeneralUtility::makeInstance(\TYPO3\CMS\Workspaces\Service\HistoryService::class);
88  $history = $historyService->getHistory($parameters->table, $parameters->liveId);
89  return [
90  'data' => $history,
91  'total' => count($history)
92  ];
93  }
94 
101  public function getStageActions(\stdClass $parameter)
102  {
103  $currentWorkspace = $this->getCurrentWorkspace();
104  $stages = [];
105  if ($currentWorkspace != \TYPO3\CMS\Workspaces\Service\WorkspaceService::SELECT_ALL_WORKSPACES) {
106  $stages = $this->getStagesService()->getStagesForWSUser();
107  }
108  $data = [
109  'total' => count($stages),
110  'data' => $stages
111  ];
112  return $data;
113  }
114 
121  public function getRowDetails($parameter)
122  {
123  $diffReturnArray = [];
124  $liveReturnArray = [];
126  $diffUtility = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Utility\DiffUtility::class);
128  $parseObj = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Html\RteHtmlParser::class);
129  $liveRecord = BackendUtility::getRecord($parameter->table, $parameter->t3ver_oid);
130  $versionRecord = BackendUtility::getRecord($parameter->table, $parameter->uid);
131  $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
132  $icon_Live = $iconFactory->getIconForRecord($parameter->table, $liveRecord, Icon::SIZE_SMALL)->render();
133  $icon_Workspace = $iconFactory->getIconForRecord($parameter->table, $versionRecord, Icon::SIZE_SMALL)->render();
134  $stagePosition = $this->getStagesService()->getPositionOfCurrentStage($parameter->stage);
135  $fieldsOfRecords = array_keys($liveRecord);
136  if ($GLOBALS['TCA'][$parameter->table]) {
137  if ($GLOBALS['TCA'][$parameter->table]['interface']['showRecordFieldList']) {
138  $fieldsOfRecords = $GLOBALS['TCA'][$parameter->table]['interface']['showRecordFieldList'];
139  $fieldsOfRecords = GeneralUtility::trimExplode(',', $fieldsOfRecords, true);
140  }
141  }
142  foreach ($fieldsOfRecords as $fieldName) {
143  if (empty($GLOBALS['TCA'][$parameter->table]['columns'][$fieldName]['config'])) {
144  continue;
145  }
146  // Get the field's label. If not available, use the field name
147  $fieldTitle = $GLOBALS['LANG']->sL(BackendUtility::getItemLabel($parameter->table, $fieldName));
148  if (empty($fieldTitle)) {
149  $fieldTitle = $fieldName;
150  }
151  // Gets the TCA configuration for the current field
152  $configuration = $GLOBALS['TCA'][$parameter->table]['columns'][$fieldName]['config'];
153  // check for exclude fields
154  if ($GLOBALS['BE_USER']->isAdmin() || $GLOBALS['TCA'][$parameter->table]['columns'][$fieldName]['exclude'] == 0 || GeneralUtility::inList($GLOBALS['BE_USER']->groupData['non_exclude_fields'], $parameter->table . ':' . $fieldName)) {
155  // call diff class only if there is a difference
156  if ($configuration['type'] === 'inline' && $configuration['foreign_table'] === 'sys_file_reference') {
157  $useThumbnails = false;
158  if (!empty($configuration['foreign_selector_fieldTcaOverride']['config']['appearance']['elementBrowserAllowed']) && !empty($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'])) {
159  $fileExtensions = GeneralUtility::trimExplode(',', $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], true);
160  $allowedExtensions = GeneralUtility::trimExplode(',', $configuration['foreign_selector_fieldTcaOverride']['config']['appearance']['elementBrowserAllowed'], true);
161  $differentExtensions = array_diff($allowedExtensions, $fileExtensions);
162  $useThumbnails = empty($differentExtensions);
163  }
164 
165  $liveFileReferences = BackendUtility::resolveFileReferences(
166  $parameter->table,
167  $fieldName,
168  $liveRecord,
169  0
170  );
171  $versionFileReferences = BackendUtility::resolveFileReferences(
172  $parameter->table,
173  $fieldName,
174  $versionRecord,
175  $this->getCurrentWorkspace()
176  );
177  $fileReferenceDifferences = $this->prepareFileReferenceDifferences(
178  $liveFileReferences,
179  $versionFileReferences,
180  $useThumbnails
181  );
182 
183  if ($fileReferenceDifferences === null) {
184  continue;
185  }
186 
187  $diffReturnArray[] = [
188  'field' => $fieldName,
189  'label' => $fieldTitle,
190  'content' => $fileReferenceDifferences['differences']
191  ];
192  $liveReturnArray[] = [
193  'field' => $fieldName,
194  'label' => $fieldTitle,
195  'content' => $fileReferenceDifferences['live']
196  ];
197  } elseif ((string)$liveRecord[$fieldName] !== (string)$versionRecord[$fieldName]) {
198  // Select the human readable values before diff
199  $liveRecord[$fieldName] = BackendUtility::getProcessedValue(
200  $parameter->table,
201  $fieldName,
202  $liveRecord[$fieldName],
203  0,
204  1,
205  false,
206  $liveRecord['uid']
207  );
208  $versionRecord[$fieldName] = BackendUtility::getProcessedValue(
209  $parameter->table,
210  $fieldName,
211  $versionRecord[$fieldName],
212  0,
213  1,
214  false,
215  $versionRecord['uid']
216  );
217 
218  if ($configuration['type'] == 'group' && $configuration['internal_type'] == 'file') {
219  $versionThumb = BackendUtility::thumbCode($versionRecord, $parameter->table, $fieldName, '');
220  $liveThumb = BackendUtility::thumbCode($liveRecord, $parameter->table, $fieldName, '');
221  $diffReturnArray[] = [
222  'field' => $fieldName,
223  'label' => $fieldTitle,
224  'content' => $versionThumb
225  ];
226  $liveReturnArray[] = [
227  'field' => $fieldName,
228  'label' => $fieldTitle,
229  'content' => $liveThumb
230  ];
231  } else {
232  $diffReturnArray[] = [
233  'field' => $fieldName,
234  'label' => $fieldTitle,
235  'content' => $diffUtility->makeDiffDisplay($liveRecord[$fieldName], $versionRecord[$fieldName])
236  ];
237  $liveReturnArray[] = [
238  'field' => $fieldName,
239  'label' => $fieldTitle,
240  'content' => $parseObj->TS_images_rte($liveRecord[$fieldName])
241  ];
242  }
243  }
244  }
245  }
246  // Hook for modifying the difference and live arrays
247  // (this may be used by custom or dynamically-defined fields)
248  if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['workspaces']['modifyDifferenceArray'])) {
249  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['workspaces']['modifyDifferenceArray'] as $className) {
250  $hookObject = GeneralUtility::getUserObj($className);
251  if (method_exists($hookObject, 'modifyDifferenceArray')) {
252  $hookObject->modifyDifferenceArray($parameter, $diffReturnArray, $liveReturnArray, $diffUtility);
253  }
254  }
255  }
256  $commentsForRecord = $this->getCommentsForRecord($parameter->uid, $parameter->table);
257  return [
258  'total' => 1,
259  'data' => [
260  [
261  // these parts contain HTML (don't escape)
262  'diff' => $diffReturnArray,
263  'live_record' => $liveReturnArray,
264  'icon_Live' => $icon_Live,
265  'icon_Workspace' => $icon_Workspace,
266  // this part is already escaped in getCommentsForRecord()
267  'comments' => $commentsForRecord,
268  // escape/santinize the others
269  'path_Live' => htmlspecialchars($parameter->path_Live),
270  'label_Stage' => htmlspecialchars($parameter->label_Stage),
271  'stage_position' => (int)$stagePosition['position'],
272  'stage_count' => (int)$stagePosition['count']
273  ]
274  ]
275  ];
276  }
277 
286  protected function prepareFileReferenceDifferences(array $liveFileReferences, array $versionFileReferences, $useThumbnails = false)
287  {
288  $randomValue = uniqid('file');
289 
290  $liveValues = [];
291  $versionValues = [];
292  $candidates = [];
293  $substitutes = [];
294 
295  // Process live references
296  foreach ($liveFileReferences as $identifier => $liveFileReference) {
297  $identifierWithRandomValue = $randomValue . '__' . $liveFileReference->getUid() . '__' . $randomValue;
298  $candidates[$identifierWithRandomValue] = $liveFileReference;
299  $liveValues[] = $identifierWithRandomValue;
300  }
301 
302  // Process version references
303  foreach ($versionFileReferences as $identifier => $versionFileReference) {
304  $identifierWithRandomValue = $randomValue . '__' . $versionFileReference->getUid() . '__' . $randomValue;
305  $candidates[$identifierWithRandomValue] = $versionFileReference;
306  $versionValues[] = $identifierWithRandomValue;
307  }
308 
309  // Combine values and surround by spaces
310  // (to reduce the chunks Diff will find)
311  $liveInformation = ' ' . implode(' ', $liveValues) . ' ';
312  $versionInformation = ' ' . implode(' ', $versionValues) . ' ';
313 
314  // Return if information has not changed
315  if ($liveInformation === $versionInformation) {
316  return null;
317  }
318 
323  foreach ($candidates as $identifierWithRandomValue => $fileReference) {
324  if ($useThumbnails) {
325  $thumbnailFile = $fileReference->getOriginalFile()->process(
326  \TYPO3\CMS\Core\Resource\ProcessedFile::CONTEXT_IMAGEPREVIEW,
327  ['width' => 40, 'height' => 40]
328  );
329  $thumbnailMarkup = '<img src="' . $thumbnailFile->getPublicUrl(true) . '" />';
330  $substitutes[$identifierWithRandomValue] = $thumbnailMarkup;
331  } else {
332  $substitutes[$identifierWithRandomValue] = $fileReference->getPublicUrl();
333  }
334  }
335 
336  $differences = $this->getDifferenceHandler()->render($liveInformation, $versionInformation);
337  $liveInformation = str_replace(array_keys($substitutes), array_values($substitutes), trim($liveInformation));
338  $differences = str_replace(array_keys($substitutes), array_values($substitutes), trim($differences));
339 
340  return [
341  'live' => $liveInformation,
342  'differences' => $differences
343  ];
344  }
345 
353  public function getCommentsForRecord($uid, $table)
354  {
355  $sysLogReturnArray = [];
356  $sysLogRows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
357  'log_data,tstamp,userid',
358  'sys_log',
359  'action=6 and details_nr=30 AND tablename=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($table, 'sys_log')
360  . ' AND recuid=' . (int)$uid,
361  '',
362  'tstamp DESC'
363  );
364  foreach ($sysLogRows as $sysLogRow) {
365  $sysLogEntry = [];
366  $data = unserialize($sysLogRow['log_data']);
367  $beUserRecord = BackendUtility::getRecord('be_users', $sysLogRow['userid']);
368  $sysLogEntry['stage_title'] = htmlspecialchars($this->getStagesService()->getStageTitle($data['stage']));
369  $sysLogEntry['user_uid'] = (int)$sysLogRow['userid'];
370  $sysLogEntry['user_username'] = is_array($beUserRecord) ? htmlspecialchars($beUserRecord['username']) : '';
371  $sysLogEntry['tstamp'] = htmlspecialchars(BackendUtility::datetime($sysLogRow['tstamp']));
372  $sysLogEntry['user_comment'] = nl2br(htmlspecialchars($data['comment']));
373  $sysLogReturnArray[] = $sysLogEntry;
374  }
375  return $sysLogReturnArray;
376  }
377 
383  public function getSystemLanguages()
384  {
385  $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
386  $systemLanguages = [
387  [
388  'uid' => 'all',
389  'title' => \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate('language.allLanguages', 'workspaces'),
390  'icon' => $iconFactory->getIcon('empty-empty', Icon::SIZE_SMALL)->render()
391  ]
392  ];
393  foreach ($this->getGridDataService()->getSystemLanguages() as $id => $systemLanguage) {
394  if ($id < 0) {
395  continue;
396  }
397  $systemLanguages[] = [
398  'uid' => $id,
399  'title' => htmlspecialchars($systemLanguage['title']),
400  'icon' => $iconFactory->getIcon($systemLanguage['flagIcon'], Icon::SIZE_SMALL)->render()
401  ];
402  }
403  $result = [
404  'total' => count($systemLanguages),
405  'data' => $systemLanguages
406  ];
407  return $result;
408  }
409 
415  protected function getGridDataService()
416  {
417  if (!isset($this->gridDataService)) {
418  $this->gridDataService = GeneralUtility::makeInstance(\TYPO3\CMS\Workspaces\Service\GridDataService::class);
419  }
420  return $this->gridDataService;
421  }
422 
428  protected function getStagesService()
429  {
430  if (!isset($this->stagesService)) {
431  $this->stagesService = GeneralUtility::makeInstance(\TYPO3\CMS\Workspaces\Service\StagesService::class);
432  }
433  return $this->stagesService;
434  }
435 
441  protected function getDifferenceHandler()
442  {
443  if (!isset($this->differenceHandler)) {
444  $granularity = new \cogpowered\FineDiff\Granularity\Word();
445  $this->differenceHandler = new \cogpowered\FineDiff\Diff($granularity);
446  }
448  }
449 
453  protected function getObjectManager()
454  {
455  return GeneralUtility::makeInstance(ObjectManager::class);
456  }
457 }
static translate($key, $extensionName, $arguments=null)
static getItemLabel($table, $col, $printAllWrap='')
static trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
$uid
Definition: server.php:38
static getRecord($table, $uid, $fields=' *', $where='', $useDeleteClause=true)
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']