TYPO3  7.6
ExtDirectServer.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Workspaces\ExtDirect;
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 = array(
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 array(
90  'data' => $history,
91  'total' => count($history)
92  );
93  }
94 
101  public function getStageActions(\stdClass $parameter)
102  {
103  $currentWorkspace = $this->getCurrentWorkspace();
104  $stages = array();
105  if ($currentWorkspace != \TYPO3\CMS\Workspaces\Service\WorkspaceService::SELECT_ALL_WORKSPACES) {
106  $stages = $this->getStagesService()->getStagesForWSUser();
107  }
108  $data = array(
109  'total' => count($stages),
110  'data' => $stages
111  );
112  return $data;
113  }
114 
121  public function getRowDetails($parameter)
122  {
123  $diffReturnArray = array();
124  $liveReturnArray = array();
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[] = array(
188  'field' => $fieldName,
189  'label' => $fieldTitle,
190  'content' => $fileReferenceDifferences['differences']
191  );
192  $liveReturnArray[] = array(
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[] = array(
222  'field' => $fieldName,
223  'label' => $fieldTitle,
224  'content' => $versionThumb
225  );
226  $liveReturnArray[] = array(
227  'field' => $fieldName,
228  'label' => $fieldTitle,
229  'content' => $liveThumb
230  );
231  } else {
232  $diffReturnArray[] = array(
233  'field' => $fieldName,
234  'label' => $fieldTitle,
235  'content' => $diffUtility->makeDiffDisplay($liveRecord[$fieldName], $versionRecord[$fieldName])
236  );
237  $liveReturnArray[] = array(
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 array(
258  'total' => 1,
259  'data' => array(
260  array(
261  'diff' => $diffReturnArray,
262  'live_record' => $liveReturnArray,
263  'path_Live' => $parameter->path_Live,
264  'label_Stage' => $parameter->label_Stage,
265  'stage_position' => $stagePosition['position'],
266  'stage_count' => $stagePosition['count'],
267  'comments' => $commentsForRecord,
268  'icon_Live' => $icon_Live,
269  'icon_Workspace' => $icon_Workspace
270  )
271  )
272  );
273  }
274 
283  protected function prepareFileReferenceDifferences(array $liveFileReferences, array $versionFileReferences, $useThumbnails = false)
284  {
285  $randomValue = uniqid('file');
286 
287  $liveValues = array();
288  $versionValues = array();
289  $candidates = array();
290  $substitutes = array();
291 
292  // Process live references
293  foreach ($liveFileReferences as $identifier => $liveFileReference) {
294  $identifierWithRandomValue = $randomValue . '__' . $liveFileReference->getUid() . '__' . $randomValue;
295  $candidates[$identifierWithRandomValue] = $liveFileReference;
296  $liveValues[] = $identifierWithRandomValue;
297  }
298 
299  // Process version references
300  foreach ($versionFileReferences as $identifier => $versionFileReference) {
301  $identifierWithRandomValue = $randomValue . '__' . $versionFileReference->getUid() . '__' . $randomValue;
302  $candidates[$identifierWithRandomValue] = $versionFileReference;
303  $versionValues[] = $identifierWithRandomValue;
304  }
305 
306  // Combine values and surround by spaces
307  // (to reduce the chunks Diff will find)
308  $liveInformation = ' ' . implode(' ', $liveValues) . ' ';
309  $versionInformation = ' ' . implode(' ', $versionValues) . ' ';
310 
311  // Return if information has not changed
312  if ($liveInformation === $versionInformation) {
313  return null;
314  }
315 
320  foreach ($candidates as $identifierWithRandomValue => $fileReference) {
321  if ($useThumbnails) {
322  $thumbnailFile = $fileReference->getOriginalFile()->process(
323  \TYPO3\CMS\Core\Resource\ProcessedFile::CONTEXT_IMAGEPREVIEW,
324  array('width' => 40, 'height' => 40)
325  );
326  $thumbnailMarkup = '<img src="' . $thumbnailFile->getPublicUrl(true) . '" />';
327  $substitutes[$identifierWithRandomValue] = $thumbnailMarkup;
328  } else {
329  $substitutes[$identifierWithRandomValue] = $fileReference->getPublicUrl();
330  }
331  }
332 
333  $differences = $this->getDifferenceHandler()->render($liveInformation, $versionInformation);
334  $liveInformation = str_replace(array_keys($substitutes), array_values($substitutes), trim($liveInformation));
335  $differences = str_replace(array_keys($substitutes), array_values($substitutes), trim($differences));
336 
337  return array(
338  'live' => $liveInformation,
339  'differences' => $differences
340  );
341  }
342 
350  public function getCommentsForRecord($uid, $table)
351  {
352  $sysLogReturnArray = array();
353  $sysLogRows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
354  'log_data,tstamp,userid',
355  'sys_log',
356  'action=6 and details_nr=30 AND tablename=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($table, 'sys_log')
357  . ' AND recuid=' . (int)$uid,
358  '',
359  'tstamp DESC'
360  );
361  foreach ($sysLogRows as $sysLogRow) {
362  $sysLogEntry = array();
363  $data = unserialize($sysLogRow['log_data']);
364  $beUserRecord = BackendUtility::getRecord('be_users', $sysLogRow['userid']);
365  $sysLogEntry['stage_title'] = $this->getStagesService()->getStageTitle($data['stage']);
366  $sysLogEntry['user_uid'] = $sysLogRow['userid'];
367  $sysLogEntry['user_username'] = is_array($beUserRecord) ? $beUserRecord['username'] : '';
368  $sysLogEntry['tstamp'] = BackendUtility::datetime($sysLogRow['tstamp']);
369  $sysLogEntry['user_comment'] = $data['comment'];
370  $sysLogReturnArray[] = $sysLogEntry;
371  }
372  return $sysLogReturnArray;
373  }
374 
380  public function getSystemLanguages()
381  {
382  $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
383  $systemLanguages = array(
384  array(
385  'uid' => 'all',
386  'title' => \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate('language.allLanguages', 'workspaces'),
387  'icon' => $iconFactory->getIcon('empty-empty', Icon::SIZE_SMALL)->render()
388  )
389  );
390  foreach ($this->getGridDataService()->getSystemLanguages() as $id => $systemLanguage) {
391  if ($id < 0) {
392  continue;
393  }
394  $systemLanguages[] = array(
395  'uid' => $id,
396  'title' => htmlspecialchars($systemLanguage['title']),
397  'icon' => $iconFactory->getIcon($systemLanguage['flagIcon'], Icon::SIZE_SMALL)->render()
398  );
399  }
400  $result = array(
401  'total' => count($systemLanguages),
402  'data' => $systemLanguages
403  );
404  return $result;
405  }
406 
412  protected function getGridDataService()
413  {
414  if (!isset($this->gridDataService)) {
415  $this->gridDataService = GeneralUtility::makeInstance(\TYPO3\CMS\Workspaces\Service\GridDataService::class);
416  }
417  return $this->gridDataService;
418  }
419 
425  protected function getStagesService()
426  {
427  if (!isset($this->stagesService)) {
428  $this->stagesService = GeneralUtility::makeInstance(\TYPO3\CMS\Workspaces\Service\StagesService::class);
429  }
430  return $this->stagesService;
431  }
432 
438  protected function getDifferenceHandler()
439  {
440  if (!isset($this->differenceHandler)) {
441  $granularity = new \cogpowered\FineDiff\Granularity\Word();
442  $this->differenceHandler = new \cogpowered\FineDiff\Diff($granularity);
443  }
445  }
446 
450  protected function getObjectManager()
451  {
452  return GeneralUtility::makeInstance(ObjectManager::class);
453  }
454 }