[TASK] The Number of The Workspace
[Packages/TYPO3.CMS.git] / typo3 / sysext / workspaces / Classes / ExtDirect / ExtDirectServer.php
index 4a35a4e..dde139e 100644 (file)
@@ -14,12 +14,25 @@ namespace TYPO3\CMS\Workspaces\ExtDirect;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Backend\Backend\Avatar\Avatar;
 use TYPO3\CMS\Backend\Utility\BackendUtility;
+use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
+use TYPO3\CMS\Core\Database\DatabaseConnection;
+use TYPO3\CMS\Core\Html\RteHtmlParser;
 use TYPO3\CMS\Core\Imaging\Icon;
 use TYPO3\CMS\Core\Imaging\IconFactory;
 use TYPO3\CMS\Core\Resource\FileReference;
+use TYPO3\CMS\Core\Resource\ProcessedFile;
+use TYPO3\CMS\Core\Utility\DiffUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Core\Utility\MathUtility;
 use TYPO3\CMS\Extbase\Object\ObjectManager;
+use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
+use TYPO3\CMS\Lang\LanguageService;
+use TYPO3\CMS\Workspaces\Service\GridDataService;
+use TYPO3\CMS\Workspaces\Service\HistoryService;
+use TYPO3\CMS\Workspaces\Service\StagesService;
+use TYPO3\CMS\Workspaces\Service\WorkspaceService;
 
 /**
  * ExtDirect server
@@ -27,17 +40,17 @@ use TYPO3\CMS\Extbase\Object\ObjectManager;
 class ExtDirectServer extends AbstractHandler
 {
     /**
-     * @var \TYPO3\CMS\Workspaces\Service\GridDataService
+     * @var GridDataService
      */
     protected $gridDataService;
 
     /**
-     * @var \TYPO3\CMS\Workspaces\Service\StagesService
+     * @var StagesService
      */
     protected $stagesService;
 
     /**
-     * @var \cogpowered\FineDiff\Diff
+     * @var DiffUtility
      */
     protected $differenceHandler;
 
@@ -67,7 +80,7 @@ class ExtDirectServer extends AbstractHandler
     {
         // To avoid too much work we use -1 to indicate that every page is relevant
         $pageId = $parameter->id > 0 ? $parameter->id : -1;
-        if (!isset($parameter->language) || !\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($parameter->language)) {
+        if (!isset($parameter->language) || !MathUtility::canBeInterpretedAsInteger($parameter->language)) {
             $parameter->language = null;
         }
         $versions = $this->getWorkspaceService()->selectVersionsInWorkspace($this->getCurrentWorkspace(), 0, -99, $pageId, $parameter->depth, 'tables_select', $parameter->language);
@@ -76,23 +89,6 @@ class ExtDirectServer extends AbstractHandler
     }
 
     /**
-     * Gets the editing history of a record.
-     *
-     * @param stdClass $parameters
-     * @return array
-     */
-    public function getHistory($parameters)
-    {
-        /** @var $historyService \TYPO3\CMS\Workspaces\Service\HistoryService */
-        $historyService = GeneralUtility::makeInstance(\TYPO3\CMS\Workspaces\Service\HistoryService::class);
-        $history = $historyService->getHistory($parameters->table, $parameters->liveId);
-        return array(
-            'data' => $history,
-            'total' => count($history)
-        );
-    }
-
-    /**
      * Get List of available workspace actions
      *
      * @param \stdClass $parameter
@@ -102,7 +98,7 @@ class ExtDirectServer extends AbstractHandler
     {
         $currentWorkspace = $this->getCurrentWorkspace();
         $stages = array();
-        if ($currentWorkspace != \TYPO3\CMS\Workspaces\Service\WorkspaceService::SELECT_ALL_WORKSPACES) {
+        if ($currentWorkspace != WorkspaceService::SELECT_ALL_WORKSPACES) {
             $stages = $this->getStagesService()->getStagesForWSUser();
         }
         $data = array(
@@ -122,16 +118,16 @@ class ExtDirectServer extends AbstractHandler
     {
         $diffReturnArray = array();
         $liveReturnArray = array();
-        /** @var $diffUtility \TYPO3\CMS\Core\Utility\DiffUtility */
-        $diffUtility = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Utility\DiffUtility::class);
-        /** @var $parseObj \TYPO3\CMS\Core\Html\RteHtmlParser */
-        $parseObj = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Html\RteHtmlParser::class);
+        $diffUtility = $this->getDifferenceHandler();
+        /** @var $parseObj RteHtmlParser */
+        $parseObj = GeneralUtility::makeInstance(RteHtmlParser::class);
         $liveRecord = BackendUtility::getRecord($parameter->table, $parameter->t3ver_oid);
         $versionRecord = BackendUtility::getRecord($parameter->table, $parameter->uid);
         $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
         $icon_Live = $iconFactory->getIconForRecord($parameter->table, $liveRecord, Icon::SIZE_SMALL)->render();
         $icon_Workspace = $iconFactory->getIconForRecord($parameter->table, $versionRecord, Icon::SIZE_SMALL)->render();
-        $stagePosition = $this->getStagesService()->getPositionOfCurrentStage($parameter->stage);
+        $stagesService = $this->getStagesService();
+        $stagePosition = $stagesService->getPositionOfCurrentStage($parameter->stage);
         $fieldsOfRecords = array_keys($liveRecord);
         if ($GLOBALS['TCA'][$parameter->table]) {
             if ($GLOBALS['TCA'][$parameter->table]['interface']['showRecordFieldList']) {
@@ -144,14 +140,14 @@ class ExtDirectServer extends AbstractHandler
                 continue;
             }
             // Get the field's label. If not available, use the field name
-            $fieldTitle = $GLOBALS['LANG']->sL(BackendUtility::getItemLabel($parameter->table, $fieldName));
+            $fieldTitle = $this->getLanguageService()->sL(BackendUtility::getItemLabel($parameter->table, $fieldName));
             if (empty($fieldTitle)) {
                 $fieldTitle = $fieldName;
             }
             // Gets the TCA configuration for the current field
             $configuration = $GLOBALS['TCA'][$parameter->table]['columns'][$fieldName]['config'];
             // check for exclude fields
-            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)) {
+            if ($this->getBackendUser()->isAdmin() || $GLOBALS['TCA'][$parameter->table]['columns'][$fieldName]['exclude'] == 0 || GeneralUtility::inList($this->getBackendUser()->groupData['non_exclude_fields'], $parameter->table . ':' . $fieldName)) {
                 // call diff class only if there is a difference
                 if ($configuration['type'] === 'inline' && $configuration['foreign_table'] === 'sys_file_reference') {
                     $useThumbnails = false;
@@ -254,19 +250,48 @@ class ExtDirectServer extends AbstractHandler
             }
         }
         $commentsForRecord = $this->getCommentsForRecord($parameter->uid, $parameter->table);
+
+        /** @var $historyService HistoryService */
+        $historyService = GeneralUtility::makeInstance(HistoryService::class);
+        $history = $historyService->getHistory($parameter->table, $parameter->t3ver_oid);
+
+        $prevStage = $stagesService->getPrevStage($parameter->stage);
+        $nextStage = $stagesService->getNextStage($parameter->stage);
+
+        if (isset($prevStage[0])) {
+            $prevStage = current($prevStage);
+        }
+
+        if (isset($nextStage[0])) {
+            $nextStage = current($nextStage);
+        }
+
         return array(
             'total' => 1,
             'data' => array(
                 array(
+                    // these parts contain HTML (don't escape)
                     'diff' => $diffReturnArray,
                     'live_record' => $liveReturnArray,
-                    'path_Live' => $parameter->path_Live,
-                    'label_Stage' => $parameter->label_Stage,
-                    'stage_position' => $stagePosition['position'],
-                    'stage_count' => $stagePosition['count'],
-                    'comments' => $commentsForRecord,
                     'icon_Live' => $icon_Live,
-                    'icon_Workspace' => $icon_Workspace
+                    'icon_Workspace' => $icon_Workspace,
+                    // this part is already escaped in getCommentsForRecord()
+                    'comments' => $commentsForRecord,
+                    // escape/sanitize the others
+                    'path_Live' => htmlspecialchars(BackendUtility::getRecordPath($liveRecord['pid'], '', 999)),
+                    'label_Stage' => htmlspecialchars($stagesService->getStageTitle($parameter->stage)),
+                    'label_PrevStage' => $prevStage,
+                    'label_NextStage' => $nextStage,
+                    'stage_position' => (int)$stagePosition['position'],
+                    'stage_count' => (int)$stagePosition['count'],
+                    'parent' => [
+                        'table' => htmlspecialchars($parameter->table),
+                        'uid' => (int)$parameter->uid
+                    ],
+                    'history' => [
+                        'data' => $history,
+                        'total' => count($history)
+                    ]
                 )
             )
         );
@@ -320,7 +345,7 @@ class ExtDirectServer extends AbstractHandler
         foreach ($candidates as $identifierWithRandomValue => $fileReference) {
             if ($useThumbnails) {
                 $thumbnailFile = $fileReference->getOriginalFile()->process(
-                    \TYPO3\CMS\Core\Resource\ProcessedFile::CONTEXT_IMAGEPREVIEW,
+                    ProcessedFile::CONTEXT_IMAGEPREVIEW,
                     array('width' => 40, 'height' => 40)
                 );
                 $thumbnailMarkup = '<img src="' . $thumbnailFile->getPublicUrl(true) . '" />';
@@ -330,7 +355,7 @@ class ExtDirectServer extends AbstractHandler
             }
         }
 
-        $differences = $this->getDifferenceHandler()->render($liveInformation, $versionInformation);
+        $differences = $this->getDifferenceHandler()->makeDiffDisplay($liveInformation, $versionInformation);
         $liveInformation = str_replace(array_keys($substitutes), array_values($substitutes), trim($liveInformation));
         $differences = str_replace(array_keys($substitutes), array_values($substitutes), trim($differences));
 
@@ -350,23 +375,28 @@ class ExtDirectServer extends AbstractHandler
     public function getCommentsForRecord($uid, $table)
     {
         $sysLogReturnArray = array();
-        $sysLogRows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
+        $sysLogRows = $this->getDatabaseConnection()->exec_SELECTgetRows(
             'log_data,tstamp,userid',
             'sys_log',
-            'action=6 and details_nr=30 AND tablename=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($table, 'sys_log')
+            'action=6 and details_nr=30 AND tablename=' . $this->getDatabaseConnection()->fullQuoteStr($table, 'sys_log')
                 . ' AND recuid=' . (int)$uid,
             '',
             'tstamp DESC'
         );
+
+        /** @var Avatar $avatar */
+        $avatar = GeneralUtility::makeInstance(Avatar::class);
+
         foreach ($sysLogRows as $sysLogRow) {
             $sysLogEntry = array();
             $data = unserialize($sysLogRow['log_data']);
             $beUserRecord = BackendUtility::getRecord('be_users', $sysLogRow['userid']);
-            $sysLogEntry['stage_title'] = $this->getStagesService()->getStageTitle($data['stage']);
-            $sysLogEntry['user_uid'] = $sysLogRow['userid'];
-            $sysLogEntry['user_username'] = is_array($beUserRecord) ? $beUserRecord['username'] : '';
-            $sysLogEntry['tstamp'] = BackendUtility::datetime($sysLogRow['tstamp']);
-            $sysLogEntry['user_comment'] = $data['comment'];
+            $sysLogEntry['stage_title'] = htmlspecialchars($this->getStagesService()->getStageTitle($data['stage']));
+            $sysLogEntry['user_uid'] = (int)$sysLogRow['userid'];
+            $sysLogEntry['user_username'] = is_array($beUserRecord) ? htmlspecialchars($beUserRecord['username']) : '';
+            $sysLogEntry['tstamp'] = htmlspecialchars(BackendUtility::datetime($sysLogRow['tstamp']));
+            $sysLogEntry['user_comment'] = nl2br(htmlspecialchars($data['comment']));
+            $sysLogEntry['user_avatar'] = $avatar->render($beUserRecord);
             $sysLogReturnArray[] = $sysLogEntry;
         }
         return $sysLogReturnArray;
@@ -383,7 +413,7 @@ class ExtDirectServer extends AbstractHandler
         $systemLanguages = array(
             array(
                 'uid' => 'all',
-                'title' => \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate('language.allLanguages', 'workspaces'),
+                'title' => LocalizationUtility::translate('language.allLanguages', 'workspaces'),
                 'icon' => $iconFactory->getIcon('empty-empty', Icon::SIZE_SMALL)->render()
             )
         );
@@ -405,14 +435,38 @@ class ExtDirectServer extends AbstractHandler
     }
 
     /**
+     * @return BackendUserAuthentication;
+     */
+    protected function getBackendUser()
+    {
+        return $GLOBALS['BE_USER'];
+    }
+
+    /**
+     * @return LanguageService;
+     */
+    protected function getLanguageService()
+    {
+        return $GLOBALS['LANG'];
+    }
+
+    /**
+     * @return DatabaseConnection;
+     */
+    protected function getDatabaseConnection()
+    {
+        return $GLOBALS['TYPO3_DB'];
+    }
+
+    /**
      * Gets the Grid Data Service.
      *
-     * @return \TYPO3\CMS\Workspaces\Service\GridDataService
+     * @return GridDataService
      */
     protected function getGridDataService()
     {
         if (!isset($this->gridDataService)) {
-            $this->gridDataService = GeneralUtility::makeInstance(\TYPO3\CMS\Workspaces\Service\GridDataService::class);
+            $this->gridDataService = GeneralUtility::makeInstance(GridDataService::class);
         }
         return $this->gridDataService;
     }
@@ -420,12 +474,12 @@ class ExtDirectServer extends AbstractHandler
     /**
      * Gets the Stages Service.
      *
-     * @return \TYPO3\CMS\Workspaces\Service\StagesService
+     * @return StagesService
      */
     protected function getStagesService()
     {
         if (!isset($this->stagesService)) {
-            $this->stagesService = GeneralUtility::makeInstance(\TYPO3\CMS\Workspaces\Service\StagesService::class);
+            $this->stagesService = GeneralUtility::makeInstance(StagesService::class);
         }
         return $this->stagesService;
     }
@@ -433,13 +487,12 @@ class ExtDirectServer extends AbstractHandler
     /**
      * Gets the difference handler, parsing differences based on sentences.
      *
-     * @return \cogpowered\FineDiff\Diff
+     * @return DiffUtility
      */
     protected function getDifferenceHandler()
     {
         if (!isset($this->differenceHandler)) {
-            $granularity = new \cogpowered\FineDiff\Granularity\Word();
-            $this->differenceHandler = new \cogpowered\FineDiff\Diff($granularity);
+            $this->differenceHandler = GeneralUtility::makeInstance(DiffUtility::class);
         }
         return $this->differenceHandler;
     }