Completed
Push — master ( 38aa76...05a33d )
by Fabien
54:10
created
Classes/Domain/Repository/SelectionRepository.php 1 patch
Indentation   +49 added lines, -49 removed lines patch added patch discarded remove patch
@@ -19,63 +19,63 @@
 block discarded – undo
19 19
 class SelectionRepository extends Repository
20 20
 {
21 21
 
22
-    /**
23
-     * @param string $dataType
24
-     * @return QueryResult
25
-     */
26
-    public function findByDataTypeForCurrentBackendUser($dataType)
27
-    {
28
-        $query = $this->createQuery();
22
+	/**
23
+	 * @param string $dataType
24
+	 * @return QueryResult
25
+	 */
26
+	public function findByDataTypeForCurrentBackendUser($dataType)
27
+	{
28
+		$query = $this->createQuery();
29 29
 
30
-        // Compute the OR part
31
-        if ($this->getBackendUser()->isAdmin()) {
32
-            $logicalOr = $query->logicalOr([$query->equals('visibility', Selection::VISIBILITY_EVERYONE), $query->equals('visibility', Selection::VISIBILITY_ADMIN_ONLY), $query->equals('cruser_id', $this->getBackendUser()->user['uid'])]);
33
-        } else {
34
-            $logicalOr = $query->logicalOr([$query->equals('visibility', Selection::VISIBILITY_EVERYONE), $query->equals('cruser_id', $this->getBackendUser()->user['uid'])]);
35
-        }
30
+		// Compute the OR part
31
+		if ($this->getBackendUser()->isAdmin()) {
32
+			$logicalOr = $query->logicalOr([$query->equals('visibility', Selection::VISIBILITY_EVERYONE), $query->equals('visibility', Selection::VISIBILITY_ADMIN_ONLY), $query->equals('cruser_id', $this->getBackendUser()->user['uid'])]);
33
+		} else {
34
+			$logicalOr = $query->logicalOr([$query->equals('visibility', Selection::VISIBILITY_EVERYONE), $query->equals('cruser_id', $this->getBackendUser()->user['uid'])]);
35
+		}
36 36
 
37
-        // Add matching criteria
38
-        $query->matching(
39
-            $query->logicalAnd([$query->equals('dataType', $dataType), $logicalOr])
40
-        );
37
+		// Add matching criteria
38
+		$query->matching(
39
+			$query->logicalAnd([$query->equals('dataType', $dataType), $logicalOr])
40
+		);
41 41
 
42
-        // Set ordering
43
-        $query->setOrderings(
44
-            array('name' => QueryInterface::ORDER_ASCENDING)
45
-        );
42
+		// Set ordering
43
+		$query->setOrderings(
44
+			array('name' => QueryInterface::ORDER_ASCENDING)
45
+		);
46 46
 
47
-        return $query->execute();
48
-    }
47
+		return $query->execute();
48
+	}
49 49
 
50
-    /**
51
-     * @param string $dataType
52
-     * @return QueryResult
53
-     */
54
-    public function findForEveryone($dataType)
55
-    {
56
-        $query = $this->createQuery();
50
+	/**
51
+	 * @param string $dataType
52
+	 * @return QueryResult
53
+	 */
54
+	public function findForEveryone($dataType)
55
+	{
56
+		$query = $this->createQuery();
57 57
 
58
-        // Add matching criteria
59
-        $query->matching(
60
-            $query->logicalAnd([$query->equals('dataType', $dataType), $query->equals('visibility', Selection::VISIBILITY_EVERYONE)])
61
-        );
58
+		// Add matching criteria
59
+		$query->matching(
60
+			$query->logicalAnd([$query->equals('dataType', $dataType), $query->equals('visibility', Selection::VISIBILITY_EVERYONE)])
61
+		);
62 62
 
63
-        // Set ordering
64
-        $query->setOrderings(
65
-            array('name' => QueryInterface::ORDER_ASCENDING)
66
-        );
63
+		// Set ordering
64
+		$query->setOrderings(
65
+			array('name' => QueryInterface::ORDER_ASCENDING)
66
+		);
67 67
 
68
-        return $query->execute();
69
-    }
68
+		return $query->execute();
69
+	}
70 70
 
71
-    /**
72
-     * Returns an instance of the current Backend User.
73
-     *
74
-     * @return BackendUserAuthentication
75
-     */
76
-    protected function getBackendUser()
77
-    {
78
-        return $GLOBALS['BE_USER'];
79
-    }
71
+	/**
72
+	 * Returns an instance of the current Backend User.
73
+	 *
74
+	 * @return BackendUserAuthentication
75
+	 */
76
+	protected function getBackendUser()
77
+	{
78
+		return $GLOBALS['BE_USER'];
79
+	}
80 80
 
81 81
 }
82 82
\ No newline at end of file
Please login to merge, or discard this patch.
Classes/Controller/UserPreferencesController.php 2 patches
Indentation   +56 added lines, -56 removed lines patch added patch discarded remove patch
@@ -21,69 +21,69 @@
 block discarded – undo
21 21
 class UserPreferencesController extends ActionController
22 22
 {
23 23
 
24
-    /**
25
-     * @param string $key
26
-     * @param string $value
27
-     * @param string $preferenceSignature
28
-     * @return string
29
-     */
30
-    public function saveAction($key, $value, $preferenceSignature): ResponseInterface
31
-    {
24
+	/**
25
+	 * @param string $key
26
+	 * @param string $value
27
+	 * @param string $preferenceSignature
28
+	 * @return string
29
+	 */
30
+	public function saveAction($key, $value, $preferenceSignature): ResponseInterface
31
+	{
32 32
 
33
-        $dataType = $this->getModuleLoader()->getDataType();
33
+		$dataType = $this->getModuleLoader()->getDataType();
34 34
 
35
-        $key = $dataType . '_' . $this->getBackendUserIdentifier() . '_' . $key;
36
-        $this->getCacheInstance()->set($key, $value, [], 0);
35
+		$key = $dataType . '_' . $this->getBackendUserIdentifier() . '_' . $key;
36
+		$this->getCacheInstance()->set($key, $value, [], 0);
37 37
 
38
-        $key = $dataType . '_' . $this->getBackendUserIdentifier() . '_signature';
39
-        $this->getCacheInstance()->set($key, $preferenceSignature, [], 0);
38
+		$key = $dataType . '_' . $this->getBackendUserIdentifier() . '_signature';
39
+		$this->getCacheInstance()->set($key, $preferenceSignature, [], 0);
40 40
 
41
-        return $this->htmlResponse('OK');
42
-    }
41
+		return $this->htmlResponse('OK');
42
+	}
43 43
 
44
-    /**
45
-     * @return int
46
-     */
47
-    protected function getBackendUserIdentifier()
48
-    {
49
-        return $this->getBackendUser()->user['uid'];
50
-    }
44
+	/**
45
+	 * @return int
46
+	 */
47
+	protected function getBackendUserIdentifier()
48
+	{
49
+		return $this->getBackendUser()->user['uid'];
50
+	}
51 51
 
52
-    /**
53
-     * Returns an instance of the current Backend User.
54
-     *
55
-     * @return BackendUserAuthentication
56
-     */
57
-    protected function getBackendUser()
58
-    {
59
-        return $GLOBALS['BE_USER'];
60
-    }
52
+	/**
53
+	 * Returns an instance of the current Backend User.
54
+	 *
55
+	 * @return BackendUserAuthentication
56
+	 */
57
+	protected function getBackendUser()
58
+	{
59
+		return $GLOBALS['BE_USER'];
60
+	}
61 61
 
62
-    /**
63
-     * Get the Vidi Module Loader.
64
-     *
65
-     * @return ModuleLoader
66
-     */
67
-    protected function getModuleLoader()
68
-    {
69
-        return GeneralUtility::makeInstance(ModuleLoader::class);
70
-    }
62
+	/**
63
+	 * Get the Vidi Module Loader.
64
+	 *
65
+	 * @return ModuleLoader
66
+	 */
67
+	protected function getModuleLoader()
68
+	{
69
+		return GeneralUtility::makeInstance(ModuleLoader::class);
70
+	}
71 71
 
72
-    /**
73
-     * @return AbstractFrontend
74
-     */
75
-    protected function getCacheInstance()
76
-    {
77
-        return $this->getCacheManager()->getCache('vidi');
78
-    }
72
+	/**
73
+	 * @return AbstractFrontend
74
+	 */
75
+	protected function getCacheInstance()
76
+	{
77
+		return $this->getCacheManager()->getCache('vidi');
78
+	}
79 79
 
80
-    /**
81
-     * Return the Cache Manager
82
-     *
83
-     * @return CacheManager
84
-     */
85
-    protected function getCacheManager()
86
-    {
87
-        return GeneralUtility::makeInstance(CacheManager::class);
88
-    }
80
+	/**
81
+	 * Return the Cache Manager
82
+	 *
83
+	 * @return CacheManager
84
+	 */
85
+	protected function getCacheManager()
86
+	{
87
+		return GeneralUtility::makeInstance(CacheManager::class);
88
+	}
89 89
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -32,10 +32,10 @@
 block discarded – undo
32 32
 
33 33
         $dataType = $this->getModuleLoader()->getDataType();
34 34
 
35
-        $key = $dataType . '_' . $this->getBackendUserIdentifier() . '_' . $key;
35
+        $key = $dataType.'_'.$this->getBackendUserIdentifier().'_'.$key;
36 36
         $this->getCacheInstance()->set($key, $value, [], 0);
37 37
 
38
-        $key = $dataType . '_' . $this->getBackendUserIdentifier() . '_signature';
38
+        $key = $dataType.'_'.$this->getBackendUserIdentifier().'_signature';
39 39
         $this->getCacheInstance()->set($key, $preferenceSignature, [], 0);
40 40
 
41 41
         return $this->htmlResponse('OK');
Please login to merge, or discard this patch.
Classes/Controller/SelectionController.php 1 patch
Indentation   +78 added lines, -78 removed lines patch added patch discarded remove patch
@@ -25,91 +25,91 @@
 block discarded – undo
25 25
 class SelectionController extends ActionController
26 26
 {
27 27
 
28
-    /**
29
-     * @param Selection $selection
30
-     */
31
-    public function createAction(Selection $selection = null)
32
-    {
33
-        $selectionRepository = GeneralUtility::makeInstance(SelectionRepository::class);
34
-        $selection->setDataType($this->getModuleLoader()->getDataType());
28
+	/**
29
+	 * @param Selection $selection
30
+	 */
31
+	public function createAction(Selection $selection = null)
32
+	{
33
+		$selectionRepository = GeneralUtility::makeInstance(SelectionRepository::class);
34
+		$selection->setDataType($this->getModuleLoader()->getDataType());
35 35
 
36
-        $selection->setOwner($this->getBackendUser()->user['uid']);
37
-        $selectionRepository->add($selection);
38
-        $this->redirect('edit', 'Selection', 'vidi', array('dataType' => $selection->getDataType()));
39
-    }
36
+		$selection->setOwner($this->getBackendUser()->user['uid']);
37
+		$selectionRepository->add($selection);
38
+		$this->redirect('edit', 'Selection', 'vidi', array('dataType' => $selection->getDataType()));
39
+	}
40 40
 
41
-    /**
42
-     * @param Selection $selection
43
-     * @return string
44
-     */
45
-    public function deleteAction(Selection $selection): ResponseInterface
46
-    {
47
-        $selectionRepository = GeneralUtility::makeInstance(SelectionRepository::class);
48
-        $selectionRepository->remove($selection);
49
-        return $this->htmlResponse('ok');
50
-    }
41
+	/**
42
+	 * @param Selection $selection
43
+	 * @return string
44
+	 */
45
+	public function deleteAction(Selection $selection): ResponseInterface
46
+	{
47
+		$selectionRepository = GeneralUtility::makeInstance(SelectionRepository::class);
48
+		$selectionRepository->remove($selection);
49
+		return $this->htmlResponse('ok');
50
+	}
51 51
 
52
-    /**
53
-     * @param Selection $selection
54
-     */
55
-    public function updateAction(Selection $selection)
56
-    {
57
-        $selectionRepository = GeneralUtility::makeInstance(SelectionRepository::class);
58
-        $selectionRepository->update($selection);
59
-        $this->redirect('show', 'Selection', 'vidi', array('selection' => $selection->getUid()));
60
-    }
52
+	/**
53
+	 * @param Selection $selection
54
+	 */
55
+	public function updateAction(Selection $selection)
56
+	{
57
+		$selectionRepository = GeneralUtility::makeInstance(SelectionRepository::class);
58
+		$selectionRepository->update($selection);
59
+		$this->redirect('show', 'Selection', 'vidi', array('selection' => $selection->getUid()));
60
+	}
61 61
 
62
-    /**
63
-     * @param Selection $selection
64
-     */
65
-    public function showAction(Selection $selection): ResponseInterface
66
-    {
67
-        $this->view->assign('selection', $selection);
68
-        return $this->htmlResponse();
69
-    }
62
+	/**
63
+	 * @param Selection $selection
64
+	 */
65
+	public function showAction(Selection $selection): ResponseInterface
66
+	{
67
+		$this->view->assign('selection', $selection);
68
+		return $this->htmlResponse();
69
+	}
70 70
 
71
-    /**
72
-     * Returns an editing form for a given data type.
73
-     *
74
-     * @param string $dataType
75
-     */
76
-    public function editAction($dataType): ResponseInterface
77
-    {
78
-        $selectionRepository = GeneralUtility::makeInstance(SelectionRepository::class);
79
-        $selections = $selectionRepository->findByDataTypeForCurrentBackendUser($dataType);
80
-        $this->view->assign('selections', $selections);
81
-        return $this->htmlResponse();
82
-    }
71
+	/**
72
+	 * Returns an editing form for a given data type.
73
+	 *
74
+	 * @param string $dataType
75
+	 */
76
+	public function editAction($dataType): ResponseInterface
77
+	{
78
+		$selectionRepository = GeneralUtility::makeInstance(SelectionRepository::class);
79
+		$selections = $selectionRepository->findByDataTypeForCurrentBackendUser($dataType);
80
+		$this->view->assign('selections', $selections);
81
+		return $this->htmlResponse();
82
+	}
83 83
 
84
-    /**
85
-     * @param string $dataType
86
-     */
87
-    public function listAction($dataType): ResponseInterface
88
-    {
89
-        $selectionRepository = GeneralUtility::makeInstance(SelectionRepository::class);
90
-        $selections = $selectionRepository->findByDataTypeForCurrentBackendUser($dataType);
91
-        $this->view->assign('selections', $selections);
92
-        return $this->htmlResponse();
93
-    }
84
+	/**
85
+	 * @param string $dataType
86
+	 */
87
+	public function listAction($dataType): ResponseInterface
88
+	{
89
+		$selectionRepository = GeneralUtility::makeInstance(SelectionRepository::class);
90
+		$selections = $selectionRepository->findByDataTypeForCurrentBackendUser($dataType);
91
+		$this->view->assign('selections', $selections);
92
+		return $this->htmlResponse();
93
+	}
94 94
 
95
-    /**
96
-     * Get the Vidi Module Loader.
97
-     *
98
-     * @return ModuleLoader
99
-     */
100
-    protected function getModuleLoader()
101
-    {
102
-        return GeneralUtility::makeInstance(ModuleLoader::class);
103
-    }
95
+	/**
96
+	 * Get the Vidi Module Loader.
97
+	 *
98
+	 * @return ModuleLoader
99
+	 */
100
+	protected function getModuleLoader()
101
+	{
102
+		return GeneralUtility::makeInstance(ModuleLoader::class);
103
+	}
104 104
 
105
-    /**
106
-     * Returns an instance of the current Backend User.
107
-     *
108
-     * @return BackendUserAuthentication
109
-     */
110
-    protected function getBackendUser()
111
-    {
112
-        return $GLOBALS['BE_USER'];
113
-    }
105
+	/**
106
+	 * Returns an instance of the current Backend User.
107
+	 *
108
+	 * @return BackendUserAuthentication
109
+	 */
110
+	protected function getBackendUser()
111
+	{
112
+		return $GLOBALS['BE_USER'];
113
+	}
114 114
 
115 115
 }
Please login to merge, or discard this patch.
Classes/Controller/ToolController.php 1 patch
Indentation   +39 added lines, -39 removed lines patch added patch discarded remove patch
@@ -21,48 +21,48 @@
 block discarded – undo
21 21
 class ToolController extends ActionController
22 22
 {
23 23
 
24
-    /**
25
-     * @return void
26
-     */
27
-    public function welcomeAction(): ResponseInterface
28
-    {
29
-        $items = [];
30
-        $tools = ToolRegistry::getInstance()->getTools($this->getModuleLoader()->getDataType());
24
+	/**
25
+	 * @return void
26
+	 */
27
+	public function welcomeAction(): ResponseInterface
28
+	{
29
+		$items = [];
30
+		$tools = ToolRegistry::getInstance()->getTools($this->getModuleLoader()->getDataType());
31 31
 
32
-        foreach ($tools as $index => $tool) {
33
-            $item = [];
34
-            $item['title'] = $tool->getTitle();
35
-            $item['description'] = $tool->getDescription();
32
+		foreach ($tools as $index => $tool) {
33
+			$item = [];
34
+			$item['title'] = $tool->getTitle();
35
+			$item['description'] = $tool->getDescription();
36 36
 
37
-            $items[] = $item;
38
-        }
39
-        $this->view->assign('items', $items);
40
-        return $this->htmlResponse();
41
-    }
37
+			$items[] = $item;
38
+		}
39
+		$this->view->assign('items', $items);
40
+		return $this->htmlResponse();
41
+	}
42 42
 
43
-    /**
44
-     * @param string $tool
45
-     * @param array $arguments
46
-     * @return void
47
-     * @Extbase\Validate("Fab\Vidi\Domain\Validator\ToolValidator", param="tool")
48
-     */
49
-    public function workAction(string $tool, array $arguments = array()): ResponseInterface
50
-    {
51
-        /** @var ToolInterface $tool */
52
-        $tool = GeneralUtility::makeInstance($tool);
53
-        $workResult = $tool->work($arguments);
54
-        $this->view->assign('result', $workResult);
55
-        return $this->htmlResponse();
56
-    }
43
+	/**
44
+	 * @param string $tool
45
+	 * @param array $arguments
46
+	 * @return void
47
+	 * @Extbase\Validate("Fab\Vidi\Domain\Validator\ToolValidator", param="tool")
48
+	 */
49
+	public function workAction(string $tool, array $arguments = array()): ResponseInterface
50
+	{
51
+		/** @var ToolInterface $tool */
52
+		$tool = GeneralUtility::makeInstance($tool);
53
+		$workResult = $tool->work($arguments);
54
+		$this->view->assign('result', $workResult);
55
+		return $this->htmlResponse();
56
+	}
57 57
 
58
-    /**
59
-     * Get the Vidi Module Loader.
60
-     *
61
-     * @return ModuleLoader|object
62
-     */
63
-    protected function getModuleLoader()
64
-    {
65
-        return GeneralUtility::makeInstance(ModuleLoader::class);
66
-    }
58
+	/**
59
+	 * Get the Vidi Module Loader.
60
+	 *
61
+	 * @return ModuleLoader|object
62
+	 */
63
+	protected function getModuleLoader()
64
+	{
65
+		return GeneralUtility::makeInstance(ModuleLoader::class);
66
+	}
67 67
 
68 68
 }
Please login to merge, or discard this patch.
Classes/Controller/ClipboardController.php 1 patch
Indentation   +75 added lines, -75 removed lines patch added patch discarded remove patch
@@ -20,80 +20,80 @@
 block discarded – undo
20 20
 class ClipboardController extends ActionController
21 21
 {
22 22
 
23
-    /**
24
-     * Save data into the clipboard.
25
-     *
26
-     * @param array $matches
27
-     * @return string
28
-     */
29
-    public function saveAction(array $matches = array()): ResponseInterface
30
-    {
31
-
32
-        $matcher = MatcherObjectFactory::getInstance()->getMatcher($matches);
33
-        $this->getClipboardService()->save($matcher);
34
-
35
-        // Fetch objects via the Content Service.
36
-        $contentService = $this->getContentService()->findBy($matcher);
37
-        $numberOfObjects = $contentService->getNumberOfObjects();
38
-
39
-        if ($numberOfObjects === 0) {
40
-            $this->getClipboardService()->flush();
41
-        }
42
-
43
-        # Json header is not automatically sent in the BE...
44
-        $this->response->setHeader('Content-Type', 'application/json');
45
-        $this->response->sendHeaders();
46
-        return $this->jsonResponse(json_encode($numberOfObjects));
47
-    }
48
-
49
-    /**
50
-     * Completely flush the clipboard.
51
-     *
52
-     * @return string
53
-     */
54
-    public function flushAction(): ResponseInterface
55
-    {
56
-        $this->getClipboardService()->flush();
57
-
58
-        # Json header is not automatically sent in the BE...
59
-        $this->response->setHeader('Content-Type', 'application/json');
60
-        $this->response->sendHeaders();
61
-        return $this->jsonResponse(json_encode(true));
62
-    }
63
-
64
-    /**
65
-     * Show the content of the clipboard.
66
-     */
67
-    public function showAction(): ResponseInterface
68
-    {
69
-
70
-        // Retrieve matcher object from clipboard.
71
-        $matcher = $this->getClipboardService()->getMatcher();
72
-
73
-        // Fetch objects via the Content Service.
74
-        $contentService = $this->getContentService()->findBy($matcher);
75
-
76
-        // count number of items and display it.
77
-        $this->view->assign('target', GeneralUtility::_GP('id'));
78
-        $this->view->assign('numberOfObjects', $contentService->getNumberOfObjects());
79
-        $this->view->assign('objects', $contentService->getObjects());
80
-        return $this->htmlResponse();
81
-    }
82
-
83
-    /**
84
-     * @return ClipboardService|object
85
-     */
86
-    protected function getClipboardService()
87
-    {
88
-        return GeneralUtility::makeInstance(ClipboardService::class);
89
-    }
90
-
91
-    /**
92
-     * @return ContentService|object
93
-     */
94
-    protected function getContentService()
95
-    {
96
-        return GeneralUtility::makeInstance(ContentService::class);
97
-    }
23
+	/**
24
+	 * Save data into the clipboard.
25
+	 *
26
+	 * @param array $matches
27
+	 * @return string
28
+	 */
29
+	public function saveAction(array $matches = array()): ResponseInterface
30
+	{
31
+
32
+		$matcher = MatcherObjectFactory::getInstance()->getMatcher($matches);
33
+		$this->getClipboardService()->save($matcher);
34
+
35
+		// Fetch objects via the Content Service.
36
+		$contentService = $this->getContentService()->findBy($matcher);
37
+		$numberOfObjects = $contentService->getNumberOfObjects();
38
+
39
+		if ($numberOfObjects === 0) {
40
+			$this->getClipboardService()->flush();
41
+		}
42
+
43
+		# Json header is not automatically sent in the BE...
44
+		$this->response->setHeader('Content-Type', 'application/json');
45
+		$this->response->sendHeaders();
46
+		return $this->jsonResponse(json_encode($numberOfObjects));
47
+	}
48
+
49
+	/**
50
+	 * Completely flush the clipboard.
51
+	 *
52
+	 * @return string
53
+	 */
54
+	public function flushAction(): ResponseInterface
55
+	{
56
+		$this->getClipboardService()->flush();
57
+
58
+		# Json header is not automatically sent in the BE...
59
+		$this->response->setHeader('Content-Type', 'application/json');
60
+		$this->response->sendHeaders();
61
+		return $this->jsonResponse(json_encode(true));
62
+	}
63
+
64
+	/**
65
+	 * Show the content of the clipboard.
66
+	 */
67
+	public function showAction(): ResponseInterface
68
+	{
69
+
70
+		// Retrieve matcher object from clipboard.
71
+		$matcher = $this->getClipboardService()->getMatcher();
72
+
73
+		// Fetch objects via the Content Service.
74
+		$contentService = $this->getContentService()->findBy($matcher);
75
+
76
+		// count number of items and display it.
77
+		$this->view->assign('target', GeneralUtility::_GP('id'));
78
+		$this->view->assign('numberOfObjects', $contentService->getNumberOfObjects());
79
+		$this->view->assign('objects', $contentService->getObjects());
80
+		return $this->htmlResponse();
81
+	}
82
+
83
+	/**
84
+	 * @return ClipboardService|object
85
+	 */
86
+	protected function getClipboardService()
87
+	{
88
+		return GeneralUtility::makeInstance(ClipboardService::class);
89
+	}
90
+
91
+	/**
92
+	 * @return ContentService|object
93
+	 */
94
+	protected function getContentService()
95
+	{
96
+		return GeneralUtility::makeInstance(ContentService::class);
97
+	}
98 98
 
99 99
 }
Please login to merge, or discard this patch.
Classes/Module/ModuleLoader.php 2 patches
Indentation   +999 added lines, -999 removed lines patch added patch discarded remove patch
@@ -37,1004 +37,1004 @@
 block discarded – undo
37 37
 class ModuleLoader
38 38
 {
39 39
 
40
-    /**
41
-     * Define the default main module
42
-     */
43
-    const DEFAULT_MAIN_MODULE = 'content';
44
-
45
-    /**
46
-     * Define the default pid
47
-     */
48
-    const DEFAULT_PID = 0;
49
-
50
-    /**
51
-     * The type of data being listed (which corresponds to a table name in TCA)
52
-     *
53
-     * @var string
54
-     */
55
-    protected $dataType;
56
-
57
-    /**
58
-     * @var string
59
-     */
60
-    protected $defaultPid;
61
-
62
-    /**
63
-     * @var bool
64
-     */
65
-    protected $isPidIgnored = false;
66
-
67
-    /**
68
-     * @var bool
69
-     */
70
-    protected $showPageTree = false;
71
-
72
-    /**
73
-     * @var bool
74
-     */
75
-    protected $isShown = true;
76
-
77
-    /**
78
-     * @var string
79
-     */
80
-    protected $access;
81
-
82
-    /**
83
-     * @var string
84
-     */
85
-    protected $mainModule;
86
-
87
-    /**
88
-     * @var string
89
-     */
90
-    protected $position = '';
91
-
92
-    /**
93
-     * @var string
94
-     */
95
-    protected $icon;
96
-
97
-    /**
98
-     * @var string
99
-     */
100
-    protected $moduleLanguageFile;
101
-
102
-    /**
103
-     * The module key such as m1, m2.
104
-     *
105
-     * @var string
106
-     */
107
-    protected $moduleKey = 'm1';
108
-
109
-    /**
110
-     * @var string[]
111
-     */
112
-    protected $additionalJavaScriptFiles = [];
113
-
114
-    /**
115
-     * @var string[]
116
-     */
117
-    protected $additionalStyleSheetFiles = [];
118
-
119
-    /**
120
-     * @var array
121
-     */
122
-    protected $components = [];
123
-
124
-    /**
125
-     * @param string $dataType
126
-     */
127
-    public function __construct($dataType = null)
128
-    {
129
-        $this->dataType = $dataType;
130
-
131
-        // Initialize components
132
-        $this->components = [
133
-            ModulePosition::DOC_HEADER => [
134
-                ModulePosition::TOP => [
135
-                    ModulePosition::LEFT => [],
136
-                    ModulePosition::RIGHT => [
137
-                        ToolButton::class,
138
-                    ],
139
-                ],
140
-                ModulePosition::BOTTOM => [
141
-                    ModulePosition::LEFT => [
142
-                        NewButton::class,
143
-                        BackViewHelper::class,
144
-                    ],
145
-                    ModulePosition::RIGHT => [],
146
-                ],
147
-            ],
148
-            ModulePosition::GRID => [
149
-                ModulePosition::TOP => [
150
-                    RelationsCheck::class,
151
-                    #\Fab\Vidi\View\Tab\DataTypeTab::class,
152
-                ],
153
-                ModulePosition::BUTTONS => [
154
-                    EditButton::class,
155
-                    DeleteButton::class,
156
-                ],
157
-                ModulePosition::BOTTOM => [],
158
-            ],
159
-            ModulePosition::MENU_MASS_ACTION => [
160
-                ExportXlsMenuItem::class,
161
-                ExportXmlMenuItem::class,
162
-                ExportCsvMenuItem::class,
163
-                DividerMenuItem::class,
164
-                MassDeleteMenuItem::class,
165
-                #\Fab\Vidi\View\MenuItem\MassEditMenuItem::class,
166
-            ],
167
-        ];
168
-    }
169
-
170
-    /**
171
-     * Tell whether a module is already registered.
172
-     *
173
-     * @param string $dataType
174
-     * @return bool
175
-     */
176
-    public function isRegistered($dataType): bool
177
-    {
178
-        $internalModuleSignature = $this->getInternalModuleSignature($dataType);
179
-        return !empty($GLOBALS['TBE_MODULES_EXT']['vidi'][$internalModuleSignature]);
180
-    }
181
-
182
-    /**
183
-     * @return array
184
-     */
185
-    protected function getExistingInternalConfiguration(): array
186
-    {
187
-        $internalModuleSignature = $this->getInternalModuleSignature();
188
-        return $GLOBALS['TBE_MODULES_EXT']['vidi'][$internalModuleSignature] ?? [];
189
-    }
190
-
191
-    /**
192
-     * @return array
193
-     */
194
-    protected function getExistingMainConfiguration(): array
195
-    {
196
-        $moduleSignature = $this->computeMainModule() . '_' . $this->getInternalModuleSignature();
197
-        return $GLOBALS['TBE_MODULES']['_configuration'][$moduleSignature] ?? [];
198
-    }
199
-
200
-    /**
201
-     * @return string
202
-     */
203
-    protected function computeMainModule(): string
204
-    {
205
-        $existingConfiguration = $this->getExistingInternalConfiguration();
206
-
207
-        if ($this->mainModule !== null) {
208
-            $mainModule = $this->mainModule;
209
-        } elseif (!empty($existingConfiguration['mainModule'])) { // existing configuration may override.
210
-            $mainModule = $existingConfiguration['mainModule'];
211
-        } else {
212
-            $mainModule = self::DEFAULT_MAIN_MODULE; //default value.
213
-        }
214
-        return $mainModule;
215
-    }
216
-
217
-    /**
218
-     * @return string
219
-     */
220
-    protected function computeDefaultPid(): string
221
-    {
222
-        $existingConfiguration = $this->getExistingInternalConfiguration();
223
-
224
-        if ($this->defaultPid !== null) {
225
-            $defaultPid = $this->defaultPid;
226
-        } elseif (!empty($existingConfiguration['defaultPid'])) { // existing configuration may override.
227
-            $defaultPid = $existingConfiguration['defaultPid'];
228
-        } else {
229
-            $defaultPid = self::DEFAULT_PID; //default value.
230
-        }
231
-        return $defaultPid;
232
-    }
233
-
234
-    /**
235
-     * @return array
236
-     */
237
-    protected function computeAdditionalJavaScriptFiles(): array
238
-    {
239
-        $additionalJavaScriptFiles = $this->additionalJavaScriptFiles;
240
-
241
-        // Possible merge of existing javascript files.
242
-        $existingConfiguration = $this->getExistingInternalConfiguration();
243
-        if (!empty($existingConfiguration['additionalJavaScriptFiles'])) {
244
-            $additionalJavaScriptFiles = array_merge($additionalJavaScriptFiles, $existingConfiguration['additionalJavaScriptFiles']);
245
-        }
246
-
247
-        return $additionalJavaScriptFiles;
248
-    }
249
-
250
-    /**
251
-     * @return array
252
-     */
253
-    protected function computeAdditionalStyleSheetFiles(): array
254
-    {
255
-        $additionalStyleSheetFiles = $this->additionalStyleSheetFiles;
256
-
257
-        // Possible merge of existing style sheets.
258
-        $existingConfiguration = $this->getExistingInternalConfiguration();
259
-        if (!empty($existingConfiguration['additionalStyleSheetFiles'])) {
260
-            $additionalStyleSheetFiles = array_merge($additionalStyleSheetFiles, $existingConfiguration['additionalStyleSheetFiles']);
261
-        }
262
-
263
-        return $additionalStyleSheetFiles;
264
-    }
265
-
266
-    /**
267
-     * @return array
268
-     */
269
-    protected function computeComponents(): array
270
-    {
271
-        // We override the config in any case. See if we need more than that.
272
-        return $this->components;
273
-    }
274
-
275
-    /**
276
-     * Register the module in two places: core + vidi internal.
277
-     *
278
-     * @return $this
279
-     */
280
-    public function register(): self
281
-    {
282
-        // Internal Vidi module registration.
283
-        $configuration = [];
284
-        $configuration['dataType'] = $this->dataType;
285
-        $configuration['mainModule'] = $this->computeMainModule();
286
-        $configuration['defaultPid'] = $this->computeDefaultPid();
287
-        $configuration['additionalJavaScriptFiles'] = $this->computeAdditionalJavaScriptFiles();
288
-        $configuration['additionalStyleSheetFiles'] = $this->computeAdditionalStyleSheetFiles();
289
-        $configuration['components'] = $this->computeComponents();
290
-        $configuration['isPidIgnored'] = $this->isPidIgnored;
291
-
292
-        $internalModuleSignature = $this->getInternalModuleSignature();
293
-        $GLOBALS['TBE_MODULES_EXT']['vidi'][$internalModuleSignature] = $configuration;
294
-
295
-        // Core module registration.
296
-        // Register and displays module in the BE only if told, default is "true".
297
-        if ($this->isShown) {
298
-
299
-            $moduleConfiguration = [];
300
-            #$moduleConfiguration['routeTarget'] = \Fab\Vidi\Controller\ContentController::class . '::mainAction', // what to do here?
301
-            $moduleConfiguration['access'] = $this->getAccess();
302
-            $moduleConfiguration['labels'] = $this->getModuleLanguageFile();
303
-            $icon = $this->getIcon();
304
-            if ($icon) {
305
-                $moduleConfiguration['icon'] = $icon;
306
-            }
307
-
308
-            if ($this->showPageTree) {
309
-                $moduleConfiguration['navigationComponentId'] = 'TYPO3/CMS/Backend/PageTree/PageTreeElement';
310
-                $moduleConfiguration['inheritNavigationComponentFromMainModule'] = true;
311
-            } else {
312
-                $moduleConfiguration['inheritNavigationComponentFromMainModule'] = true;
313
-            }
314
-
315
-            ExtensionUtility::registerModule(
316
-                'Vidi',
317
-                $this->computeMainModule(),
318
-                $this->dataType . '_' . $this->moduleKey,
319
-                $this->position,
320
-                [
321
-                    ContentController::class => 'index, list, delete, update, edit, copy, move, localize, sort, copyClipboard, moveClipboard',
322
-                    ToolController::class => 'welcome, work',
323
-                    FacetController::class => 'autoSuggest, autoSuggests',
324
-                    SelectionController::class => 'edit, update, create, delete, list, show',
325
-                    UserPreferencesController::class => 'save',
326
-                    ClipboardController::class => 'save, flush, show',
327
-                ],
328
-                $moduleConfiguration
329
-            );
330
-        }
331
-        return $this;
332
-    }
333
-
334
-    /**
335
-     * Return the module code for a BE module.
336
-     *
337
-     * @return string
338
-     */
339
-    public function getSignature(): string
340
-    {
341
-        $signature = GeneralUtility::_GP(Parameter::MODULE);
342
-        $trimmedSignature = trim($signature, '/');
343
-        return str_replace(['/', 'module_'], ['_', ''], $trimmedSignature);
344
-    }
345
-
346
-    /**
347
-     * Returns the current pid.
348
-     *
349
-     * @return int
350
-     */
351
-    public function getCurrentPid(): int
352
-    {
353
-        return GeneralUtility::_GET(Parameter::PID) > 0 ? (int)GeneralUtility::_GET(Parameter::PID) : 0;
354
-    }
355
-
356
-    /**
357
-     * Return the module URL.
358
-     *
359
-     * @param array $additionalParameters
360
-     * @return string
361
-     */
362
-    public function getModuleUrl(array $additionalParameters = []): string
363
-    {
364
-        $moduleCode = $this->getSignature();
365
-
366
-        // And don't forget the pid!
367
-        if (GeneralUtility::_GET(Parameter::PID)) {
368
-            $additionalParameters[Parameter::PID] = GeneralUtility::_GET(Parameter::PID);
369
-        }
370
-
371
-        return BackendUtility::getModuleUrl($moduleCode, $additionalParameters);
372
-    }
373
-
374
-    /**
375
-     * Return the parameter prefix for a BE module.
376
-     *
377
-     * @return string
378
-     */
379
-    public function getParameterPrefix(): string
380
-    {
381
-        return 'tx_vidi_' . strtolower($this->getSignature());
382
-    }
383
-
384
-    /**
385
-     * Return a configuration key or the entire module configuration array if not key is given.
386
-     *
387
-     * @param string $key
388
-     * @return mixed
389
-     */
390
-    public function getModuleConfiguration($key = '')
391
-    {
392
-
393
-        $vidiModuleCode = $this->getSignature();
394
-
395
-        // Module code must exist
396
-        if (empty($GLOBALS['TBE_MODULES_EXT']['vidi'][$vidiModuleCode])) {
397
-            $message = sprintf('Invalid or not existing module code "%s"', $vidiModuleCode);
398
-            throw new InvalidKeyInArrayException($message, 1375092053);
399
-        }
400
-
401
-        $result = $GLOBALS['TBE_MODULES_EXT']['vidi'][$vidiModuleCode];
402
-
403
-        if (!empty($key)) {
404
-            if (isset($result[$key])) {
405
-                $result = $result[$key];
406
-            } else {
407
-                // key must exist
408
-                $message = sprintf('Invalid key configuration "%s"', $key);
409
-                throw new InvalidKeyInArrayException($message, 1375092054);
410
-            }
411
-        }
412
-        return $result;
413
-    }
414
-
415
-    /**
416
-     * @param string $icon
417
-     * @return $this
418
-     */
419
-    public function setIcon($icon): self
420
-    {
421
-        $this->icon = $icon;
422
-        return $this;
423
-    }
424
-
425
-    /**
426
-     * @return string
427
-     */
428
-    protected function getIcon(): string
429
-    {
430
-        $moduleConfiguration = $this->getExistingMainConfiguration();
431
-
432
-
433
-        if ($this->icon) {
434
-            $icon = $this->icon;
435
-        } elseif ($moduleConfiguration['icon']) { // existing configuration may override.
436
-            $icon = $moduleConfiguration['icon'];
437
-        } else {
438
-            $icon = ''; //default value.
439
-        }
440
-
441
-        return $icon;
442
-    }
443
-
444
-    /**
445
-     * @param string $mainModule
446
-     * @return $this
447
-     */
448
-    public function setMainModule($mainModule): self
449
-    {
450
-        $this->mainModule = $mainModule;
451
-        return $this;
452
-    }
453
-
454
-    /**
455
-     * @return string
456
-     */
457
-    public function getMainModule(): string
458
-    {
459
-        if ($this->mainModule === null) {
460
-            $this->mainModule = $this->getModuleConfiguration('mainModule');
461
-        }
462
-        return $this->mainModule;
463
-    }
464
-
465
-    /**
466
-     * @param string $moduleLanguageFile
467
-     * @return $this
468
-     */
469
-    public function setModuleLanguageFile($moduleLanguageFile): self
470
-    {
471
-        $this->moduleLanguageFile = $moduleLanguageFile;
472
-        return $this;
473
-    }
474
-
475
-    /**
476
-     * @param string $component
477
-     * @return $this
478
-     */
479
-    public function removeComponentFromDocHeader(string $component): self
480
-    {
481
-        foreach ($this->components[ModulePosition::DOC_HEADER] as $verticalPosition => $docHeaders) {
482
-            foreach ($docHeaders as $horizontalPosition => $docHeader) {
483
-
484
-                $index = array_search($component, $docHeader, true);
485
-                if ($index !== false) {
486
-                    // $verticalPosition: top or bottom
487
-                    // $horizontalPosition: left or right
488
-                    unset($this->components[ModulePosition::DOC_HEADER][$verticalPosition][$horizontalPosition][$index]);
489
-                }
490
-            }
491
-        }
492
-        return $this;
493
-    }
494
-
495
-    /**
496
-     * @param bool $isPidIgnored
497
-     * @return $this
498
-     */
499
-    public function ignorePid(bool $isPidIgnored): self
500
-    {
501
-        $this->isPidIgnored = $isPidIgnored;
502
-        return $this;
503
-    }
504
-
505
-    /**
506
-     * @return bool
507
-     */
508
-    public function isPidIgnored(): bool
509
-    {
510
-        return $this->getModuleConfiguration('isPidIgnored');
511
-    }
512
-
513
-    /**
514
-     * @param string $component
515
-     * @return bool
516
-     */
517
-    public function hasComponentInDocHeader(string $component): bool
518
-    {
519
-        foreach ($this->getModuleConfiguration('components')[ModulePosition::DOC_HEADER] as $verticalPosition => $docHeaders) {
520
-            foreach ($docHeaders as $horizontalPosition => $docHeader) {
521
-
522
-                $index = array_search($component, $docHeader, true);
523
-                if ($index !== false) {
524
-                    return true;
525
-                }
526
-            }
527
-        }
528
-        return false;
529
-    }
530
-
531
-    /**
532
-     * @return string
533
-     */
534
-    protected function getModuleLanguageFile(): string
535
-    {
536
-        $moduleConfiguration = $this->getExistingMainConfiguration();
537
-
538
-        if ($this->moduleLanguageFile) {
539
-            $moduleLanguageFile = $this->moduleLanguageFile;
540
-        } elseif ($moduleConfiguration['labels']) { // existing configuration may override.
541
-            $moduleLanguageFile = $moduleConfiguration['labels'];
542
-        } else {
543
-            $moduleLanguageFile = ''; //default value.
544
-        }
545
-
546
-        return $moduleLanguageFile;
547
-    }
548
-
549
-    /**
550
-     * @param string $position
551
-     * @return $this
552
-     */
553
-    public function setPosition($position): self
554
-    {
555
-        $this->position = $position;
556
-        return $this;
557
-    }
558
-
559
-    /**
560
-     * @return string
561
-     */
562
-    public function getPosition(): string
563
-    {
564
-        return $this->position;
565
-    }
566
-
567
-    /**
568
-     * @param array $files
569
-     * @return $this
570
-     */
571
-    public function addJavaScriptFiles(array $files): self
572
-    {
573
-        foreach ($files as $file) {
574
-            $this->additionalJavaScriptFiles[] = $file;
575
-        }
576
-        return $this;
577
-    }
578
-
579
-    /**
580
-     * @param string $fileNameAndPath
581
-     * @return $this
582
-     */
583
-    public function addJavaScriptFile($fileNameAndPath): self
584
-    {
585
-        $this->additionalJavaScriptFiles[] = $fileNameAndPath;
586
-        return $this;
587
-    }
588
-
589
-    /**
590
-     * @param array $files
591
-     * @return $this
592
-     */
593
-    public function addStyleSheetFiles(array $files): self
594
-    {
595
-        foreach ($files as $file) {
596
-            $this->additionalStyleSheetFiles[] = $file;
597
-        }
598
-        return $this;
599
-    }
600
-
601
-    /**
602
-     * @param string $fileNameAndPath
603
-     * @return $this
604
-     */
605
-    public function addStyleSheetFile($fileNameAndPath): self
606
-    {
607
-        $this->additionalStyleSheetFiles[] = $fileNameAndPath;
608
-        return $this;
609
-    }
610
-
611
-    /**
612
-     * @return string
613
-     */
614
-    public function getDataType(): string
615
-    {
616
-        if ($this->dataType === null) {
617
-            $this->dataType = $this->getModuleConfiguration('dataType');
618
-        }
619
-        return $this->dataType;
620
-    }
621
-
622
-    /**
623
-     * @return array
624
-     */
625
-    public function getDataTypes(): array
626
-    {
627
-        $dataTypes = [];
628
-        foreach ($GLOBALS['TBE_MODULES_EXT']['vidi'] as $module) {
629
-            $dataTypes[] = $module['dataType'];
630
-        }
631
-        return $dataTypes;
632
-    }
633
-
634
-    /**
635
-     * @param string $dataType
636
-     * @return $this
637
-     */
638
-    public function setDataType($dataType): self
639
-    {
640
-        $this->dataType = $dataType;
641
-        return $this;
642
-    }
643
-
644
-    /**
645
-     * @return int
646
-     */
647
-    public function getDefaultPid(): int
648
-    {
649
-        if (empty($this->defaultPid)) {
650
-            $this->defaultPid = $this->getModuleConfiguration('defaultPid');
651
-        }
652
-        return (int)$this->defaultPid;
653
-    }
654
-
655
-    /**
656
-     * @param string $defaultPid
657
-     * @return $this
658
-     */
659
-    public function setDefaultPid($defaultPid): self
660
-    {
661
-        $this->defaultPid = $defaultPid;
662
-        return $this;
663
-    }
664
-
665
-    /**
666
-     * @param bool $isPageTreeShown
667
-     * @return $this
668
-     */
669
-    public function showPageTree($isPageTreeShown): self
670
-    {
671
-        $this->showPageTree = $isPageTreeShown;
672
-        return $this;
673
-    }
674
-
675
-    /**
676
-     * @param string $isShown
677
-     * @return $this
678
-     */
679
-    public function isShown($isShown): self
680
-    {
681
-        $this->isShown = $isShown;
682
-        return $this;
683
-    }
684
-
685
-    /**
686
-     * @return $array
687
-     */
688
-    public function getDocHeaderTopLeftComponents()
689
-    {
690
-        $configuration = $this->getModuleConfiguration();
691
-        return $configuration['components'][ModulePosition::DOC_HEADER][ModulePosition::TOP][ModulePosition::LEFT];
692
-    }
693
-
694
-    /**
695
-     * @param array $components
696
-     * @return $this
697
-     */
698
-    public function setDocHeaderTopLeftComponents(array $components): self
699
-    {
700
-        $this->components[ModulePosition::DOC_HEADER][ModulePosition::TOP][ModulePosition::LEFT] = $components;
701
-        return $this;
702
-    }
703
-
704
-    /**
705
-     * @param string|array $components
706
-     * @return $this
707
-     */
708
-    public function addDocHeaderTopLeftComponents($components): self
709
-    {
710
-        if (is_string($components)) {
711
-            $components = [$components];
712
-        }
713
-        $currentComponents = $this->components[ModulePosition::DOC_HEADER][ModulePosition::TOP][ModulePosition::LEFT];
714
-        $this->components[ModulePosition::DOC_HEADER][ModulePosition::TOP][ModulePosition::LEFT] = array_merge($currentComponents, $components);
715
-        return $this;
716
-    }
717
-
718
-    /**
719
-     * @return $array
720
-     */
721
-    public function getDocHeaderTopRightComponents()
722
-    {
723
-        $configuration = $this->getModuleConfiguration();
724
-        return $configuration['components'][ModulePosition::DOC_HEADER][ModulePosition::TOP][ModulePosition::RIGHT];
725
-    }
726
-
727
-    /**
728
-     * @param array $components
729
-     * @return $this
730
-     */
731
-    public function setDocHeaderTopRightComponents(array $components): self
732
-    {
733
-        $this->components[ModulePosition::DOC_HEADER][ModulePosition::TOP][ModulePosition::RIGHT] = $components;
734
-        return $this;
735
-    }
736
-
737
-    /**
738
-     * @param string|array $components
739
-     * @return $this
740
-     */
741
-    public function addDocHeaderTopRightComponents($components): self
742
-    {
743
-        if (is_string($components)) {
744
-            $components = [$components];
745
-        }
746
-        $currentComponents = $this->components[ModulePosition::DOC_HEADER][ModulePosition::TOP][ModulePosition::RIGHT];
747
-        $this->components[ModulePosition::DOC_HEADER][ModulePosition::TOP][ModulePosition::RIGHT] = array_merge($currentComponents, $components);
748
-        return $this;
749
-    }
750
-
751
-    /**
752
-     * @return $array
753
-     */
754
-    public function getDocHeaderBottomLeftComponents()
755
-    {
756
-        $configuration = $this->getModuleConfiguration();
757
-        return $configuration['components'][ModulePosition::DOC_HEADER][ModulePosition::BOTTOM][ModulePosition::LEFT];
758
-    }
759
-
760
-    /**
761
-     * @param array $components
762
-     * @return $this
763
-     */
764
-    public function setDocHeaderBottomLeftComponents(array $components): self
765
-    {
766
-        $this->components[ModulePosition::DOC_HEADER][ModulePosition::BOTTOM][ModulePosition::LEFT] = $components;
767
-        return $this;
768
-    }
769
-
770
-    /**
771
-     * @param string|array $components
772
-     * @return $this
773
-     */
774
-    public function addDocHeaderBottomLeftComponents($components): self
775
-    {
776
-        if (is_string($components)) {
777
-            $components = [$components];
778
-        }
779
-        $currentComponents = $this->components[ModulePosition::DOC_HEADER][ModulePosition::BOTTOM][ModulePosition::LEFT];
780
-        $this->components[ModulePosition::DOC_HEADER][ModulePosition::BOTTOM][ModulePosition::LEFT] = array_merge($currentComponents, $components);
781
-        return $this;
782
-    }
783
-
784
-    /**
785
-     * @return $array
786
-     */
787
-    public function getDocHeaderBottomRightComponents()
788
-    {
789
-        $configuration = $this->getModuleConfiguration();
790
-        return $configuration['components'][ModulePosition::DOC_HEADER][ModulePosition::BOTTOM][ModulePosition::RIGHT];
791
-    }
792
-
793
-    /**
794
-     * @param array $components
795
-     * @return $this
796
-     */
797
-    public function setDocHeaderBottomRightComponents(array $components): self
798
-    {
799
-        $this->components[ModulePosition::DOC_HEADER][ModulePosition::BOTTOM][ModulePosition::RIGHT] = $components;
800
-        return $this;
801
-    }
802
-
803
-    /**
804
-     * @param string|array $components
805
-     * @return $this
806
-     */
807
-    public function addDocHeaderBottomRightComponents($components): self
808
-    {
809
-        if (is_string($components)) {
810
-            $components = [$components];
811
-        }
812
-        $currentComponents = $this->components[ModulePosition::DOC_HEADER][ModulePosition::BOTTOM][ModulePosition::RIGHT];
813
-        $this->components[ModulePosition::DOC_HEADER][ModulePosition::BOTTOM][ModulePosition::RIGHT] = array_merge($currentComponents, $components);
814
-        return $this;
815
-    }
816
-
817
-    /**
818
-     * @return $array
819
-     */
820
-    public function getGridTopComponents()
821
-    {
822
-        $configuration = $this->getModuleConfiguration();
823
-        return $configuration['components'][ModulePosition::GRID][ModulePosition::TOP];
824
-    }
825
-
826
-    /**
827
-     * @param array $components
828
-     * @return $this
829
-     */
830
-    public function setGridTopComponents(array $components): self
831
-    {
832
-        $this->components[ModulePosition::GRID][ModulePosition::TOP] = $components;
833
-        return $this;
834
-    }
835
-
836
-    /**
837
-     * @param string|array $components
838
-     * @return $this
839
-     */
840
-    public function addGridTopComponents($components): self
841
-    {
842
-        if (is_string($components)) {
843
-            $components = [$components];
844
-        }
845
-        $currentComponents = $this->components[ModulePosition::GRID][ModulePosition::TOP];
846
-        $this->components[ModulePosition::GRID][ModulePosition::TOP] = array_merge($currentComponents, $components);
847
-        return $this;
848
-    }
849
-
850
-    /**
851
-     * @return mixed $array
852
-     */
853
-    public function getGridBottomComponents()
854
-    {
855
-        $configuration = $this->getModuleConfiguration();
856
-        return $configuration['components'][ModulePosition::GRID][ModulePosition::BOTTOM];
857
-    }
858
-
859
-    /**
860
-     * @param array $components
861
-     * @return $this
862
-     */
863
-    public function setGridBottomComponents(array $components): self
864
-    {
865
-        $this->components[ModulePosition::GRID][ModulePosition::BOTTOM] = $components;
866
-        return $this;
867
-    }
868
-
869
-    /**
870
-     * @param string|array $components
871
-     * @return $this
872
-     */
873
-    public function addGridBottomComponents($components): self
874
-    {
875
-        if (is_string($components)) {
876
-            $components = [$components];
877
-        }
878
-        $currentComponents = $this->components[ModulePosition::GRID][ModulePosition::BOTTOM];
879
-        $this->components[ModulePosition::GRID][ModulePosition::BOTTOM] = array_merge($currentComponents, $components);
880
-        return $this;
881
-    }
882
-
883
-    /**
884
-     * @return $array
885
-     */
886
-    public function getGridButtonsComponents()
887
-    {
888
-        $configuration = $this->getModuleConfiguration();
889
-        return $configuration['components'][ModulePosition::GRID][ModulePosition::BUTTONS];
890
-    }
891
-
892
-    /**
893
-     * @param array $components
894
-     * @return $this
895
-     */
896
-    public function setGridButtonsComponents(array $components): self
897
-    {
898
-        $this->components[ModulePosition::GRID][ModulePosition::BUTTONS] = $components;
899
-        return $this;
900
-    }
901
-
902
-    /**
903
-     * @param string|array $components
904
-     * @return $this
905
-     */
906
-    public function addGridButtonsComponents($components): self
907
-    {
908
-        if (is_string($components)) {
909
-            $components = [$components];
910
-        }
911
-        $currentComponents = $this->components[ModulePosition::GRID][ModulePosition::BUTTONS];
912
-        $this->components[ModulePosition::GRID][ModulePosition::BUTTONS] = array_merge($components, $currentComponents);
913
-        return $this;
914
-    }
915
-
916
-    /**
917
-     * @return $array
918
-     */
919
-    public function getMenuMassActionComponents()
920
-    {
921
-        $configuration = $this->getModuleConfiguration();
922
-        return $configuration['components'][ModulePosition::MENU_MASS_ACTION];
923
-    }
924
-
925
-    /**
926
-     * @param array $components
927
-     * @return $this
928
-     */
929
-    public function setMenuMassActionComponents(array $components): self
930
-    {
931
-        $this->components[ModulePosition::MENU_MASS_ACTION] = $components;
932
-        return $this;
933
-    }
934
-
935
-    /**
936
-     * @param string|array $components
937
-     * @return $this
938
-     */
939
-    public function addMenuMassActionComponents($components): self
940
-    {
941
-        if (is_string($components)) {
942
-            $components = [$components];
943
-        }
944
-        $currentComponents = $this->components[ModulePosition::MENU_MASS_ACTION];
945
-        $this->components[ModulePosition::MENU_MASS_ACTION] = array_merge($components, $currentComponents);
946
-        return $this;
947
-    }
948
-
949
-    /**
950
-     * @return string
951
-     */
952
-    protected function getAccess(): string
953
-    {
954
-        $moduleConfiguration = $this->getExistingMainConfiguration();
955
-
956
-        if ($this->access !== null) {
957
-            $access = $this->access;
958
-        } elseif (!empty($moduleConfiguration['access'])) { // existing configuration may override.
959
-            $access = $moduleConfiguration['access'];
960
-        } else {
961
-            $access = Access::USER; //default value.
962
-        }
963
-        return $access;
964
-    }
965
-
966
-    /**
967
-     * @param string $access
968
-     * @return $this
969
-     */
970
-    public function setAccess($access): self
971
-    {
972
-        $this->access = $access;
973
-        return $this;
974
-    }
975
-
976
-    /**
977
-     * @return \string[]
978
-     */
979
-    public function getAdditionalJavaScriptFiles(): array
980
-    {
981
-        if (empty($this->additionalJavaScriptFiles)) {
982
-            $this->additionalJavaScriptFiles = $this->getModuleConfiguration('additionalJavaScriptFiles');
983
-        }
984
-        return $this->additionalJavaScriptFiles;
985
-    }
986
-
987
-    /**
988
-     * @return \string[]
989
-     */
990
-    public function getAdditionalStyleSheetFiles(): array
991
-    {
992
-        if (empty($this->additionalStyleSheetFiles)) {
993
-            $this->additionalStyleSheetFiles = $this->getModuleConfiguration('additionalStyleSheetFiles');
994
-        }
995
-        return $this->additionalStyleSheetFiles;
996
-    }
997
-
998
-    /**
999
-     * @return array
1000
-     */
1001
-    public function getComponents(): array
1002
-    {
1003
-        return $this->components;
1004
-    }
1005
-
1006
-    /**
1007
-     * @param string $pluginName
1008
-     * @return bool
1009
-     */
1010
-    public function hasPlugin($pluginName = ''): bool
1011
-    {
1012
-        $parameterPrefix = $this->getParameterPrefix();
1013
-        $parameters = GeneralUtility::_GET($parameterPrefix);
1014
-
1015
-        $hasPlugin = !empty($parameters['plugins']) && is_array($parameters['plugins']);
1016
-        if ($hasPlugin && $pluginName) {
1017
-            $hasPlugin = in_array($pluginName, $parameters['plugins']);
1018
-        }
1019
-        return $hasPlugin;
1020
-    }
1021
-
1022
-    /**
1023
-     * Compute the internal module code
1024
-     *
1025
-     * @param null|string $dataType
1026
-     * @return string
1027
-     */
1028
-    protected function getInternalModuleSignature($dataType = null): string
1029
-    {
1030
-        // Else we forge the module signature
1031
-        if ($dataType === null) {
1032
-            $dataType = $this->dataType;
1033
-        }
1034
-        $subModuleName = $dataType . '_' . $this->moduleKey;
1035
-
1036
-        $mainModule = $this->mainModule ?: self::DEFAULT_MAIN_MODULE;
1037
-        return $mainModule . '_Vidi' . GeneralUtility::underscoredToUpperCamelCase($subModuleName);
1038
-    }
40
+	/**
41
+	 * Define the default main module
42
+	 */
43
+	const DEFAULT_MAIN_MODULE = 'content';
44
+
45
+	/**
46
+	 * Define the default pid
47
+	 */
48
+	const DEFAULT_PID = 0;
49
+
50
+	/**
51
+	 * The type of data being listed (which corresponds to a table name in TCA)
52
+	 *
53
+	 * @var string
54
+	 */
55
+	protected $dataType;
56
+
57
+	/**
58
+	 * @var string
59
+	 */
60
+	protected $defaultPid;
61
+
62
+	/**
63
+	 * @var bool
64
+	 */
65
+	protected $isPidIgnored = false;
66
+
67
+	/**
68
+	 * @var bool
69
+	 */
70
+	protected $showPageTree = false;
71
+
72
+	/**
73
+	 * @var bool
74
+	 */
75
+	protected $isShown = true;
76
+
77
+	/**
78
+	 * @var string
79
+	 */
80
+	protected $access;
81
+
82
+	/**
83
+	 * @var string
84
+	 */
85
+	protected $mainModule;
86
+
87
+	/**
88
+	 * @var string
89
+	 */
90
+	protected $position = '';
91
+
92
+	/**
93
+	 * @var string
94
+	 */
95
+	protected $icon;
96
+
97
+	/**
98
+	 * @var string
99
+	 */
100
+	protected $moduleLanguageFile;
101
+
102
+	/**
103
+	 * The module key such as m1, m2.
104
+	 *
105
+	 * @var string
106
+	 */
107
+	protected $moduleKey = 'm1';
108
+
109
+	/**
110
+	 * @var string[]
111
+	 */
112
+	protected $additionalJavaScriptFiles = [];
113
+
114
+	/**
115
+	 * @var string[]
116
+	 */
117
+	protected $additionalStyleSheetFiles = [];
118
+
119
+	/**
120
+	 * @var array
121
+	 */
122
+	protected $components = [];
123
+
124
+	/**
125
+	 * @param string $dataType
126
+	 */
127
+	public function __construct($dataType = null)
128
+	{
129
+		$this->dataType = $dataType;
130
+
131
+		// Initialize components
132
+		$this->components = [
133
+			ModulePosition::DOC_HEADER => [
134
+				ModulePosition::TOP => [
135
+					ModulePosition::LEFT => [],
136
+					ModulePosition::RIGHT => [
137
+						ToolButton::class,
138
+					],
139
+				],
140
+				ModulePosition::BOTTOM => [
141
+					ModulePosition::LEFT => [
142
+						NewButton::class,
143
+						BackViewHelper::class,
144
+					],
145
+					ModulePosition::RIGHT => [],
146
+				],
147
+			],
148
+			ModulePosition::GRID => [
149
+				ModulePosition::TOP => [
150
+					RelationsCheck::class,
151
+					#\Fab\Vidi\View\Tab\DataTypeTab::class,
152
+				],
153
+				ModulePosition::BUTTONS => [
154
+					EditButton::class,
155
+					DeleteButton::class,
156
+				],
157
+				ModulePosition::BOTTOM => [],
158
+			],
159
+			ModulePosition::MENU_MASS_ACTION => [
160
+				ExportXlsMenuItem::class,
161
+				ExportXmlMenuItem::class,
162
+				ExportCsvMenuItem::class,
163
+				DividerMenuItem::class,
164
+				MassDeleteMenuItem::class,
165
+				#\Fab\Vidi\View\MenuItem\MassEditMenuItem::class,
166
+			],
167
+		];
168
+	}
169
+
170
+	/**
171
+	 * Tell whether a module is already registered.
172
+	 *
173
+	 * @param string $dataType
174
+	 * @return bool
175
+	 */
176
+	public function isRegistered($dataType): bool
177
+	{
178
+		$internalModuleSignature = $this->getInternalModuleSignature($dataType);
179
+		return !empty($GLOBALS['TBE_MODULES_EXT']['vidi'][$internalModuleSignature]);
180
+	}
181
+
182
+	/**
183
+	 * @return array
184
+	 */
185
+	protected function getExistingInternalConfiguration(): array
186
+	{
187
+		$internalModuleSignature = $this->getInternalModuleSignature();
188
+		return $GLOBALS['TBE_MODULES_EXT']['vidi'][$internalModuleSignature] ?? [];
189
+	}
190
+
191
+	/**
192
+	 * @return array
193
+	 */
194
+	protected function getExistingMainConfiguration(): array
195
+	{
196
+		$moduleSignature = $this->computeMainModule() . '_' . $this->getInternalModuleSignature();
197
+		return $GLOBALS['TBE_MODULES']['_configuration'][$moduleSignature] ?? [];
198
+	}
199
+
200
+	/**
201
+	 * @return string
202
+	 */
203
+	protected function computeMainModule(): string
204
+	{
205
+		$existingConfiguration = $this->getExistingInternalConfiguration();
206
+
207
+		if ($this->mainModule !== null) {
208
+			$mainModule = $this->mainModule;
209
+		} elseif (!empty($existingConfiguration['mainModule'])) { // existing configuration may override.
210
+			$mainModule = $existingConfiguration['mainModule'];
211
+		} else {
212
+			$mainModule = self::DEFAULT_MAIN_MODULE; //default value.
213
+		}
214
+		return $mainModule;
215
+	}
216
+
217
+	/**
218
+	 * @return string
219
+	 */
220
+	protected function computeDefaultPid(): string
221
+	{
222
+		$existingConfiguration = $this->getExistingInternalConfiguration();
223
+
224
+		if ($this->defaultPid !== null) {
225
+			$defaultPid = $this->defaultPid;
226
+		} elseif (!empty($existingConfiguration['defaultPid'])) { // existing configuration may override.
227
+			$defaultPid = $existingConfiguration['defaultPid'];
228
+		} else {
229
+			$defaultPid = self::DEFAULT_PID; //default value.
230
+		}
231
+		return $defaultPid;
232
+	}
233
+
234
+	/**
235
+	 * @return array
236
+	 */
237
+	protected function computeAdditionalJavaScriptFiles(): array
238
+	{
239
+		$additionalJavaScriptFiles = $this->additionalJavaScriptFiles;
240
+
241
+		// Possible merge of existing javascript files.
242
+		$existingConfiguration = $this->getExistingInternalConfiguration();
243
+		if (!empty($existingConfiguration['additionalJavaScriptFiles'])) {
244
+			$additionalJavaScriptFiles = array_merge($additionalJavaScriptFiles, $existingConfiguration['additionalJavaScriptFiles']);
245
+		}
246
+
247
+		return $additionalJavaScriptFiles;
248
+	}
249
+
250
+	/**
251
+	 * @return array
252
+	 */
253
+	protected function computeAdditionalStyleSheetFiles(): array
254
+	{
255
+		$additionalStyleSheetFiles = $this->additionalStyleSheetFiles;
256
+
257
+		// Possible merge of existing style sheets.
258
+		$existingConfiguration = $this->getExistingInternalConfiguration();
259
+		if (!empty($existingConfiguration['additionalStyleSheetFiles'])) {
260
+			$additionalStyleSheetFiles = array_merge($additionalStyleSheetFiles, $existingConfiguration['additionalStyleSheetFiles']);
261
+		}
262
+
263
+		return $additionalStyleSheetFiles;
264
+	}
265
+
266
+	/**
267
+	 * @return array
268
+	 */
269
+	protected function computeComponents(): array
270
+	{
271
+		// We override the config in any case. See if we need more than that.
272
+		return $this->components;
273
+	}
274
+
275
+	/**
276
+	 * Register the module in two places: core + vidi internal.
277
+	 *
278
+	 * @return $this
279
+	 */
280
+	public function register(): self
281
+	{
282
+		// Internal Vidi module registration.
283
+		$configuration = [];
284
+		$configuration['dataType'] = $this->dataType;
285
+		$configuration['mainModule'] = $this->computeMainModule();
286
+		$configuration['defaultPid'] = $this->computeDefaultPid();
287
+		$configuration['additionalJavaScriptFiles'] = $this->computeAdditionalJavaScriptFiles();
288
+		$configuration['additionalStyleSheetFiles'] = $this->computeAdditionalStyleSheetFiles();
289
+		$configuration['components'] = $this->computeComponents();
290
+		$configuration['isPidIgnored'] = $this->isPidIgnored;
291
+
292
+		$internalModuleSignature = $this->getInternalModuleSignature();
293
+		$GLOBALS['TBE_MODULES_EXT']['vidi'][$internalModuleSignature] = $configuration;
294
+
295
+		// Core module registration.
296
+		// Register and displays module in the BE only if told, default is "true".
297
+		if ($this->isShown) {
298
+
299
+			$moduleConfiguration = [];
300
+			#$moduleConfiguration['routeTarget'] = \Fab\Vidi\Controller\ContentController::class . '::mainAction', // what to do here?
301
+			$moduleConfiguration['access'] = $this->getAccess();
302
+			$moduleConfiguration['labels'] = $this->getModuleLanguageFile();
303
+			$icon = $this->getIcon();
304
+			if ($icon) {
305
+				$moduleConfiguration['icon'] = $icon;
306
+			}
307
+
308
+			if ($this->showPageTree) {
309
+				$moduleConfiguration['navigationComponentId'] = 'TYPO3/CMS/Backend/PageTree/PageTreeElement';
310
+				$moduleConfiguration['inheritNavigationComponentFromMainModule'] = true;
311
+			} else {
312
+				$moduleConfiguration['inheritNavigationComponentFromMainModule'] = true;
313
+			}
314
+
315
+			ExtensionUtility::registerModule(
316
+				'Vidi',
317
+				$this->computeMainModule(),
318
+				$this->dataType . '_' . $this->moduleKey,
319
+				$this->position,
320
+				[
321
+					ContentController::class => 'index, list, delete, update, edit, copy, move, localize, sort, copyClipboard, moveClipboard',
322
+					ToolController::class => 'welcome, work',
323
+					FacetController::class => 'autoSuggest, autoSuggests',
324
+					SelectionController::class => 'edit, update, create, delete, list, show',
325
+					UserPreferencesController::class => 'save',
326
+					ClipboardController::class => 'save, flush, show',
327
+				],
328
+				$moduleConfiguration
329
+			);
330
+		}
331
+		return $this;
332
+	}
333
+
334
+	/**
335
+	 * Return the module code for a BE module.
336
+	 *
337
+	 * @return string
338
+	 */
339
+	public function getSignature(): string
340
+	{
341
+		$signature = GeneralUtility::_GP(Parameter::MODULE);
342
+		$trimmedSignature = trim($signature, '/');
343
+		return str_replace(['/', 'module_'], ['_', ''], $trimmedSignature);
344
+	}
345
+
346
+	/**
347
+	 * Returns the current pid.
348
+	 *
349
+	 * @return int
350
+	 */
351
+	public function getCurrentPid(): int
352
+	{
353
+		return GeneralUtility::_GET(Parameter::PID) > 0 ? (int)GeneralUtility::_GET(Parameter::PID) : 0;
354
+	}
355
+
356
+	/**
357
+	 * Return the module URL.
358
+	 *
359
+	 * @param array $additionalParameters
360
+	 * @return string
361
+	 */
362
+	public function getModuleUrl(array $additionalParameters = []): string
363
+	{
364
+		$moduleCode = $this->getSignature();
365
+
366
+		// And don't forget the pid!
367
+		if (GeneralUtility::_GET(Parameter::PID)) {
368
+			$additionalParameters[Parameter::PID] = GeneralUtility::_GET(Parameter::PID);
369
+		}
370
+
371
+		return BackendUtility::getModuleUrl($moduleCode, $additionalParameters);
372
+	}
373
+
374
+	/**
375
+	 * Return the parameter prefix for a BE module.
376
+	 *
377
+	 * @return string
378
+	 */
379
+	public function getParameterPrefix(): string
380
+	{
381
+		return 'tx_vidi_' . strtolower($this->getSignature());
382
+	}
383
+
384
+	/**
385
+	 * Return a configuration key or the entire module configuration array if not key is given.
386
+	 *
387
+	 * @param string $key
388
+	 * @return mixed
389
+	 */
390
+	public function getModuleConfiguration($key = '')
391
+	{
392
+
393
+		$vidiModuleCode = $this->getSignature();
394
+
395
+		// Module code must exist
396
+		if (empty($GLOBALS['TBE_MODULES_EXT']['vidi'][$vidiModuleCode])) {
397
+			$message = sprintf('Invalid or not existing module code "%s"', $vidiModuleCode);
398
+			throw new InvalidKeyInArrayException($message, 1375092053);
399
+		}
400
+
401
+		$result = $GLOBALS['TBE_MODULES_EXT']['vidi'][$vidiModuleCode];
402
+
403
+		if (!empty($key)) {
404
+			if (isset($result[$key])) {
405
+				$result = $result[$key];
406
+			} else {
407
+				// key must exist
408
+				$message = sprintf('Invalid key configuration "%s"', $key);
409
+				throw new InvalidKeyInArrayException($message, 1375092054);
410
+			}
411
+		}
412
+		return $result;
413
+	}
414
+
415
+	/**
416
+	 * @param string $icon
417
+	 * @return $this
418
+	 */
419
+	public function setIcon($icon): self
420
+	{
421
+		$this->icon = $icon;
422
+		return $this;
423
+	}
424
+
425
+	/**
426
+	 * @return string
427
+	 */
428
+	protected function getIcon(): string
429
+	{
430
+		$moduleConfiguration = $this->getExistingMainConfiguration();
431
+
432
+
433
+		if ($this->icon) {
434
+			$icon = $this->icon;
435
+		} elseif ($moduleConfiguration['icon']) { // existing configuration may override.
436
+			$icon = $moduleConfiguration['icon'];
437
+		} else {
438
+			$icon = ''; //default value.
439
+		}
440
+
441
+		return $icon;
442
+	}
443
+
444
+	/**
445
+	 * @param string $mainModule
446
+	 * @return $this
447
+	 */
448
+	public function setMainModule($mainModule): self
449
+	{
450
+		$this->mainModule = $mainModule;
451
+		return $this;
452
+	}
453
+
454
+	/**
455
+	 * @return string
456
+	 */
457
+	public function getMainModule(): string
458
+	{
459
+		if ($this->mainModule === null) {
460
+			$this->mainModule = $this->getModuleConfiguration('mainModule');
461
+		}
462
+		return $this->mainModule;
463
+	}
464
+
465
+	/**
466
+	 * @param string $moduleLanguageFile
467
+	 * @return $this
468
+	 */
469
+	public function setModuleLanguageFile($moduleLanguageFile): self
470
+	{
471
+		$this->moduleLanguageFile = $moduleLanguageFile;
472
+		return $this;
473
+	}
474
+
475
+	/**
476
+	 * @param string $component
477
+	 * @return $this
478
+	 */
479
+	public function removeComponentFromDocHeader(string $component): self
480
+	{
481
+		foreach ($this->components[ModulePosition::DOC_HEADER] as $verticalPosition => $docHeaders) {
482
+			foreach ($docHeaders as $horizontalPosition => $docHeader) {
483
+
484
+				$index = array_search($component, $docHeader, true);
485
+				if ($index !== false) {
486
+					// $verticalPosition: top or bottom
487
+					// $horizontalPosition: left or right
488
+					unset($this->components[ModulePosition::DOC_HEADER][$verticalPosition][$horizontalPosition][$index]);
489
+				}
490
+			}
491
+		}
492
+		return $this;
493
+	}
494
+
495
+	/**
496
+	 * @param bool $isPidIgnored
497
+	 * @return $this
498
+	 */
499
+	public function ignorePid(bool $isPidIgnored): self
500
+	{
501
+		$this->isPidIgnored = $isPidIgnored;
502
+		return $this;
503
+	}
504
+
505
+	/**
506
+	 * @return bool
507
+	 */
508
+	public function isPidIgnored(): bool
509
+	{
510
+		return $this->getModuleConfiguration('isPidIgnored');
511
+	}
512
+
513
+	/**
514
+	 * @param string $component
515
+	 * @return bool
516
+	 */
517
+	public function hasComponentInDocHeader(string $component): bool
518
+	{
519
+		foreach ($this->getModuleConfiguration('components')[ModulePosition::DOC_HEADER] as $verticalPosition => $docHeaders) {
520
+			foreach ($docHeaders as $horizontalPosition => $docHeader) {
521
+
522
+				$index = array_search($component, $docHeader, true);
523
+				if ($index !== false) {
524
+					return true;
525
+				}
526
+			}
527
+		}
528
+		return false;
529
+	}
530
+
531
+	/**
532
+	 * @return string
533
+	 */
534
+	protected function getModuleLanguageFile(): string
535
+	{
536
+		$moduleConfiguration = $this->getExistingMainConfiguration();
537
+
538
+		if ($this->moduleLanguageFile) {
539
+			$moduleLanguageFile = $this->moduleLanguageFile;
540
+		} elseif ($moduleConfiguration['labels']) { // existing configuration may override.
541
+			$moduleLanguageFile = $moduleConfiguration['labels'];
542
+		} else {
543
+			$moduleLanguageFile = ''; //default value.
544
+		}
545
+
546
+		return $moduleLanguageFile;
547
+	}
548
+
549
+	/**
550
+	 * @param string $position
551
+	 * @return $this
552
+	 */
553
+	public function setPosition($position): self
554
+	{
555
+		$this->position = $position;
556
+		return $this;
557
+	}
558
+
559
+	/**
560
+	 * @return string
561
+	 */
562
+	public function getPosition(): string
563
+	{
564
+		return $this->position;
565
+	}
566
+
567
+	/**
568
+	 * @param array $files
569
+	 * @return $this
570
+	 */
571
+	public function addJavaScriptFiles(array $files): self
572
+	{
573
+		foreach ($files as $file) {
574
+			$this->additionalJavaScriptFiles[] = $file;
575
+		}
576
+		return $this;
577
+	}
578
+
579
+	/**
580
+	 * @param string $fileNameAndPath
581
+	 * @return $this
582
+	 */
583
+	public function addJavaScriptFile($fileNameAndPath): self
584
+	{
585
+		$this->additionalJavaScriptFiles[] = $fileNameAndPath;
586
+		return $this;
587
+	}
588
+
589
+	/**
590
+	 * @param array $files
591
+	 * @return $this
592
+	 */
593
+	public function addStyleSheetFiles(array $files): self
594
+	{
595
+		foreach ($files as $file) {
596
+			$this->additionalStyleSheetFiles[] = $file;
597
+		}
598
+		return $this;
599
+	}
600
+
601
+	/**
602
+	 * @param string $fileNameAndPath
603
+	 * @return $this
604
+	 */
605
+	public function addStyleSheetFile($fileNameAndPath): self
606
+	{
607
+		$this->additionalStyleSheetFiles[] = $fileNameAndPath;
608
+		return $this;
609
+	}
610
+
611
+	/**
612
+	 * @return string
613
+	 */
614
+	public function getDataType(): string
615
+	{
616
+		if ($this->dataType === null) {
617
+			$this->dataType = $this->getModuleConfiguration('dataType');
618
+		}
619
+		return $this->dataType;
620
+	}
621
+
622
+	/**
623
+	 * @return array
624
+	 */
625
+	public function getDataTypes(): array
626
+	{
627
+		$dataTypes = [];
628
+		foreach ($GLOBALS['TBE_MODULES_EXT']['vidi'] as $module) {
629
+			$dataTypes[] = $module['dataType'];
630
+		}
631
+		return $dataTypes;
632
+	}
633
+
634
+	/**
635
+	 * @param string $dataType
636
+	 * @return $this
637
+	 */
638
+	public function setDataType($dataType): self
639
+	{
640
+		$this->dataType = $dataType;
641
+		return $this;
642
+	}
643
+
644
+	/**
645
+	 * @return int
646
+	 */
647
+	public function getDefaultPid(): int
648
+	{
649
+		if (empty($this->defaultPid)) {
650
+			$this->defaultPid = $this->getModuleConfiguration('defaultPid');
651
+		}
652
+		return (int)$this->defaultPid;
653
+	}
654
+
655
+	/**
656
+	 * @param string $defaultPid
657
+	 * @return $this
658
+	 */
659
+	public function setDefaultPid($defaultPid): self
660
+	{
661
+		$this->defaultPid = $defaultPid;
662
+		return $this;
663
+	}
664
+
665
+	/**
666
+	 * @param bool $isPageTreeShown
667
+	 * @return $this
668
+	 */
669
+	public function showPageTree($isPageTreeShown): self
670
+	{
671
+		$this->showPageTree = $isPageTreeShown;
672
+		return $this;
673
+	}
674
+
675
+	/**
676
+	 * @param string $isShown
677
+	 * @return $this
678
+	 */
679
+	public function isShown($isShown): self
680
+	{
681
+		$this->isShown = $isShown;
682
+		return $this;
683
+	}
684
+
685
+	/**
686
+	 * @return $array
687
+	 */
688
+	public function getDocHeaderTopLeftComponents()
689
+	{
690
+		$configuration = $this->getModuleConfiguration();
691
+		return $configuration['components'][ModulePosition::DOC_HEADER][ModulePosition::TOP][ModulePosition::LEFT];
692
+	}
693
+
694
+	/**
695
+	 * @param array $components
696
+	 * @return $this
697
+	 */
698
+	public function setDocHeaderTopLeftComponents(array $components): self
699
+	{
700
+		$this->components[ModulePosition::DOC_HEADER][ModulePosition::TOP][ModulePosition::LEFT] = $components;
701
+		return $this;
702
+	}
703
+
704
+	/**
705
+	 * @param string|array $components
706
+	 * @return $this
707
+	 */
708
+	public function addDocHeaderTopLeftComponents($components): self
709
+	{
710
+		if (is_string($components)) {
711
+			$components = [$components];
712
+		}
713
+		$currentComponents = $this->components[ModulePosition::DOC_HEADER][ModulePosition::TOP][ModulePosition::LEFT];
714
+		$this->components[ModulePosition::DOC_HEADER][ModulePosition::TOP][ModulePosition::LEFT] = array_merge($currentComponents, $components);
715
+		return $this;
716
+	}
717
+
718
+	/**
719
+	 * @return $array
720
+	 */
721
+	public function getDocHeaderTopRightComponents()
722
+	{
723
+		$configuration = $this->getModuleConfiguration();
724
+		return $configuration['components'][ModulePosition::DOC_HEADER][ModulePosition::TOP][ModulePosition::RIGHT];
725
+	}
726
+
727
+	/**
728
+	 * @param array $components
729
+	 * @return $this
730
+	 */
731
+	public function setDocHeaderTopRightComponents(array $components): self
732
+	{
733
+		$this->components[ModulePosition::DOC_HEADER][ModulePosition::TOP][ModulePosition::RIGHT] = $components;
734
+		return $this;
735
+	}
736
+
737
+	/**
738
+	 * @param string|array $components
739
+	 * @return $this
740
+	 */
741
+	public function addDocHeaderTopRightComponents($components): self
742
+	{
743
+		if (is_string($components)) {
744
+			$components = [$components];
745
+		}
746
+		$currentComponents = $this->components[ModulePosition::DOC_HEADER][ModulePosition::TOP][ModulePosition::RIGHT];
747
+		$this->components[ModulePosition::DOC_HEADER][ModulePosition::TOP][ModulePosition::RIGHT] = array_merge($currentComponents, $components);
748
+		return $this;
749
+	}
750
+
751
+	/**
752
+	 * @return $array
753
+	 */
754
+	public function getDocHeaderBottomLeftComponents()
755
+	{
756
+		$configuration = $this->getModuleConfiguration();
757
+		return $configuration['components'][ModulePosition::DOC_HEADER][ModulePosition::BOTTOM][ModulePosition::LEFT];
758
+	}
759
+
760
+	/**
761
+	 * @param array $components
762
+	 * @return $this
763
+	 */
764
+	public function setDocHeaderBottomLeftComponents(array $components): self
765
+	{
766
+		$this->components[ModulePosition::DOC_HEADER][ModulePosition::BOTTOM][ModulePosition::LEFT] = $components;
767
+		return $this;
768
+	}
769
+
770
+	/**
771
+	 * @param string|array $components
772
+	 * @return $this
773
+	 */
774
+	public function addDocHeaderBottomLeftComponents($components): self
775
+	{
776
+		if (is_string($components)) {
777
+			$components = [$components];
778
+		}
779
+		$currentComponents = $this->components[ModulePosition::DOC_HEADER][ModulePosition::BOTTOM][ModulePosition::LEFT];
780
+		$this->components[ModulePosition::DOC_HEADER][ModulePosition::BOTTOM][ModulePosition::LEFT] = array_merge($currentComponents, $components);
781
+		return $this;
782
+	}
783
+
784
+	/**
785
+	 * @return $array
786
+	 */
787
+	public function getDocHeaderBottomRightComponents()
788
+	{
789
+		$configuration = $this->getModuleConfiguration();
790
+		return $configuration['components'][ModulePosition::DOC_HEADER][ModulePosition::BOTTOM][ModulePosition::RIGHT];
791
+	}
792
+
793
+	/**
794
+	 * @param array $components
795
+	 * @return $this
796
+	 */
797
+	public function setDocHeaderBottomRightComponents(array $components): self
798
+	{
799
+		$this->components[ModulePosition::DOC_HEADER][ModulePosition::BOTTOM][ModulePosition::RIGHT] = $components;
800
+		return $this;
801
+	}
802
+
803
+	/**
804
+	 * @param string|array $components
805
+	 * @return $this
806
+	 */
807
+	public function addDocHeaderBottomRightComponents($components): self
808
+	{
809
+		if (is_string($components)) {
810
+			$components = [$components];
811
+		}
812
+		$currentComponents = $this->components[ModulePosition::DOC_HEADER][ModulePosition::BOTTOM][ModulePosition::RIGHT];
813
+		$this->components[ModulePosition::DOC_HEADER][ModulePosition::BOTTOM][ModulePosition::RIGHT] = array_merge($currentComponents, $components);
814
+		return $this;
815
+	}
816
+
817
+	/**
818
+	 * @return $array
819
+	 */
820
+	public function getGridTopComponents()
821
+	{
822
+		$configuration = $this->getModuleConfiguration();
823
+		return $configuration['components'][ModulePosition::GRID][ModulePosition::TOP];
824
+	}
825
+
826
+	/**
827
+	 * @param array $components
828
+	 * @return $this
829
+	 */
830
+	public function setGridTopComponents(array $components): self
831
+	{
832
+		$this->components[ModulePosition::GRID][ModulePosition::TOP] = $components;
833
+		return $this;
834
+	}
835
+
836
+	/**
837
+	 * @param string|array $components
838
+	 * @return $this
839
+	 */
840
+	public function addGridTopComponents($components): self
841
+	{
842
+		if (is_string($components)) {
843
+			$components = [$components];
844
+		}
845
+		$currentComponents = $this->components[ModulePosition::GRID][ModulePosition::TOP];
846
+		$this->components[ModulePosition::GRID][ModulePosition::TOP] = array_merge($currentComponents, $components);
847
+		return $this;
848
+	}
849
+
850
+	/**
851
+	 * @return mixed $array
852
+	 */
853
+	public function getGridBottomComponents()
854
+	{
855
+		$configuration = $this->getModuleConfiguration();
856
+		return $configuration['components'][ModulePosition::GRID][ModulePosition::BOTTOM];
857
+	}
858
+
859
+	/**
860
+	 * @param array $components
861
+	 * @return $this
862
+	 */
863
+	public function setGridBottomComponents(array $components): self
864
+	{
865
+		$this->components[ModulePosition::GRID][ModulePosition::BOTTOM] = $components;
866
+		return $this;
867
+	}
868
+
869
+	/**
870
+	 * @param string|array $components
871
+	 * @return $this
872
+	 */
873
+	public function addGridBottomComponents($components): self
874
+	{
875
+		if (is_string($components)) {
876
+			$components = [$components];
877
+		}
878
+		$currentComponents = $this->components[ModulePosition::GRID][ModulePosition::BOTTOM];
879
+		$this->components[ModulePosition::GRID][ModulePosition::BOTTOM] = array_merge($currentComponents, $components);
880
+		return $this;
881
+	}
882
+
883
+	/**
884
+	 * @return $array
885
+	 */
886
+	public function getGridButtonsComponents()
887
+	{
888
+		$configuration = $this->getModuleConfiguration();
889
+		return $configuration['components'][ModulePosition::GRID][ModulePosition::BUTTONS];
890
+	}
891
+
892
+	/**
893
+	 * @param array $components
894
+	 * @return $this
895
+	 */
896
+	public function setGridButtonsComponents(array $components): self
897
+	{
898
+		$this->components[ModulePosition::GRID][ModulePosition::BUTTONS] = $components;
899
+		return $this;
900
+	}
901
+
902
+	/**
903
+	 * @param string|array $components
904
+	 * @return $this
905
+	 */
906
+	public function addGridButtonsComponents($components): self
907
+	{
908
+		if (is_string($components)) {
909
+			$components = [$components];
910
+		}
911
+		$currentComponents = $this->components[ModulePosition::GRID][ModulePosition::BUTTONS];
912
+		$this->components[ModulePosition::GRID][ModulePosition::BUTTONS] = array_merge($components, $currentComponents);
913
+		return $this;
914
+	}
915
+
916
+	/**
917
+	 * @return $array
918
+	 */
919
+	public function getMenuMassActionComponents()
920
+	{
921
+		$configuration = $this->getModuleConfiguration();
922
+		return $configuration['components'][ModulePosition::MENU_MASS_ACTION];
923
+	}
924
+
925
+	/**
926
+	 * @param array $components
927
+	 * @return $this
928
+	 */
929
+	public function setMenuMassActionComponents(array $components): self
930
+	{
931
+		$this->components[ModulePosition::MENU_MASS_ACTION] = $components;
932
+		return $this;
933
+	}
934
+
935
+	/**
936
+	 * @param string|array $components
937
+	 * @return $this
938
+	 */
939
+	public function addMenuMassActionComponents($components): self
940
+	{
941
+		if (is_string($components)) {
942
+			$components = [$components];
943
+		}
944
+		$currentComponents = $this->components[ModulePosition::MENU_MASS_ACTION];
945
+		$this->components[ModulePosition::MENU_MASS_ACTION] = array_merge($components, $currentComponents);
946
+		return $this;
947
+	}
948
+
949
+	/**
950
+	 * @return string
951
+	 */
952
+	protected function getAccess(): string
953
+	{
954
+		$moduleConfiguration = $this->getExistingMainConfiguration();
955
+
956
+		if ($this->access !== null) {
957
+			$access = $this->access;
958
+		} elseif (!empty($moduleConfiguration['access'])) { // existing configuration may override.
959
+			$access = $moduleConfiguration['access'];
960
+		} else {
961
+			$access = Access::USER; //default value.
962
+		}
963
+		return $access;
964
+	}
965
+
966
+	/**
967
+	 * @param string $access
968
+	 * @return $this
969
+	 */
970
+	public function setAccess($access): self
971
+	{
972
+		$this->access = $access;
973
+		return $this;
974
+	}
975
+
976
+	/**
977
+	 * @return \string[]
978
+	 */
979
+	public function getAdditionalJavaScriptFiles(): array
980
+	{
981
+		if (empty($this->additionalJavaScriptFiles)) {
982
+			$this->additionalJavaScriptFiles = $this->getModuleConfiguration('additionalJavaScriptFiles');
983
+		}
984
+		return $this->additionalJavaScriptFiles;
985
+	}
986
+
987
+	/**
988
+	 * @return \string[]
989
+	 */
990
+	public function getAdditionalStyleSheetFiles(): array
991
+	{
992
+		if (empty($this->additionalStyleSheetFiles)) {
993
+			$this->additionalStyleSheetFiles = $this->getModuleConfiguration('additionalStyleSheetFiles');
994
+		}
995
+		return $this->additionalStyleSheetFiles;
996
+	}
997
+
998
+	/**
999
+	 * @return array
1000
+	 */
1001
+	public function getComponents(): array
1002
+	{
1003
+		return $this->components;
1004
+	}
1005
+
1006
+	/**
1007
+	 * @param string $pluginName
1008
+	 * @return bool
1009
+	 */
1010
+	public function hasPlugin($pluginName = ''): bool
1011
+	{
1012
+		$parameterPrefix = $this->getParameterPrefix();
1013
+		$parameters = GeneralUtility::_GET($parameterPrefix);
1014
+
1015
+		$hasPlugin = !empty($parameters['plugins']) && is_array($parameters['plugins']);
1016
+		if ($hasPlugin && $pluginName) {
1017
+			$hasPlugin = in_array($pluginName, $parameters['plugins']);
1018
+		}
1019
+		return $hasPlugin;
1020
+	}
1021
+
1022
+	/**
1023
+	 * Compute the internal module code
1024
+	 *
1025
+	 * @param null|string $dataType
1026
+	 * @return string
1027
+	 */
1028
+	protected function getInternalModuleSignature($dataType = null): string
1029
+	{
1030
+		// Else we forge the module signature
1031
+		if ($dataType === null) {
1032
+			$dataType = $this->dataType;
1033
+		}
1034
+		$subModuleName = $dataType . '_' . $this->moduleKey;
1035
+
1036
+		$mainModule = $this->mainModule ?: self::DEFAULT_MAIN_MODULE;
1037
+		return $mainModule . '_Vidi' . GeneralUtility::underscoredToUpperCamelCase($subModuleName);
1038
+	}
1039 1039
 
1040 1040
 }
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -193,7 +193,7 @@  discard block
 block discarded – undo
193 193
      */
194 194
     protected function getExistingMainConfiguration(): array
195 195
     {
196
-        $moduleSignature = $this->computeMainModule() . '_' . $this->getInternalModuleSignature();
196
+        $moduleSignature = $this->computeMainModule().'_'.$this->getInternalModuleSignature();
197 197
         return $GLOBALS['TBE_MODULES']['_configuration'][$moduleSignature] ?? [];
198 198
     }
199 199
 
@@ -315,7 +315,7 @@  discard block
 block discarded – undo
315 315
             ExtensionUtility::registerModule(
316 316
                 'Vidi',
317 317
                 $this->computeMainModule(),
318
-                $this->dataType . '_' . $this->moduleKey,
318
+                $this->dataType.'_'.$this->moduleKey,
319 319
                 $this->position,
320 320
                 [
321 321
                     ContentController::class => 'index, list, delete, update, edit, copy, move, localize, sort, copyClipboard, moveClipboard',
@@ -378,7 +378,7 @@  discard block
 block discarded – undo
378 378
      */
379 379
     public function getParameterPrefix(): string
380 380
     {
381
-        return 'tx_vidi_' . strtolower($this->getSignature());
381
+        return 'tx_vidi_'.strtolower($this->getSignature());
382 382
     }
383 383
 
384 384
     /**
@@ -1031,10 +1031,10 @@  discard block
 block discarded – undo
1031 1031
         if ($dataType === null) {
1032 1032
             $dataType = $this->dataType;
1033 1033
         }
1034
-        $subModuleName = $dataType . '_' . $this->moduleKey;
1034
+        $subModuleName = $dataType.'_'.$this->moduleKey;
1035 1035
 
1036 1036
         $mainModule = $this->mainModule ?: self::DEFAULT_MAIN_MODULE;
1037
-        return $mainModule . '_Vidi' . GeneralUtility::underscoredToUpperCamelCase($subModuleName);
1037
+        return $mainModule.'_Vidi'.GeneralUtility::underscoredToUpperCamelCase($subModuleName);
1038 1038
     }
1039 1039
 
1040 1040
 }
Please login to merge, or discard this patch.
Classes/Persistence/Storage/VidiDbBackend.php 1 patch
Indentation   +1047 added lines, -1047 removed lines patch added patch discarded remove patch
@@ -52,1052 +52,1052 @@
 block discarded – undo
52 52
 class VidiDbBackend
53 53
 {
54 54
 
55
-    const OPERATOR_EQUAL_TO_NULL = 'operatorEqualToNull';
56
-    const OPERATOR_NOT_EQUAL_TO_NULL = 'operatorNotEqualToNull';
57
-
58
-    /**
59
-     * The TYPO3 page repository. Used for language and workspace overlay
60
-     *
61
-     * @var PageRepository
62
-     */
63
-    protected $pageRepository;
64
-
65
-    /**
66
-     * @var Query
67
-     */
68
-    protected $query;
69
-
70
-    /**
71
-     * Store some info related to table name and its aliases.
72
-     *
73
-     * @var array
74
-     */
75
-    protected $tableNameAliases = array(
76
-        'aliases' => [],
77
-        'aliasIncrement' => [],
78
-    );
79
-
80
-    /**
81
-     * Use to store the current foreign table name alias.
82
-     *
83
-     * @var string
84
-     */
85
-    protected $currentChildTableNameAlias = '';
86
-
87
-    /**
88
-     * @param Query $query
89
-     */
90
-    public function __construct(Query $query)
91
-    {
92
-        $this->query = $query;
93
-    }
94
-
95
-    /**
96
-     * @param $parameters
97
-     * @return array
98
-     */
99
-    protected static function getTypes($parameters)
100
-    {
101
-        $types = [];
102
-        foreach ($parameters as $parameter) {
103
-            if (is_array($parameter)) {
104
-                if (MathUtility::canBeInterpretedAsInteger($parameter[0])) {
105
-                    $types[] = \Doctrine\DBAL\Connection::PARAM_INT_ARRAY;
106
-                } else {
107
-                    $types[] = \Doctrine\DBAL\Connection::PARAM_STR_ARRAY;
108
-                }
109
-            } else {
110
-                if (MathUtility::canBeInterpretedAsInteger($parameter)) {
111
-                    $types[] = ParameterType::INTEGER;
112
-                } else {
113
-                    $types[] = ParameterType::STRING;
114
-                }
115
-            }
116
-        }
117
-        return $types;
118
-    }
119
-
120
-    /**
121
-     * Returns the result of the query
122
-     */
123
-    public function fetchResult()
124
-    {
125
-        $parameters = [];
126
-        $statementParts = $this->parseQuery($parameters);
127
-        $statementParts = $this->processStatementStructureForRecursiveMMRelation($statementParts);
128
-        $sql = $this->buildQuery($statementParts);
129
-        //print $sql; exit();
130
-
131
-        $rows = $this->getConnection()
132
-            ->executeQuery($sql, $parameters, self::getTypes($parameters))
133
-            ->fetchAll();
134
-
135
-        return $this->getContentObjects($rows);
136
-    }
137
-
138
-    /**
139
-     * Returns the number of tuples matching the query.
140
-     *
141
-     * @return int The number of matching tuples
142
-     */
143
-    public function countResult()
144
-    {
145
-        $parameters = [];
146
-        $statementParts = $this->parseQuery($parameters);
147
-        $statementParts = $this->processStatementStructureForRecursiveMMRelation($statementParts);
148
-        $types = self::getTypes($parameters);
149
-
150
-        // if limit is set, we need to count the rows "manually" as COUNT(*) ignores LIMIT constraints
151
-        if (!empty($statementParts['limit'])) {
152
-            $sql = $this->buildQuery($statementParts);
153
-
154
-            $count = $this
155
-                ->getConnection()
156
-                ->executeQuery($sql, $parameters, $types)
157
-                ->rowCount();
158
-        } else {
159
-            $statementParts['fields'] = array('COUNT(*)');
160
-            // having orderings without grouping is not compatible with non-MySQL DBMS
161
-            $statementParts['orderings'] = [];
162
-            if (isset($statementParts['keywords']['distinct'])) {
163
-                unset($statementParts['keywords']['distinct']);
164
-                $distinctField = $this->query->getDistinct() ? $this->query->getDistinct() : 'uid';
165
-                $statementParts['fields'] = array('COUNT(DISTINCT ' . $statementParts['mainTable'] . '.' . $distinctField . ')');
166
-            }
167
-
168
-            $sql = $this->buildQuery($statementParts);
169
-            $count = $this
170
-                ->getConnection()
171
-                ->executeQuery($sql, $parameters, $types)
172
-                ->fetchColumn(0);
173
-        }
174
-        return (int)$count;
175
-    }
176
-
177
-    /**
178
-     * Parses the query and returns the SQL statement parts.
179
-     *
180
-     * @param array &$parameters
181
-     * @return array
182
-     */
183
-    public function parseQuery(array &$parameters)
184
-    {
185
-        $statementParts = [];
186
-        $statementParts['keywords'] = [];
187
-        $statementParts['tables'] = [];
188
-        $statementParts['unions'] = [];
189
-        $statementParts['fields'] = [];
190
-        $statementParts['where'] = [];
191
-        $statementParts['additionalWhereClause'] = [];
192
-        $statementParts['orderings'] = [];
193
-        $statementParts['limit'] = [];
194
-        $query = $this->query;
195
-        $source = $query->getSource();
196
-        $this->parseSource($source, $statementParts);
197
-        $this->parseConstraint($query->getConstraint(), $source, $statementParts, $parameters);
198
-        $this->parseOrderings($query->getOrderings(), $source, $statementParts);
199
-        $this->parseLimitAndOffset($query->getLimit(), $query->getOffset(), $statementParts);
200
-        $tableNames = array_unique(array_keys($statementParts['tables'] + $statementParts['unions']));
201
-        foreach ($tableNames as $tableNameOrAlias) {
202
-            if (is_string($tableNameOrAlias) && strlen($tableNameOrAlias) > 0) {
203
-                $this->addAdditionalWhereClause($query->getTypo3QuerySettings(), $tableNameOrAlias, $statementParts);
204
-            }
205
-        }
206
-
207
-        return $statementParts;
208
-    }
209
-
210
-    /**
211
-     * Fiddle with the statement structure to handle recursive MM relations.
212
-     * For the recursive MM query to work, we must invert some values.
213
-     * Let see if that is the best way of doing that...
214
-     *
215
-     * @param array $statementParts
216
-     * @return array
217
-     */
218
-    public function processStatementStructureForRecursiveMMRelation(array $statementParts)
219
-    {
220
-
221
-        if ($this->hasRecursiveMMRelation()) {
222
-            $tableName = $this->query->getType();
223
-
224
-            // In order the MM query to work for a recursive MM query, we must invert some values.
225
-            // tx_domain_model_foo0 (the alias) <--> tx_domain_model_foo (the origin table name)
226
-            $values = [];
227
-            foreach ($statementParts['fields'] as $key => $value) {
228
-                $values[$key] = str_replace($tableName, $tableName . '0', $value);
229
-            }
230
-            $statementParts['fields'] = $values;
231
-
232
-            // Same comment as above.
233
-            $values = [];
234
-            foreach ($statementParts['where'] as $key => $value) {
235
-                $values[$key] = str_replace($tableName . '0', $tableName, $value);
236
-            }
237
-            $statementParts['where'] = $values;
238
-
239
-            // We must be more restrictive by transforming the "left" union by "inner"
240
-            $values = [];
241
-            foreach ($statementParts['unions'] as $key => $value) {
242
-                $values[$key] = str_replace('LEFT JOIN', 'INNER JOIN', $value);
243
-            }
244
-            $statementParts['unions'] = $values;
245
-        }
246
-
247
-        return $statementParts;
248
-    }
249
-
250
-    /**
251
-     * Tell whether there is a recursive MM relation.
252
-     *
253
-     * @return bool
254
-     */
255
-    public function hasRecursiveMMRelation()
256
-    {
257
-        return isset($this->tableNameAliases['aliasIncrement'][$this->query->getType()]);
258
-
259
-    }
260
-
261
-    /**
262
-     * Returns the statement, ready to be executed.
263
-     *
264
-     * @param array $statementParts The SQL statement parts
265
-     * @return string The SQL statement
266
-     */
267
-    public function buildQuery(array $statementParts)
268
-    {
269
-
270
-        // Add more statement to the UNION part.
271
-        if (!empty($statementParts['unions'])) {
272
-            foreach ($statementParts['unions'] as $tableName => $unionPart) {
273
-                if (!empty($statementParts['additionalWhereClause'][$tableName])) {
274
-                    $statementParts['unions'][$tableName] .= ' AND ' . implode(' AND ', $statementParts['additionalWhereClause'][$tableName]);
275
-                }
276
-            }
277
-        }
278
-
279
-        $statement = 'SELECT ' . implode(' ', $statementParts['keywords']) . ' ' . implode(',', $statementParts['fields']) . ' FROM ' . implode(' ', $statementParts['tables']) . ' ' . implode(' ', $statementParts['unions']);
280
-        if (!empty($statementParts['where'])) {
281
-            $statement .= ' WHERE ' . implode('', $statementParts['where']);
282
-            if (!empty($statementParts['additionalWhereClause'][$this->query->getType()])) {
283
-                $statement .= ' AND ' . implode(' AND ', $statementParts['additionalWhereClause'][$this->query->getType()]);
284
-            }
285
-        } elseif (!empty($statementParts['additionalWhereClause'])) {
286
-            $statement .= ' WHERE ' . implode(' AND ', $statementParts['additionalWhereClause'][$this->query->getType()]);
287
-        }
288
-        if (!empty($statementParts['orderings'])) {
289
-            $statement .= ' ORDER BY ' . implode(', ', $statementParts['orderings']);
290
-        }
291
-        if (!empty($statementParts['limit'])) {
292
-            $statement .= ' LIMIT ' . $statementParts['limit'];
293
-        }
294
-
295
-        return $statement;
296
-    }
297
-
298
-    /**
299
-     * Transforms a Query Source into SQL and parameter arrays
300
-     *
301
-     * @param SourceInterface $source The source
302
-     * @param array &$sql
303
-     * @return void
304
-     */
305
-    protected function parseSource(SourceInterface $source, array &$sql)
306
-    {
307
-        $tableName = $this->getTableName();
308
-        $sql['fields'][$tableName] = $tableName . '.*';
309
-        if ($this->query->getDistinct()) {
310
-            $sql['fields'][$tableName] = $tableName . '.' . $this->query->getDistinct();
311
-            $sql['keywords']['distinct'] = 'DISTINCT';
312
-        }
313
-        $sql['tables'][$tableName] = $tableName;
314
-        $sql['mainTable'] = $tableName;
315
-    }
316
-
317
-    /**
318
-     * Transforms a constraint into SQL and parameter arrays
319
-     *
320
-     * @param ConstraintInterface $constraint The constraint
321
-     * @param SourceInterface $source The source
322
-     * @param array &$statementParts The query parts
323
-     * @param array &$parameters The parameters that will replace the markers
324
-     * @return void
325
-     */
326
-    protected function parseConstraint(ConstraintInterface $constraint = null, SourceInterface $source, array &$statementParts, array &$parameters)
327
-    {
328
-        if ($constraint instanceof AndInterface) {
329
-            $statementParts['where'][] = '(';
330
-            $this->parseConstraint($constraint->getConstraint1(), $source, $statementParts, $parameters);
331
-            $statementParts['where'][] = ' AND ';
332
-            $this->parseConstraint($constraint->getConstraint2(), $source, $statementParts, $parameters);
333
-            $statementParts['where'][] = ')';
334
-        } elseif ($constraint instanceof OrInterface) {
335
-            $statementParts['where'][] = '(';
336
-            $this->parseConstraint($constraint->getConstraint1(), $source, $statementParts, $parameters);
337
-            $statementParts['where'][] = ' OR ';
338
-            $this->parseConstraint($constraint->getConstraint2(), $source, $statementParts, $parameters);
339
-            $statementParts['where'][] = ')';
340
-        } elseif ($constraint instanceof NotInterface) {
341
-            $statementParts['where'][] = 'NOT (';
342
-            $this->parseConstraint($constraint->getConstraint(), $source, $statementParts, $parameters);
343
-            $statementParts['where'][] = ')';
344
-        } elseif ($constraint instanceof ComparisonInterface) {
345
-            $this->parseComparison($constraint, $source, $statementParts, $parameters);
346
-        }
347
-    }
348
-
349
-    /**
350
-     * Parse a Comparison into SQL and parameter arrays.
351
-     *
352
-     * @param ComparisonInterface $comparison The comparison to parse
353
-     * @param SourceInterface $source The source
354
-     * @param array &$statementParts SQL query parts to add to
355
-     * @param array &$parameters Parameters to bind to the SQL
356
-     * @return void
357
-     * @throws Exception\RepositoryException
358
-     */
359
-    protected function parseComparison(ComparisonInterface $comparison, SourceInterface $source, array &$statementParts, array &$parameters)
360
-    {
361
-        $operand1 = $comparison->getOperand1();
362
-        $operator = $comparison->getOperator();
363
-        $operand2 = $comparison->getOperand2();
364
-        if ($operator === QueryInterface::OPERATOR_IN) {
365
-            $items = [];
366
-            $hasValue = false;
367
-            foreach ($operand2 as $value) {
368
-                $value = $this->getPlainValue($value);
369
-                if ($value !== null) {
370
-                    $items[] = $value;
371
-                    $hasValue = true;
372
-                }
373
-            }
374
-            if ($hasValue === false) {
375
-                $statementParts['where'][] = '1<>1';
376
-            } else {
377
-                $this->parseDynamicOperand($operand1, $operator, $source, $statementParts, $parameters, null);
378
-                $parameters[] = $items;
379
-            }
380
-        } elseif ($operator === QueryInterface::OPERATOR_CONTAINS) {
381
-            if ($operand2 === null) {
382
-                $statementParts['where'][] = '1<>1';
383
-            } else {
384
-                throw new \Exception('Not implemented! Contact extension author.', 1412931227);
385
-                # @todo re-implement me if necessary.
386
-                #$tableName = $this->query->getType();
387
-                #$propertyName = $operand1->getPropertyName();
388
-                #while (strpos($propertyName, '.') !== false) {
389
-                #	$this->addUnionStatement($tableName, $propertyName, $statementParts);
390
-                #}
391
-                #$columnName = $propertyName;
392
-                #$columnMap = $propertyName;
393
-                #$typeOfRelation = $columnMap instanceof ColumnMap ? $columnMap->getTypeOfRelation() : null;
394
-                #if ($typeOfRelation === ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) {
395
-                #	$relationTableName = $columnMap->getRelationTableName();
396
-                #	$statementParts['where'][] = $tableName . '.uid IN (SELECT ' . $columnMap->getParentKeyFieldName() . ' FROM ' . $relationTableName . ' WHERE ' . $columnMap->getChildKeyFieldName() . '=?)';
397
-                #	$parameters[] = intval($this->getPlainValue($operand2));
398
-                #} elseif ($typeOfRelation === ColumnMap::RELATION_HAS_MANY) {
399
-                #	$parentKeyFieldName = $columnMap->getParentKeyFieldName();
400
-                #	if (isset($parentKeyFieldName)) {
401
-                #		$childTableName = $columnMap->getChildTableName();
402
-                #		$statementParts['where'][] = $tableName . '.uid=(SELECT ' . $childTableName . '.' . $parentKeyFieldName . ' FROM ' . $childTableName . ' WHERE ' . $childTableName . '.uid=?)';
403
-                #		$parameters[] = intval($this->getPlainValue($operand2));
404
-                #	} else {
405
-                #		$statementParts['where'][] = 'FIND_IN_SET(?,' . $tableName . '.' . $columnName . ')';
406
-                #		$parameters[] = intval($this->getPlainValue($operand2));
407
-                #	}
408
-                #} else {
409
-                #	throw new Exception\RepositoryException('Unsupported or non-existing property name "' . $propertyName . '" used in relation matching.', 1327065745);
410
-                #}
411
-            }
412
-        } else {
413
-            if ($operand2 === null) {
414
-                if ($operator === QueryInterface::OPERATOR_EQUAL_TO) {
415
-                    $operator = self::OPERATOR_EQUAL_TO_NULL;
416
-                } elseif ($operator === QueryInterface::OPERATOR_NOT_EQUAL_TO) {
417
-                    $operator = self::OPERATOR_NOT_EQUAL_TO_NULL;
418
-                }
419
-            }
420
-            $this->parseDynamicOperand($operand1, $operator, $source, $statementParts, $parameters);
421
-            $parameters[] = $this->getPlainValue($operand2);
422
-        }
423
-    }
424
-
425
-    /**
426
-     * Returns a plain value, i.e. objects are flattened if possible.
427
-     *
428
-     * @param mixed $input
429
-     * @return mixed
430
-     * @throws UnexpectedTypeException
431
-     */
432
-    protected function getPlainValue($input)
433
-    {
434
-        if (is_array($input)) {
435
-            throw new UnexpectedTypeException('An array could not be converted to a plain value.', 1274799932);
436
-        }
437
-        if ($input instanceof \DateTime) {
438
-            return $input->format('U');
439
-        } elseif (is_object($input)) {
440
-            if ($input instanceof LazyLoadingProxy) {
441
-                $realInput = $input->_loadRealInstance();
442
-            } else {
443
-                $realInput = $input;
444
-            }
445
-            if ($realInput instanceof DomainObjectInterface) {
446
-                return $realInput->getUid();
447
-            } else {
448
-                throw new UnexpectedTypeException('An object of class "' . get_class($realInput) . '" could not be converted to a plain value.', 1274799934);
449
-            }
450
-        } elseif (is_bool($input)) {
451
-            return $input === true ? 1 : 0;
452
-        } else {
453
-            return $input;
454
-        }
455
-    }
456
-
457
-    /**
458
-     * Parse a DynamicOperand into SQL and parameter arrays.
459
-     *
460
-     * @param DynamicOperandInterface $operand
461
-     * @param string $operator One of the JCR_OPERATOR_* constants
462
-     * @param SourceInterface $source The source
463
-     * @param array &$statementParts The query parts
464
-     * @param array &$parameters The parameters that will replace the markers
465
-     * @param string $valueFunction an optional SQL function to apply to the operand value
466
-     * @return void
467
-     */
468
-    protected function parseDynamicOperand(DynamicOperandInterface $operand, $operator, SourceInterface $source, array &$statementParts, array &$parameters, $valueFunction = null)
469
-    {
470
-        if ($operand instanceof LowerCaseInterface) {
471
-            $this->parseDynamicOperand($operand->getOperand(), $operator, $source, $statementParts, $parameters, 'LOWER');
472
-        } elseif ($operand instanceof UpperCaseInterface) {
473
-            $this->parseDynamicOperand($operand->getOperand(), $operator, $source, $statementParts, $parameters, 'UPPER');
474
-        } elseif ($operand instanceof PropertyValueInterface) {
475
-            $propertyName = $operand->getPropertyName();
476
-
477
-            // Reset value.
478
-            $this->currentChildTableNameAlias = '';
479
-
480
-            if ($source instanceof SelectorInterface) {
481
-                $tableName = $this->query->getType();
482
-                while (strpos($propertyName, '.') !== false) {
483
-                    $this->addUnionStatement($tableName, $propertyName, $statementParts);
484
-                }
485
-            } elseif ($source instanceof JoinInterface) {
486
-                $tableName = $source->getJoinCondition()->getSelector1Name();
487
-            }
488
-
489
-            $columnName = $propertyName;
490
-            $resolvedOperator = $this->resolveOperator($operator);
491
-            $constraintSQL = '';
492
-
493
-            $marker = $operator === QueryInterface::OPERATOR_IN
494
-                ? '(?)'
495
-                : '?';
496
-
497
-            if ($valueFunction === null) {
498
-                $constraintSQL .= (!empty($tableName) ? $tableName . '.' : '') . $columnName . ' ' . $resolvedOperator . ' ' . $marker;
499
-            } else {
500
-                $constraintSQL .= $valueFunction . '(' . (!empty($tableName) ? $tableName . '.' : '') . $columnName . ') ' . $resolvedOperator . ' ' . $marker;
501
-            }
502
-
503
-            if (isset($tableName) && !empty($this->currentChildTableNameAlias)) {
504
-                $constraintSQL = $this->replaceTableNameByAlias($tableName, $this->currentChildTableNameAlias, $constraintSQL);
505
-            }
506
-            $statementParts['where'][] = $constraintSQL;
507
-        }
508
-    }
509
-
510
-    /**
511
-     * @param string &$tableName
512
-     * @param string &$propertyPath
513
-     * @param array &$statementParts
514
-     */
515
-    protected function addUnionStatement(&$tableName, &$propertyPath, array &$statementParts)
516
-    {
517
-
518
-        $table = Tca::table($tableName);
519
-
520
-        $explodedPropertyPath = explode('.', $propertyPath, 2);
521
-        $fieldName = $explodedPropertyPath[0];
522
-
523
-        // Field of type "group" are special because property path must contain the table name
524
-        // to determine the relation type. Example for sys_category, property path will look like "items.sys_file"
525
-        $parts = explode('.', $propertyPath, 3);
526
-        if ($table->field($fieldName)->isGroup() && count($parts) > 2) {
527
-            $explodedPropertyPath[0] = $parts[0] . '.' . $parts[1];
528
-            $explodedPropertyPath[1] = $parts[2];
529
-            $fieldName = $explodedPropertyPath[0];
530
-        }
531
-
532
-        $parentKeyFieldName = $table->field($fieldName)->getForeignField();
533
-        $childTableName = $table->field($fieldName)->getForeignTable();
534
-
535
-        if ($childTableName === null) {
536
-            throw new InvalidRelationConfigurationException('The relation information for property "' . $fieldName . '" of class "' . $tableName . '" is missing.', 1353170925);
537
-        }
538
-
539
-        if ($table->field($fieldName)->hasOne()) { // includes relation "one-to-one" and "many-to-one"
540
-            // sometimes the opposite relation is not defined. We don't want to force this config for backward compatibility reasons.
541
-            // $parentKeyFieldName === null does the trick somehow. Before condition was if (isset($parentKeyFieldName))
542
-            if ($table->field($fieldName)->hasRelationManyToOne() || $parentKeyFieldName === null) {
543
-                $statementParts['unions'][$childTableName] = 'LEFT JOIN ' . $childTableName . ' ON ' . $tableName . '.' . $fieldName . '=' . $childTableName . '.uid';
544
-            } else {
545
-                $statementParts['unions'][$childTableName] = 'LEFT JOIN ' . $childTableName . ' ON ' . $tableName . '.uid=' . $childTableName . '.' . $parentKeyFieldName;
546
-            }
547
-        } elseif ($table->field($fieldName)->hasRelationManyToMany()) {
548
-            $relationTableName = $table->field($fieldName)->getManyToManyTable();
549
-
550
-            $parentKeyFieldName = $table->field($fieldName)->isOppositeRelation() ? 'uid_foreign' : 'uid_local';
551
-            $childKeyFieldName = !$table->field($fieldName)->isOppositeRelation() ? 'uid_foreign' : 'uid_local';
552
-
553
-            // MM table e.g sys_category_record_mm
554
-            $relationTableNameAlias = $this->generateAlias($relationTableName);
555
-            $join = sprintf(
556
-                'LEFT JOIN %s AS %s ON %s.uid=%s.%s', $relationTableName,
557
-                $relationTableNameAlias,
558
-                $tableName,
559
-                $relationTableNameAlias,
560
-                $parentKeyFieldName
561
-            );
562
-            $statementParts['unions'][$relationTableNameAlias] = $join;
563
-
564
-            // Foreign table e.g sys_category
565
-            $childTableNameAlias = $this->generateAlias($childTableName);
566
-            $this->currentChildTableNameAlias = $childTableNameAlias;
567
-            $join = sprintf(
568
-                'LEFT JOIN %s AS %s ON %s.%s=%s.uid',
569
-                $childTableName,
570
-                $childTableNameAlias,
571
-                $relationTableNameAlias,
572
-                $childKeyFieldName,
573
-                $childTableNameAlias
574
-            );
575
-            $statementParts['unions'][$childTableNameAlias] = $join;
576
-
577
-            // Find a possible table name for a MM condition.
578
-            $tableNameCondition = $table->field($fieldName)->getAdditionalTableNameCondition();
579
-            if ($tableNameCondition) {
580
-
581
-                // If we can find a source file name,  we can then retrieve more MM conditions from the TCA such as a field name.
582
-                $sourceFileName = $this->query->getSourceFieldName();
583
-                if (empty($sourceFileName)) {
584
-                    $additionalMMConditions = array(
585
-                        'tablenames' => $tableNameCondition,
586
-                    );
587
-                } else {
588
-                    $additionalMMConditions = Tca::table($tableNameCondition)->field($sourceFileName)->getAdditionalMMCondition();
589
-                }
590
-
591
-                foreach ($additionalMMConditions as $additionalFieldName => $additionalMMCondition) {
592
-                    $additionalJoin = sprintf(' AND %s.%s = "%s"', $relationTableNameAlias, $additionalFieldName, $additionalMMCondition);
593
-                    $statementParts['unions'][$relationTableNameAlias] .= $additionalJoin;
594
-
595
-                    $additionalJoin = sprintf(' AND %s.%s = "%s"', $relationTableNameAlias, $additionalFieldName, $additionalMMCondition);
596
-                    $statementParts['unions'][$childTableNameAlias] .= $additionalJoin;
597
-                }
598
-            }
599
-
600
-        } elseif ($table->field($fieldName)->hasMany()) { // includes relations "many-to-one" and "csv" relations
601
-            $childTableNameAlias = $this->generateAlias($childTableName);
602
-            $this->currentChildTableNameAlias = $childTableNameAlias;
603
-
604
-            if (isset($parentKeyFieldName)) {
605
-                $join = sprintf(
606
-                    'LEFT JOIN %s AS %s ON %s.uid=%s.%s',
607
-                    $childTableName,
608
-                    $childTableNameAlias,
609
-                    $tableName,
610
-                    $childTableNameAlias,
611
-                    $parentKeyFieldName
612
-                );
613
-                $statementParts['unions'][$childTableNameAlias] = $join;
614
-            } else {
615
-                $join = sprintf(
616
-                    'LEFT JOIN %s AS %s ON (FIND_IN_SET(%s.uid, %s.%s))',
617
-                    $childTableName,
618
-                    $childTableNameAlias,
619
-                    $childTableNameAlias,
620
-                    $tableName,
621
-                    $fieldName
622
-                );
623
-                $statementParts['unions'][$childTableNameAlias] = $join;
624
-            }
625
-        } else {
626
-            throw new Exception('Could not determine type of relation.', 1252502725);
627
-        }
628
-
629
-        $statementParts['keywords']['distinct'] = 'DISTINCT';
630
-        $propertyPath = $explodedPropertyPath[1];
631
-        $tableName = $childTableName;
632
-    }
633
-
634
-    /**
635
-     * Returns the SQL operator for the given JCR operator type.
636
-     *
637
-     * @param string $operator One of the JCR_OPERATOR_* constants
638
-     * @return string an SQL operator
639
-     * @throws Exception
640
-     */
641
-    protected function resolveOperator($operator)
642
-    {
643
-        switch ($operator) {
644
-            case self::OPERATOR_EQUAL_TO_NULL:
645
-                $operator = 'IS';
646
-                break;
647
-            case self::OPERATOR_NOT_EQUAL_TO_NULL:
648
-                $operator = 'IS NOT';
649
-                break;
650
-            case QueryInterface::OPERATOR_IN:
651
-                $operator = 'IN';
652
-                break;
653
-            case QueryInterface::OPERATOR_EQUAL_TO:
654
-                $operator = '=';
655
-                break;
656
-            case QueryInterface::OPERATOR_NOT_EQUAL_TO:
657
-                $operator = '!=';
658
-                break;
659
-            case QueryInterface::OPERATOR_LESS_THAN:
660
-                $operator = '<';
661
-                break;
662
-            case QueryInterface::OPERATOR_LESS_THAN_OR_EQUAL_TO:
663
-                $operator = '<=';
664
-                break;
665
-            case QueryInterface::OPERATOR_GREATER_THAN:
666
-                $operator = '>';
667
-                break;
668
-            case QueryInterface::OPERATOR_GREATER_THAN_OR_EQUAL_TO:
669
-                $operator = '>=';
670
-                break;
671
-            case QueryInterface::OPERATOR_LIKE:
672
-                $operator = 'LIKE';
673
-                break;
674
-            default:
675
-                throw new Exception('Unsupported operator encountered.', 1242816073);
676
-        }
677
-        return $operator;
678
-    }
679
-
680
-    /**
681
-     * Adds additional WHERE statements according to the query settings.
682
-     *
683
-     * @param QuerySettingsInterface $querySettings The TYPO3 CMS specific query settings
684
-     * @param string $tableNameOrAlias The table name to add the additional where clause for
685
-     * @param array &$statementParts
686
-     * @return void
687
-     */
688
-    protected function addAdditionalWhereClause(QuerySettingsInterface $querySettings, $tableNameOrAlias, &$statementParts)
689
-    {
690
-        $this->addVisibilityConstraintStatement($querySettings, $tableNameOrAlias, $statementParts);
691
-        if ($querySettings->getRespectSysLanguage()) {
692
-            $this->addSysLanguageStatement($tableNameOrAlias, $statementParts, $querySettings);
693
-        }
694
-    }
695
-
696
-    /**
697
-     * Adds enableFields and deletedClause to the query if necessary
698
-     *
699
-     * @param QuerySettingsInterface $querySettings
700
-     * @param string $tableNameOrAlias The database table name
701
-     * @param array &$statementParts The query parts
702
-     * @return void
703
-     */
704
-    protected function addVisibilityConstraintStatement(QuerySettingsInterface $querySettings, $tableNameOrAlias, array &$statementParts)
705
-    {
706
-        $statement = '';
707
-        $tableName = $this->resolveTableNameAlias($tableNameOrAlias);
708
-        if (is_array($GLOBALS['TCA'][$tableName]['ctrl'])) {
709
-            $ignoreEnableFields = $querySettings->getIgnoreEnableFields();
710
-            $enableFieldsToBeIgnored = $querySettings->getEnableFieldsToBeIgnored();
711
-            $includeDeleted = $querySettings->getIncludeDeleted();
712
-            if (ApplicationType::fromRequest($GLOBALS['TYPO3_REQUEST'])->isFrontend()) {
713
-                $statement .= $this->getFrontendConstraintStatement($tableNameOrAlias, $ignoreEnableFields, $enableFieldsToBeIgnored, $includeDeleted);
714
-            } else {
715
-                // 'BE' case
716
-                $statement .= $this->getBackendConstraintStatement($tableNameOrAlias, $ignoreEnableFields, $includeDeleted);
717
-            }
718
-
719
-            // Remove the prefixing "AND" if any.
720
-            if (!empty($statement)) {
721
-                $statement = strtolower(substr($statement, 1, 3)) === 'and' ? substr($statement, 5) : $statement;
722
-                $statementParts['additionalWhereClause'][$tableNameOrAlias][] = $statement;
723
-            }
724
-        }
725
-    }
726
-
727
-    /**
728
-     * Returns constraint statement for frontend context
729
-     *
730
-     * @param string $tableNameOrAlias
731
-     * @param boolean $ignoreEnableFields A flag indicating whether the enable fields should be ignored
732
-     * @param array $enableFieldsToBeIgnored If $ignoreEnableFields is true, this array specifies enable fields to be ignored. If it is null or an empty array (default) all enable fields are ignored.
733
-     * @param boolean $includeDeleted A flag indicating whether deleted records should be included
734
-     * @return string
735
-     * @throws Exception\InconsistentQuerySettingsException
736
-     */
737
-    protected function getFrontendConstraintStatement($tableNameOrAlias, $ignoreEnableFields, $enableFieldsToBeIgnored, $includeDeleted)
738
-    {
739
-        $statement = '';
740
-        $tableName = $this->resolveTableNameAlias($tableNameOrAlias);
741
-        if ($ignoreEnableFields && !$includeDeleted) {
742
-            if (count($enableFieldsToBeIgnored)) {
743
-                // array_combine() is necessary because of the way \TYPO3\CMS\Frontend\Page\PageRepository::enableFields() is implemented
744
-                $statement .= $this->getPageRepository()->enableFields($tableName, -1, array_combine($enableFieldsToBeIgnored, $enableFieldsToBeIgnored));
745
-            } else {
746
-                $statement .= $this->getPageRepository()->deleteClause($tableName);
747
-            }
748
-        } elseif (!$ignoreEnableFields && !$includeDeleted) {
749
-            $statement .= $this->getPageRepository()->enableFields($tableName);
750
-        } elseif (!$ignoreEnableFields && $includeDeleted) {
751
-            throw new InconsistentQuerySettingsException('Query setting "ignoreEnableFields=false" can not be used together with "includeDeleted=true" in frontend context.', 1327678173);
752
-        }
753
-        return $this->replaceTableNameByAlias($tableName, $tableNameOrAlias, $statement);
754
-    }
755
-
756
-    /**
757
-     * Returns constraint statement for backend context
758
-     *
759
-     * @param string $tableNameOrAlias
760
-     * @param boolean $ignoreEnableFields A flag indicating whether the enable fields should be ignored
761
-     * @param boolean $includeDeleted A flag indicating whether deleted records should be included
762
-     * @return string
763
-     */
764
-    protected function getBackendConstraintStatement($tableNameOrAlias, $ignoreEnableFields, $includeDeleted)
765
-    {
766
-        $tableName = $this->resolveTableNameAlias($tableNameOrAlias);
767
-        $statement = '';
768
-        if (!$ignoreEnableFields) {
769
-            $statement .= BackendUtility::BEenableFields($tableName);
770
-        }
771
-
772
-        // If the table is found to have "workspace" support, add the corresponding fields in the statement.
773
-        if (Tca::table($tableName)->hasWorkspaceSupport()) {
774
-            if ($this->getBackendUser()->workspace === 0) {
775
-                $statement .= ' AND ' . $tableName . '.t3ver_state<=' . new VersionState(VersionState::DEFAULT_STATE);
776
-            } else {
777
-                // Show only records of live and of the current workspace
778
-                // In case we are in a Versioning preview
779
-                $statement .= ' AND (' .
780
-                    $tableName . '.t3ver_wsid=0 OR ' .
781
-                    $tableName . '.t3ver_wsid=' . (int)$this->getBackendUser()->workspace .
782
-                    ')';
783
-            }
784
-
785
-            // Check if this segment make sense here or whether it should be in the "if" part when we have workspace = 0
786
-            $statement .= ' AND ' . $tableName . '.pid<>-1';
787
-        }
788
-
789
-        if (!$includeDeleted) {
790
-            $statement .= BackendUtility::deleteClause($tableName);
791
-        }
792
-
793
-        return $this->replaceTableNameByAlias($tableName, $tableNameOrAlias, $statement);
794
-    }
795
-
796
-    /**
797
-     * Builds the language field statement
798
-     *
799
-     * @param string $tableNameOrAlias The database table name
800
-     * @param array &$statementParts The query parts
801
-     * @param QuerySettingsInterface $querySettings The TYPO3 CMS specific query settings
802
-     * @return void
803
-     * @throws Exception
804
-     */
805
-    protected function addSysLanguageStatement($tableNameOrAlias, array &$statementParts, $querySettings)
806
-    {
807
-        $tableName = $this->resolveTableNameAlias($tableNameOrAlias);
808
-        if (is_array($GLOBALS['TCA'][$tableName]['ctrl'])) {
809
-            if (!empty($GLOBALS['TCA'][$tableName]['ctrl']['languageField'])) {
810
-                // Select all entries for the current language
811
-                $additionalWhereClause = $tableNameOrAlias . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . ' IN (' . intval($querySettings->getLanguageUid()) . ',-1)';
812
-                // If any language is set -> get those entries which are not translated yet
813
-                // They will be removed by t3lib_page::getRecordOverlay if not matching overlay mode
814
-                if (isset($GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'])
815
-                    && $querySettings->getLanguageUid() > 0
816
-                ) {
817
-                    $additionalWhereClause .= ' OR (' . $tableNameOrAlias . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . '=0' .
818
-                        ' AND ' . $tableNameOrAlias . '.uid NOT IN (SELECT ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'] .
819
-                        ' FROM ' . $tableName .
820
-                        ' WHERE ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'] . '>0' .
821
-                        ' AND ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . '>0';
822
-
823
-                    // Add delete clause to ensure all entries are loaded
824
-                    if (isset($GLOBALS['TCA'][$tableName]['ctrl']['delete'])) {
825
-                        $additionalWhereClause .= ' AND ' . $tableNameOrAlias . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['delete'] . '=0';
826
-                    }
827
-                    $additionalWhereClause .= '))';
828
-                }
829
-                $statementParts['additionalWhereClause'][$tableNameOrAlias][] = '(' . $additionalWhereClause . ')';
830
-            }
831
-        }
832
-    }
833
-
834
-    /**
835
-     * Transforms orderings into SQL.
836
-     *
837
-     * @param array $orderings An array of orderings (Tx_Extbase_Persistence_QOM_Ordering)
838
-     * @param SourceInterface $source The source
839
-     * @param array &$statementParts The query parts
840
-     * @return void
841
-     * @throws Exception\UnsupportedOrderException
842
-     */
843
-    protected function parseOrderings(array $orderings, SourceInterface $source, array &$statementParts)
844
-    {
845
-        foreach ($orderings as $fieldNameAndPath => $order) {
846
-            switch ($order) {
847
-                case QueryInterface::ORDER_ASCENDING:
848
-                    $order = 'ASC';
849
-                    break;
850
-                case QueryInterface::ORDER_DESCENDING:
851
-                    $order = 'DESC';
852
-                    break;
853
-                default:
854
-                    throw new UnsupportedOrderException('Unsupported order encountered.', 1456845126);
855
-            }
856
-
857
-            $tableName = $this->getFieldPathResolver()->getDataType($fieldNameAndPath, $this->query->getType());
858
-            $fieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath, $tableName);
859
-            $statementParts['orderings'][] = sprintf('%s.%s %s', $tableName, $fieldName, $order);
860
-        }
861
-    }
862
-
863
-    /**
864
-     * Transforms limit and offset into SQL
865
-     *
866
-     * @param int $limit
867
-     * @param int $offset
868
-     * @param array &$statementParts
869
-     * @return void
870
-     */
871
-    protected function parseLimitAndOffset($limit, $offset, array &$statementParts)
872
-    {
873
-        if ($limit !== null && $offset !== null) {
874
-            $statementParts['limit'] = intval($offset) . ', ' . intval($limit);
875
-        } elseif ($limit !== null) {
876
-            $statementParts['limit'] = intval($limit);
877
-        }
878
-    }
879
-
880
-    /**
881
-     * @param array $rows
882
-     * @return array
883
-     */
884
-    protected function getContentObjects(array $rows): array
885
-    {
886
-        $contentObjects = [];
887
-        foreach ($rows as $row) {
888
-
889
-            // Get language uid from querySettings.
890
-            // Ensure the backend handling is not broken (fallback to Get parameter 'L' if needed)
891
-            $overlaidRow = $this->doLanguageAndWorkspaceOverlay(
892
-                $row,
893
-                $this->query->getTypo3QuerySettings()
894
-            );
895
-
896
-            $contentObjects[] = GeneralUtility::makeInstance(
897
-                Content::class,
898
-                $this->query->getType(),
899
-                $overlaidRow
900
-            );
901
-        }
902
-
903
-        return $contentObjects;
904
-    }
905
-
906
-    /**
907
-     * Performs workspace and language overlay on the given row array. The language and workspace id is automatically
908
-     * detected (depending on FE or BE context). You can also explicitly set the language/workspace id.
909
-     *
910
-     * @param array $row
911
-     * @param QuerySettingsInterface $querySettings The TYPO3 CMS specific query settings
912
-     * @return array
913
-     */
914
-    protected function doLanguageAndWorkspaceOverlay(array $row, $querySettings)
915
-    {
916
-        $tableName = $this->getTableName();
917
-
918
-        $pageRepository = $this->getPageRepository();
919
-        if (is_object($GLOBALS['TSFE'])) {
920
-            $languageMode = GeneralUtility::makeInstance(Context::class)->getPropertyFromAspect('language', 'legacyLanguageMode');
921
-            #if ($this->isBackendUserLogged() && $this->getBackendUser()->workspace !== 0) {
922
-            #    $pageRepository->versioningWorkspaceId = $this->getBackendUser()->workspace;
923
-            #}
924
-        } else {
925
-            $languageMode = '';
926
-            $workspaceUid = $this->getBackendUser()->workspace;
927
-            #$pageRepository->versioningWorkspaceId = $workspaceUid;
928
-            #if ($this->getBackendUser()->workspace !== 0) {
929
-            #    $pageRepository->versioningPreview = 1;
930
-            #}
931
-        }
932
-
933
-        // If current row is a translation select its parent
934
-        if (isset($GLOBALS['TCA'][$tableName]['ctrl']['languageField'])
935
-            && isset($GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'])
936
-        ) {
937
-            if (isset($row[$GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField']])
938
-                && $row[$GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField']] > 0
939
-            ) {
940
-                $queryBuilder = $this->getQueryBuilder();
941
-                $row = $queryBuilder
942
-                    ->select($tableName . '.*')
943
-                    ->from($tableName)
944
-                    ->andWhere(
945
-                        $tableName . '.uid=' . (int)$row[$GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField']],
946
-                        $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . ' = 0'
947
-                    )
948
-                    ->execute()
949
-                    ->fetch();
950
-            }
951
-        }
952
-
953
-        // Retrieve the original uid; Used for Workspaces!
954
-        if (ApplicationType::fromRequest($GLOBALS['TYPO3_REQUEST'])->isBackend()) {
955
-            $pageRepository->versionOL($tableName, $row, true, true);
956
-        } else {
957
-            \TYPO3\CMS\Backend\Utility\BackendUtility::workspaceOL($tableName, $row);
958
-        }
959
-        if (isset($row['_ORIG_uid'])) {
960
-            $row['uid'] = $row['_ORIG_uid'];
961
-        }
962
-
963
-        // Special case for table "pages"
964
-        if ($tableName == 'pages') {
965
-            $row = $pageRepository->getPageOverlay($row, $querySettings->getLanguageUid());
966
-        } elseif (isset($GLOBALS['TCA'][$tableName]['ctrl']['languageField'])
967
-            && $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] !== ''
968
-        ) {
969
-            if (in_array($row[$GLOBALS['TCA'][$tableName]['ctrl']['languageField']], array(-1, 0))) {
970
-                $overlayMode = $languageMode === 'strict' ? 'hideNonTranslated' : '';
971
-                $row = $pageRepository->getRecordOverlay($tableName, $row, $querySettings->getLanguageUid(), $overlayMode);
972
-            }
973
-        }
974
-
975
-        return $row;
976
-    }
977
-
978
-    /**
979
-     * Return a resolved table name given a possible table name alias.
980
-     *
981
-     * @param string $tableNameOrAlias
982
-     * @return string
983
-     */
984
-    protected function resolveTableNameAlias($tableNameOrAlias)
985
-    {
986
-        $resolvedTableName = $tableNameOrAlias;
987
-        if (!empty($this->tableNameAliases['aliases'][$tableNameOrAlias])) {
988
-            $resolvedTableName = $this->tableNameAliases['aliases'][$tableNameOrAlias];
989
-        }
990
-        return $resolvedTableName;
991
-    }
992
-
993
-    /**
994
-     * Generate a unique table name alias for the given table name.
995
-     *
996
-     * @param string $tableName
997
-     * @return string
998
-     */
999
-    protected function generateAlias($tableName)
1000
-    {
1001
-
1002
-        if (!isset($this->tableNameAliases['aliasIncrement'][$tableName])) {
1003
-            $this->tableNameAliases['aliasIncrement'][$tableName] = 0;
1004
-        }
1005
-
1006
-        $numberOfAliases = $this->tableNameAliases['aliasIncrement'][$tableName];
1007
-        $tableNameAlias = $tableName . $numberOfAliases;
1008
-
1009
-        $this->tableNameAliases['aliasIncrement'][$tableName]++;
1010
-        $this->tableNameAliases['aliases'][$tableNameAlias] = $tableName;
1011
-
1012
-        return $tableNameAlias;
1013
-    }
1014
-
1015
-    /**
1016
-     * Replace the table names by its table name alias within the given statement.
1017
-     *
1018
-     * @param string $tableName
1019
-     * @param string $tableNameAlias
1020
-     * @param string $statement
1021
-     * @return string
1022
-     */
1023
-    protected function replaceTableNameByAlias($tableName, $tableNameAlias, $statement)
1024
-    {
1025
-        if ($statement && $tableName !== $tableNameAlias) {
1026
-            $statement = str_replace($tableName, $tableNameAlias, $statement);
1027
-        }
1028
-        return $statement;
1029
-    }
1030
-
1031
-    /**
1032
-     * Returns an instance of the current Backend User.
1033
-     *
1034
-     * @return BackendUserAuthentication
1035
-     */
1036
-    protected function getBackendUser()
1037
-    {
1038
-        return $GLOBALS['BE_USER'];
1039
-    }
1040
-
1041
-    /**
1042
-     * Tell whether a Backend User is logged in.
1043
-     *
1044
-     * @return bool
1045
-     */
1046
-    protected function isBackendUserLogged()
1047
-    {
1048
-        return is_object($GLOBALS['BE_USER']);
1049
-    }
1050
-
1051
-    /**
1052
-     * @return PageRepository|object
1053
-     */
1054
-    protected function getPageRepository()
1055
-    {
1056
-        if (!$this->pageRepository instanceof PageRepository) {
1057
-            if (ApplicationType::fromRequest($GLOBALS['TYPO3_REQUEST'])->isFrontend() && is_object($GLOBALS['TSFE'])) {
1058
-                $this->pageRepository = $GLOBALS['TSFE']->sys_page;
1059
-            } else {
1060
-                $this->pageRepository = GeneralUtility::makeInstance(PageRepository::class);
1061
-            }
1062
-        }
1063
-
1064
-        return $this->pageRepository;
1065
-    }
1066
-
1067
-    /**
1068
-     * @return FieldPathResolver|object
1069
-     */
1070
-    protected function getFieldPathResolver()
1071
-    {
1072
-        return GeneralUtility::makeInstance(FieldPathResolver::class);
1073
-    }
1074
-
1075
-    /**
1076
-     * @return object|Connection
1077
-     */
1078
-    protected function getConnection(): Connection
1079
-    {
1080
-        /** @var ConnectionPool $connectionPool */
1081
-        return GeneralUtility::makeInstance(ConnectionPool::class)
1082
-            ->getConnectionForTable($this->getTableName());
1083
-    }
1084
-
1085
-    /**
1086
-     * @return object|QueryBuilder
1087
-     */
1088
-    protected function getQueryBuilder(): QueryBuilder
1089
-    {
1090
-        /** @var ConnectionPool $connectionPool */
1091
-        $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
1092
-        return $connectionPool->getQueryBuilderForTable($this->getTableName());
1093
-    }
1094
-
1095
-    /**
1096
-     * @return string
1097
-     */
1098
-    public function getTableName(): string
1099
-    {
1100
-        return $this->query->getSource()->getNodeTypeName(); // getSelectorName()
1101
-    }
55
+	const OPERATOR_EQUAL_TO_NULL = 'operatorEqualToNull';
56
+	const OPERATOR_NOT_EQUAL_TO_NULL = 'operatorNotEqualToNull';
57
+
58
+	/**
59
+	 * The TYPO3 page repository. Used for language and workspace overlay
60
+	 *
61
+	 * @var PageRepository
62
+	 */
63
+	protected $pageRepository;
64
+
65
+	/**
66
+	 * @var Query
67
+	 */
68
+	protected $query;
69
+
70
+	/**
71
+	 * Store some info related to table name and its aliases.
72
+	 *
73
+	 * @var array
74
+	 */
75
+	protected $tableNameAliases = array(
76
+		'aliases' => [],
77
+		'aliasIncrement' => [],
78
+	);
79
+
80
+	/**
81
+	 * Use to store the current foreign table name alias.
82
+	 *
83
+	 * @var string
84
+	 */
85
+	protected $currentChildTableNameAlias = '';
86
+
87
+	/**
88
+	 * @param Query $query
89
+	 */
90
+	public function __construct(Query $query)
91
+	{
92
+		$this->query = $query;
93
+	}
94
+
95
+	/**
96
+	 * @param $parameters
97
+	 * @return array
98
+	 */
99
+	protected static function getTypes($parameters)
100
+	{
101
+		$types = [];
102
+		foreach ($parameters as $parameter) {
103
+			if (is_array($parameter)) {
104
+				if (MathUtility::canBeInterpretedAsInteger($parameter[0])) {
105
+					$types[] = \Doctrine\DBAL\Connection::PARAM_INT_ARRAY;
106
+				} else {
107
+					$types[] = \Doctrine\DBAL\Connection::PARAM_STR_ARRAY;
108
+				}
109
+			} else {
110
+				if (MathUtility::canBeInterpretedAsInteger($parameter)) {
111
+					$types[] = ParameterType::INTEGER;
112
+				} else {
113
+					$types[] = ParameterType::STRING;
114
+				}
115
+			}
116
+		}
117
+		return $types;
118
+	}
119
+
120
+	/**
121
+	 * Returns the result of the query
122
+	 */
123
+	public function fetchResult()
124
+	{
125
+		$parameters = [];
126
+		$statementParts = $this->parseQuery($parameters);
127
+		$statementParts = $this->processStatementStructureForRecursiveMMRelation($statementParts);
128
+		$sql = $this->buildQuery($statementParts);
129
+		//print $sql; exit();
130
+
131
+		$rows = $this->getConnection()
132
+			->executeQuery($sql, $parameters, self::getTypes($parameters))
133
+			->fetchAll();
134
+
135
+		return $this->getContentObjects($rows);
136
+	}
137
+
138
+	/**
139
+	 * Returns the number of tuples matching the query.
140
+	 *
141
+	 * @return int The number of matching tuples
142
+	 */
143
+	public function countResult()
144
+	{
145
+		$parameters = [];
146
+		$statementParts = $this->parseQuery($parameters);
147
+		$statementParts = $this->processStatementStructureForRecursiveMMRelation($statementParts);
148
+		$types = self::getTypes($parameters);
149
+
150
+		// if limit is set, we need to count the rows "manually" as COUNT(*) ignores LIMIT constraints
151
+		if (!empty($statementParts['limit'])) {
152
+			$sql = $this->buildQuery($statementParts);
153
+
154
+			$count = $this
155
+				->getConnection()
156
+				->executeQuery($sql, $parameters, $types)
157
+				->rowCount();
158
+		} else {
159
+			$statementParts['fields'] = array('COUNT(*)');
160
+			// having orderings without grouping is not compatible with non-MySQL DBMS
161
+			$statementParts['orderings'] = [];
162
+			if (isset($statementParts['keywords']['distinct'])) {
163
+				unset($statementParts['keywords']['distinct']);
164
+				$distinctField = $this->query->getDistinct() ? $this->query->getDistinct() : 'uid';
165
+				$statementParts['fields'] = array('COUNT(DISTINCT ' . $statementParts['mainTable'] . '.' . $distinctField . ')');
166
+			}
167
+
168
+			$sql = $this->buildQuery($statementParts);
169
+			$count = $this
170
+				->getConnection()
171
+				->executeQuery($sql, $parameters, $types)
172
+				->fetchColumn(0);
173
+		}
174
+		return (int)$count;
175
+	}
176
+
177
+	/**
178
+	 * Parses the query and returns the SQL statement parts.
179
+	 *
180
+	 * @param array &$parameters
181
+	 * @return array
182
+	 */
183
+	public function parseQuery(array &$parameters)
184
+	{
185
+		$statementParts = [];
186
+		$statementParts['keywords'] = [];
187
+		$statementParts['tables'] = [];
188
+		$statementParts['unions'] = [];
189
+		$statementParts['fields'] = [];
190
+		$statementParts['where'] = [];
191
+		$statementParts['additionalWhereClause'] = [];
192
+		$statementParts['orderings'] = [];
193
+		$statementParts['limit'] = [];
194
+		$query = $this->query;
195
+		$source = $query->getSource();
196
+		$this->parseSource($source, $statementParts);
197
+		$this->parseConstraint($query->getConstraint(), $source, $statementParts, $parameters);
198
+		$this->parseOrderings($query->getOrderings(), $source, $statementParts);
199
+		$this->parseLimitAndOffset($query->getLimit(), $query->getOffset(), $statementParts);
200
+		$tableNames = array_unique(array_keys($statementParts['tables'] + $statementParts['unions']));
201
+		foreach ($tableNames as $tableNameOrAlias) {
202
+			if (is_string($tableNameOrAlias) && strlen($tableNameOrAlias) > 0) {
203
+				$this->addAdditionalWhereClause($query->getTypo3QuerySettings(), $tableNameOrAlias, $statementParts);
204
+			}
205
+		}
206
+
207
+		return $statementParts;
208
+	}
209
+
210
+	/**
211
+	 * Fiddle with the statement structure to handle recursive MM relations.
212
+	 * For the recursive MM query to work, we must invert some values.
213
+	 * Let see if that is the best way of doing that...
214
+	 *
215
+	 * @param array $statementParts
216
+	 * @return array
217
+	 */
218
+	public function processStatementStructureForRecursiveMMRelation(array $statementParts)
219
+	{
220
+
221
+		if ($this->hasRecursiveMMRelation()) {
222
+			$tableName = $this->query->getType();
223
+
224
+			// In order the MM query to work for a recursive MM query, we must invert some values.
225
+			// tx_domain_model_foo0 (the alias) <--> tx_domain_model_foo (the origin table name)
226
+			$values = [];
227
+			foreach ($statementParts['fields'] as $key => $value) {
228
+				$values[$key] = str_replace($tableName, $tableName . '0', $value);
229
+			}
230
+			$statementParts['fields'] = $values;
231
+
232
+			// Same comment as above.
233
+			$values = [];
234
+			foreach ($statementParts['where'] as $key => $value) {
235
+				$values[$key] = str_replace($tableName . '0', $tableName, $value);
236
+			}
237
+			$statementParts['where'] = $values;
238
+
239
+			// We must be more restrictive by transforming the "left" union by "inner"
240
+			$values = [];
241
+			foreach ($statementParts['unions'] as $key => $value) {
242
+				$values[$key] = str_replace('LEFT JOIN', 'INNER JOIN', $value);
243
+			}
244
+			$statementParts['unions'] = $values;
245
+		}
246
+
247
+		return $statementParts;
248
+	}
249
+
250
+	/**
251
+	 * Tell whether there is a recursive MM relation.
252
+	 *
253
+	 * @return bool
254
+	 */
255
+	public function hasRecursiveMMRelation()
256
+	{
257
+		return isset($this->tableNameAliases['aliasIncrement'][$this->query->getType()]);
258
+
259
+	}
260
+
261
+	/**
262
+	 * Returns the statement, ready to be executed.
263
+	 *
264
+	 * @param array $statementParts The SQL statement parts
265
+	 * @return string The SQL statement
266
+	 */
267
+	public function buildQuery(array $statementParts)
268
+	{
269
+
270
+		// Add more statement to the UNION part.
271
+		if (!empty($statementParts['unions'])) {
272
+			foreach ($statementParts['unions'] as $tableName => $unionPart) {
273
+				if (!empty($statementParts['additionalWhereClause'][$tableName])) {
274
+					$statementParts['unions'][$tableName] .= ' AND ' . implode(' AND ', $statementParts['additionalWhereClause'][$tableName]);
275
+				}
276
+			}
277
+		}
278
+
279
+		$statement = 'SELECT ' . implode(' ', $statementParts['keywords']) . ' ' . implode(',', $statementParts['fields']) . ' FROM ' . implode(' ', $statementParts['tables']) . ' ' . implode(' ', $statementParts['unions']);
280
+		if (!empty($statementParts['where'])) {
281
+			$statement .= ' WHERE ' . implode('', $statementParts['where']);
282
+			if (!empty($statementParts['additionalWhereClause'][$this->query->getType()])) {
283
+				$statement .= ' AND ' . implode(' AND ', $statementParts['additionalWhereClause'][$this->query->getType()]);
284
+			}
285
+		} elseif (!empty($statementParts['additionalWhereClause'])) {
286
+			$statement .= ' WHERE ' . implode(' AND ', $statementParts['additionalWhereClause'][$this->query->getType()]);
287
+		}
288
+		if (!empty($statementParts['orderings'])) {
289
+			$statement .= ' ORDER BY ' . implode(', ', $statementParts['orderings']);
290
+		}
291
+		if (!empty($statementParts['limit'])) {
292
+			$statement .= ' LIMIT ' . $statementParts['limit'];
293
+		}
294
+
295
+		return $statement;
296
+	}
297
+
298
+	/**
299
+	 * Transforms a Query Source into SQL and parameter arrays
300
+	 *
301
+	 * @param SourceInterface $source The source
302
+	 * @param array &$sql
303
+	 * @return void
304
+	 */
305
+	protected function parseSource(SourceInterface $source, array &$sql)
306
+	{
307
+		$tableName = $this->getTableName();
308
+		$sql['fields'][$tableName] = $tableName . '.*';
309
+		if ($this->query->getDistinct()) {
310
+			$sql['fields'][$tableName] = $tableName . '.' . $this->query->getDistinct();
311
+			$sql['keywords']['distinct'] = 'DISTINCT';
312
+		}
313
+		$sql['tables'][$tableName] = $tableName;
314
+		$sql['mainTable'] = $tableName;
315
+	}
316
+
317
+	/**
318
+	 * Transforms a constraint into SQL and parameter arrays
319
+	 *
320
+	 * @param ConstraintInterface $constraint The constraint
321
+	 * @param SourceInterface $source The source
322
+	 * @param array &$statementParts The query parts
323
+	 * @param array &$parameters The parameters that will replace the markers
324
+	 * @return void
325
+	 */
326
+	protected function parseConstraint(ConstraintInterface $constraint = null, SourceInterface $source, array &$statementParts, array &$parameters)
327
+	{
328
+		if ($constraint instanceof AndInterface) {
329
+			$statementParts['where'][] = '(';
330
+			$this->parseConstraint($constraint->getConstraint1(), $source, $statementParts, $parameters);
331
+			$statementParts['where'][] = ' AND ';
332
+			$this->parseConstraint($constraint->getConstraint2(), $source, $statementParts, $parameters);
333
+			$statementParts['where'][] = ')';
334
+		} elseif ($constraint instanceof OrInterface) {
335
+			$statementParts['where'][] = '(';
336
+			$this->parseConstraint($constraint->getConstraint1(), $source, $statementParts, $parameters);
337
+			$statementParts['where'][] = ' OR ';
338
+			$this->parseConstraint($constraint->getConstraint2(), $source, $statementParts, $parameters);
339
+			$statementParts['where'][] = ')';
340
+		} elseif ($constraint instanceof NotInterface) {
341
+			$statementParts['where'][] = 'NOT (';
342
+			$this->parseConstraint($constraint->getConstraint(), $source, $statementParts, $parameters);
343
+			$statementParts['where'][] = ')';
344
+		} elseif ($constraint instanceof ComparisonInterface) {
345
+			$this->parseComparison($constraint, $source, $statementParts, $parameters);
346
+		}
347
+	}
348
+
349
+	/**
350
+	 * Parse a Comparison into SQL and parameter arrays.
351
+	 *
352
+	 * @param ComparisonInterface $comparison The comparison to parse
353
+	 * @param SourceInterface $source The source
354
+	 * @param array &$statementParts SQL query parts to add to
355
+	 * @param array &$parameters Parameters to bind to the SQL
356
+	 * @return void
357
+	 * @throws Exception\RepositoryException
358
+	 */
359
+	protected function parseComparison(ComparisonInterface $comparison, SourceInterface $source, array &$statementParts, array &$parameters)
360
+	{
361
+		$operand1 = $comparison->getOperand1();
362
+		$operator = $comparison->getOperator();
363
+		$operand2 = $comparison->getOperand2();
364
+		if ($operator === QueryInterface::OPERATOR_IN) {
365
+			$items = [];
366
+			$hasValue = false;
367
+			foreach ($operand2 as $value) {
368
+				$value = $this->getPlainValue($value);
369
+				if ($value !== null) {
370
+					$items[] = $value;
371
+					$hasValue = true;
372
+				}
373
+			}
374
+			if ($hasValue === false) {
375
+				$statementParts['where'][] = '1<>1';
376
+			} else {
377
+				$this->parseDynamicOperand($operand1, $operator, $source, $statementParts, $parameters, null);
378
+				$parameters[] = $items;
379
+			}
380
+		} elseif ($operator === QueryInterface::OPERATOR_CONTAINS) {
381
+			if ($operand2 === null) {
382
+				$statementParts['where'][] = '1<>1';
383
+			} else {
384
+				throw new \Exception('Not implemented! Contact extension author.', 1412931227);
385
+				# @todo re-implement me if necessary.
386
+				#$tableName = $this->query->getType();
387
+				#$propertyName = $operand1->getPropertyName();
388
+				#while (strpos($propertyName, '.') !== false) {
389
+				#	$this->addUnionStatement($tableName, $propertyName, $statementParts);
390
+				#}
391
+				#$columnName = $propertyName;
392
+				#$columnMap = $propertyName;
393
+				#$typeOfRelation = $columnMap instanceof ColumnMap ? $columnMap->getTypeOfRelation() : null;
394
+				#if ($typeOfRelation === ColumnMap::RELATION_HAS_AND_BELONGS_TO_MANY) {
395
+				#	$relationTableName = $columnMap->getRelationTableName();
396
+				#	$statementParts['where'][] = $tableName . '.uid IN (SELECT ' . $columnMap->getParentKeyFieldName() . ' FROM ' . $relationTableName . ' WHERE ' . $columnMap->getChildKeyFieldName() . '=?)';
397
+				#	$parameters[] = intval($this->getPlainValue($operand2));
398
+				#} elseif ($typeOfRelation === ColumnMap::RELATION_HAS_MANY) {
399
+				#	$parentKeyFieldName = $columnMap->getParentKeyFieldName();
400
+				#	if (isset($parentKeyFieldName)) {
401
+				#		$childTableName = $columnMap->getChildTableName();
402
+				#		$statementParts['where'][] = $tableName . '.uid=(SELECT ' . $childTableName . '.' . $parentKeyFieldName . ' FROM ' . $childTableName . ' WHERE ' . $childTableName . '.uid=?)';
403
+				#		$parameters[] = intval($this->getPlainValue($operand2));
404
+				#	} else {
405
+				#		$statementParts['where'][] = 'FIND_IN_SET(?,' . $tableName . '.' . $columnName . ')';
406
+				#		$parameters[] = intval($this->getPlainValue($operand2));
407
+				#	}
408
+				#} else {
409
+				#	throw new Exception\RepositoryException('Unsupported or non-existing property name "' . $propertyName . '" used in relation matching.', 1327065745);
410
+				#}
411
+			}
412
+		} else {
413
+			if ($operand2 === null) {
414
+				if ($operator === QueryInterface::OPERATOR_EQUAL_TO) {
415
+					$operator = self::OPERATOR_EQUAL_TO_NULL;
416
+				} elseif ($operator === QueryInterface::OPERATOR_NOT_EQUAL_TO) {
417
+					$operator = self::OPERATOR_NOT_EQUAL_TO_NULL;
418
+				}
419
+			}
420
+			$this->parseDynamicOperand($operand1, $operator, $source, $statementParts, $parameters);
421
+			$parameters[] = $this->getPlainValue($operand2);
422
+		}
423
+	}
424
+
425
+	/**
426
+	 * Returns a plain value, i.e. objects are flattened if possible.
427
+	 *
428
+	 * @param mixed $input
429
+	 * @return mixed
430
+	 * @throws UnexpectedTypeException
431
+	 */
432
+	protected function getPlainValue($input)
433
+	{
434
+		if (is_array($input)) {
435
+			throw new UnexpectedTypeException('An array could not be converted to a plain value.', 1274799932);
436
+		}
437
+		if ($input instanceof \DateTime) {
438
+			return $input->format('U');
439
+		} elseif (is_object($input)) {
440
+			if ($input instanceof LazyLoadingProxy) {
441
+				$realInput = $input->_loadRealInstance();
442
+			} else {
443
+				$realInput = $input;
444
+			}
445
+			if ($realInput instanceof DomainObjectInterface) {
446
+				return $realInput->getUid();
447
+			} else {
448
+				throw new UnexpectedTypeException('An object of class "' . get_class($realInput) . '" could not be converted to a plain value.', 1274799934);
449
+			}
450
+		} elseif (is_bool($input)) {
451
+			return $input === true ? 1 : 0;
452
+		} else {
453
+			return $input;
454
+		}
455
+	}
456
+
457
+	/**
458
+	 * Parse a DynamicOperand into SQL and parameter arrays.
459
+	 *
460
+	 * @param DynamicOperandInterface $operand
461
+	 * @param string $operator One of the JCR_OPERATOR_* constants
462
+	 * @param SourceInterface $source The source
463
+	 * @param array &$statementParts The query parts
464
+	 * @param array &$parameters The parameters that will replace the markers
465
+	 * @param string $valueFunction an optional SQL function to apply to the operand value
466
+	 * @return void
467
+	 */
468
+	protected function parseDynamicOperand(DynamicOperandInterface $operand, $operator, SourceInterface $source, array &$statementParts, array &$parameters, $valueFunction = null)
469
+	{
470
+		if ($operand instanceof LowerCaseInterface) {
471
+			$this->parseDynamicOperand($operand->getOperand(), $operator, $source, $statementParts, $parameters, 'LOWER');
472
+		} elseif ($operand instanceof UpperCaseInterface) {
473
+			$this->parseDynamicOperand($operand->getOperand(), $operator, $source, $statementParts, $parameters, 'UPPER');
474
+		} elseif ($operand instanceof PropertyValueInterface) {
475
+			$propertyName = $operand->getPropertyName();
476
+
477
+			// Reset value.
478
+			$this->currentChildTableNameAlias = '';
479
+
480
+			if ($source instanceof SelectorInterface) {
481
+				$tableName = $this->query->getType();
482
+				while (strpos($propertyName, '.') !== false) {
483
+					$this->addUnionStatement($tableName, $propertyName, $statementParts);
484
+				}
485
+			} elseif ($source instanceof JoinInterface) {
486
+				$tableName = $source->getJoinCondition()->getSelector1Name();
487
+			}
488
+
489
+			$columnName = $propertyName;
490
+			$resolvedOperator = $this->resolveOperator($operator);
491
+			$constraintSQL = '';
492
+
493
+			$marker = $operator === QueryInterface::OPERATOR_IN
494
+				? '(?)'
495
+				: '?';
496
+
497
+			if ($valueFunction === null) {
498
+				$constraintSQL .= (!empty($tableName) ? $tableName . '.' : '') . $columnName . ' ' . $resolvedOperator . ' ' . $marker;
499
+			} else {
500
+				$constraintSQL .= $valueFunction . '(' . (!empty($tableName) ? $tableName . '.' : '') . $columnName . ') ' . $resolvedOperator . ' ' . $marker;
501
+			}
502
+
503
+			if (isset($tableName) && !empty($this->currentChildTableNameAlias)) {
504
+				$constraintSQL = $this->replaceTableNameByAlias($tableName, $this->currentChildTableNameAlias, $constraintSQL);
505
+			}
506
+			$statementParts['where'][] = $constraintSQL;
507
+		}
508
+	}
509
+
510
+	/**
511
+	 * @param string &$tableName
512
+	 * @param string &$propertyPath
513
+	 * @param array &$statementParts
514
+	 */
515
+	protected function addUnionStatement(&$tableName, &$propertyPath, array &$statementParts)
516
+	{
517
+
518
+		$table = Tca::table($tableName);
519
+
520
+		$explodedPropertyPath = explode('.', $propertyPath, 2);
521
+		$fieldName = $explodedPropertyPath[0];
522
+
523
+		// Field of type "group" are special because property path must contain the table name
524
+		// to determine the relation type. Example for sys_category, property path will look like "items.sys_file"
525
+		$parts = explode('.', $propertyPath, 3);
526
+		if ($table->field($fieldName)->isGroup() && count($parts) > 2) {
527
+			$explodedPropertyPath[0] = $parts[0] . '.' . $parts[1];
528
+			$explodedPropertyPath[1] = $parts[2];
529
+			$fieldName = $explodedPropertyPath[0];
530
+		}
531
+
532
+		$parentKeyFieldName = $table->field($fieldName)->getForeignField();
533
+		$childTableName = $table->field($fieldName)->getForeignTable();
534
+
535
+		if ($childTableName === null) {
536
+			throw new InvalidRelationConfigurationException('The relation information for property "' . $fieldName . '" of class "' . $tableName . '" is missing.', 1353170925);
537
+		}
538
+
539
+		if ($table->field($fieldName)->hasOne()) { // includes relation "one-to-one" and "many-to-one"
540
+			// sometimes the opposite relation is not defined. We don't want to force this config for backward compatibility reasons.
541
+			// $parentKeyFieldName === null does the trick somehow. Before condition was if (isset($parentKeyFieldName))
542
+			if ($table->field($fieldName)->hasRelationManyToOne() || $parentKeyFieldName === null) {
543
+				$statementParts['unions'][$childTableName] = 'LEFT JOIN ' . $childTableName . ' ON ' . $tableName . '.' . $fieldName . '=' . $childTableName . '.uid';
544
+			} else {
545
+				$statementParts['unions'][$childTableName] = 'LEFT JOIN ' . $childTableName . ' ON ' . $tableName . '.uid=' . $childTableName . '.' . $parentKeyFieldName;
546
+			}
547
+		} elseif ($table->field($fieldName)->hasRelationManyToMany()) {
548
+			$relationTableName = $table->field($fieldName)->getManyToManyTable();
549
+
550
+			$parentKeyFieldName = $table->field($fieldName)->isOppositeRelation() ? 'uid_foreign' : 'uid_local';
551
+			$childKeyFieldName = !$table->field($fieldName)->isOppositeRelation() ? 'uid_foreign' : 'uid_local';
552
+
553
+			// MM table e.g sys_category_record_mm
554
+			$relationTableNameAlias = $this->generateAlias($relationTableName);
555
+			$join = sprintf(
556
+				'LEFT JOIN %s AS %s ON %s.uid=%s.%s', $relationTableName,
557
+				$relationTableNameAlias,
558
+				$tableName,
559
+				$relationTableNameAlias,
560
+				$parentKeyFieldName
561
+			);
562
+			$statementParts['unions'][$relationTableNameAlias] = $join;
563
+
564
+			// Foreign table e.g sys_category
565
+			$childTableNameAlias = $this->generateAlias($childTableName);
566
+			$this->currentChildTableNameAlias = $childTableNameAlias;
567
+			$join = sprintf(
568
+				'LEFT JOIN %s AS %s ON %s.%s=%s.uid',
569
+				$childTableName,
570
+				$childTableNameAlias,
571
+				$relationTableNameAlias,
572
+				$childKeyFieldName,
573
+				$childTableNameAlias
574
+			);
575
+			$statementParts['unions'][$childTableNameAlias] = $join;
576
+
577
+			// Find a possible table name for a MM condition.
578
+			$tableNameCondition = $table->field($fieldName)->getAdditionalTableNameCondition();
579
+			if ($tableNameCondition) {
580
+
581
+				// If we can find a source file name,  we can then retrieve more MM conditions from the TCA such as a field name.
582
+				$sourceFileName = $this->query->getSourceFieldName();
583
+				if (empty($sourceFileName)) {
584
+					$additionalMMConditions = array(
585
+						'tablenames' => $tableNameCondition,
586
+					);
587
+				} else {
588
+					$additionalMMConditions = Tca::table($tableNameCondition)->field($sourceFileName)->getAdditionalMMCondition();
589
+				}
590
+
591
+				foreach ($additionalMMConditions as $additionalFieldName => $additionalMMCondition) {
592
+					$additionalJoin = sprintf(' AND %s.%s = "%s"', $relationTableNameAlias, $additionalFieldName, $additionalMMCondition);
593
+					$statementParts['unions'][$relationTableNameAlias] .= $additionalJoin;
594
+
595
+					$additionalJoin = sprintf(' AND %s.%s = "%s"', $relationTableNameAlias, $additionalFieldName, $additionalMMCondition);
596
+					$statementParts['unions'][$childTableNameAlias] .= $additionalJoin;
597
+				}
598
+			}
599
+
600
+		} elseif ($table->field($fieldName)->hasMany()) { // includes relations "many-to-one" and "csv" relations
601
+			$childTableNameAlias = $this->generateAlias($childTableName);
602
+			$this->currentChildTableNameAlias = $childTableNameAlias;
603
+
604
+			if (isset($parentKeyFieldName)) {
605
+				$join = sprintf(
606
+					'LEFT JOIN %s AS %s ON %s.uid=%s.%s',
607
+					$childTableName,
608
+					$childTableNameAlias,
609
+					$tableName,
610
+					$childTableNameAlias,
611
+					$parentKeyFieldName
612
+				);
613
+				$statementParts['unions'][$childTableNameAlias] = $join;
614
+			} else {
615
+				$join = sprintf(
616
+					'LEFT JOIN %s AS %s ON (FIND_IN_SET(%s.uid, %s.%s))',
617
+					$childTableName,
618
+					$childTableNameAlias,
619
+					$childTableNameAlias,
620
+					$tableName,
621
+					$fieldName
622
+				);
623
+				$statementParts['unions'][$childTableNameAlias] = $join;
624
+			}
625
+		} else {
626
+			throw new Exception('Could not determine type of relation.', 1252502725);
627
+		}
628
+
629
+		$statementParts['keywords']['distinct'] = 'DISTINCT';
630
+		$propertyPath = $explodedPropertyPath[1];
631
+		$tableName = $childTableName;
632
+	}
633
+
634
+	/**
635
+	 * Returns the SQL operator for the given JCR operator type.
636
+	 *
637
+	 * @param string $operator One of the JCR_OPERATOR_* constants
638
+	 * @return string an SQL operator
639
+	 * @throws Exception
640
+	 */
641
+	protected function resolveOperator($operator)
642
+	{
643
+		switch ($operator) {
644
+			case self::OPERATOR_EQUAL_TO_NULL:
645
+				$operator = 'IS';
646
+				break;
647
+			case self::OPERATOR_NOT_EQUAL_TO_NULL:
648
+				$operator = 'IS NOT';
649
+				break;
650
+			case QueryInterface::OPERATOR_IN:
651
+				$operator = 'IN';
652
+				break;
653
+			case QueryInterface::OPERATOR_EQUAL_TO:
654
+				$operator = '=';
655
+				break;
656
+			case QueryInterface::OPERATOR_NOT_EQUAL_TO:
657
+				$operator = '!=';
658
+				break;
659
+			case QueryInterface::OPERATOR_LESS_THAN:
660
+				$operator = '<';
661
+				break;
662
+			case QueryInterface::OPERATOR_LESS_THAN_OR_EQUAL_TO:
663
+				$operator = '<=';
664
+				break;
665
+			case QueryInterface::OPERATOR_GREATER_THAN:
666
+				$operator = '>';
667
+				break;
668
+			case QueryInterface::OPERATOR_GREATER_THAN_OR_EQUAL_TO:
669
+				$operator = '>=';
670
+				break;
671
+			case QueryInterface::OPERATOR_LIKE:
672
+				$operator = 'LIKE';
673
+				break;
674
+			default:
675
+				throw new Exception('Unsupported operator encountered.', 1242816073);
676
+		}
677
+		return $operator;
678
+	}
679
+
680
+	/**
681
+	 * Adds additional WHERE statements according to the query settings.
682
+	 *
683
+	 * @param QuerySettingsInterface $querySettings The TYPO3 CMS specific query settings
684
+	 * @param string $tableNameOrAlias The table name to add the additional where clause for
685
+	 * @param array &$statementParts
686
+	 * @return void
687
+	 */
688
+	protected function addAdditionalWhereClause(QuerySettingsInterface $querySettings, $tableNameOrAlias, &$statementParts)
689
+	{
690
+		$this->addVisibilityConstraintStatement($querySettings, $tableNameOrAlias, $statementParts);
691
+		if ($querySettings->getRespectSysLanguage()) {
692
+			$this->addSysLanguageStatement($tableNameOrAlias, $statementParts, $querySettings);
693
+		}
694
+	}
695
+
696
+	/**
697
+	 * Adds enableFields and deletedClause to the query if necessary
698
+	 *
699
+	 * @param QuerySettingsInterface $querySettings
700
+	 * @param string $tableNameOrAlias The database table name
701
+	 * @param array &$statementParts The query parts
702
+	 * @return void
703
+	 */
704
+	protected function addVisibilityConstraintStatement(QuerySettingsInterface $querySettings, $tableNameOrAlias, array &$statementParts)
705
+	{
706
+		$statement = '';
707
+		$tableName = $this->resolveTableNameAlias($tableNameOrAlias);
708
+		if (is_array($GLOBALS['TCA'][$tableName]['ctrl'])) {
709
+			$ignoreEnableFields = $querySettings->getIgnoreEnableFields();
710
+			$enableFieldsToBeIgnored = $querySettings->getEnableFieldsToBeIgnored();
711
+			$includeDeleted = $querySettings->getIncludeDeleted();
712
+			if (ApplicationType::fromRequest($GLOBALS['TYPO3_REQUEST'])->isFrontend()) {
713
+				$statement .= $this->getFrontendConstraintStatement($tableNameOrAlias, $ignoreEnableFields, $enableFieldsToBeIgnored, $includeDeleted);
714
+			} else {
715
+				// 'BE' case
716
+				$statement .= $this->getBackendConstraintStatement($tableNameOrAlias, $ignoreEnableFields, $includeDeleted);
717
+			}
718
+
719
+			// Remove the prefixing "AND" if any.
720
+			if (!empty($statement)) {
721
+				$statement = strtolower(substr($statement, 1, 3)) === 'and' ? substr($statement, 5) : $statement;
722
+				$statementParts['additionalWhereClause'][$tableNameOrAlias][] = $statement;
723
+			}
724
+		}
725
+	}
726
+
727
+	/**
728
+	 * Returns constraint statement for frontend context
729
+	 *
730
+	 * @param string $tableNameOrAlias
731
+	 * @param boolean $ignoreEnableFields A flag indicating whether the enable fields should be ignored
732
+	 * @param array $enableFieldsToBeIgnored If $ignoreEnableFields is true, this array specifies enable fields to be ignored. If it is null or an empty array (default) all enable fields are ignored.
733
+	 * @param boolean $includeDeleted A flag indicating whether deleted records should be included
734
+	 * @return string
735
+	 * @throws Exception\InconsistentQuerySettingsException
736
+	 */
737
+	protected function getFrontendConstraintStatement($tableNameOrAlias, $ignoreEnableFields, $enableFieldsToBeIgnored, $includeDeleted)
738
+	{
739
+		$statement = '';
740
+		$tableName = $this->resolveTableNameAlias($tableNameOrAlias);
741
+		if ($ignoreEnableFields && !$includeDeleted) {
742
+			if (count($enableFieldsToBeIgnored)) {
743
+				// array_combine() is necessary because of the way \TYPO3\CMS\Frontend\Page\PageRepository::enableFields() is implemented
744
+				$statement .= $this->getPageRepository()->enableFields($tableName, -1, array_combine($enableFieldsToBeIgnored, $enableFieldsToBeIgnored));
745
+			} else {
746
+				$statement .= $this->getPageRepository()->deleteClause($tableName);
747
+			}
748
+		} elseif (!$ignoreEnableFields && !$includeDeleted) {
749
+			$statement .= $this->getPageRepository()->enableFields($tableName);
750
+		} elseif (!$ignoreEnableFields && $includeDeleted) {
751
+			throw new InconsistentQuerySettingsException('Query setting "ignoreEnableFields=false" can not be used together with "includeDeleted=true" in frontend context.', 1327678173);
752
+		}
753
+		return $this->replaceTableNameByAlias($tableName, $tableNameOrAlias, $statement);
754
+	}
755
+
756
+	/**
757
+	 * Returns constraint statement for backend context
758
+	 *
759
+	 * @param string $tableNameOrAlias
760
+	 * @param boolean $ignoreEnableFields A flag indicating whether the enable fields should be ignored
761
+	 * @param boolean $includeDeleted A flag indicating whether deleted records should be included
762
+	 * @return string
763
+	 */
764
+	protected function getBackendConstraintStatement($tableNameOrAlias, $ignoreEnableFields, $includeDeleted)
765
+	{
766
+		$tableName = $this->resolveTableNameAlias($tableNameOrAlias);
767
+		$statement = '';
768
+		if (!$ignoreEnableFields) {
769
+			$statement .= BackendUtility::BEenableFields($tableName);
770
+		}
771
+
772
+		// If the table is found to have "workspace" support, add the corresponding fields in the statement.
773
+		if (Tca::table($tableName)->hasWorkspaceSupport()) {
774
+			if ($this->getBackendUser()->workspace === 0) {
775
+				$statement .= ' AND ' . $tableName . '.t3ver_state<=' . new VersionState(VersionState::DEFAULT_STATE);
776
+			} else {
777
+				// Show only records of live and of the current workspace
778
+				// In case we are in a Versioning preview
779
+				$statement .= ' AND (' .
780
+					$tableName . '.t3ver_wsid=0 OR ' .
781
+					$tableName . '.t3ver_wsid=' . (int)$this->getBackendUser()->workspace .
782
+					')';
783
+			}
784
+
785
+			// Check if this segment make sense here or whether it should be in the "if" part when we have workspace = 0
786
+			$statement .= ' AND ' . $tableName . '.pid<>-1';
787
+		}
788
+
789
+		if (!$includeDeleted) {
790
+			$statement .= BackendUtility::deleteClause($tableName);
791
+		}
792
+
793
+		return $this->replaceTableNameByAlias($tableName, $tableNameOrAlias, $statement);
794
+	}
795
+
796
+	/**
797
+	 * Builds the language field statement
798
+	 *
799
+	 * @param string $tableNameOrAlias The database table name
800
+	 * @param array &$statementParts The query parts
801
+	 * @param QuerySettingsInterface $querySettings The TYPO3 CMS specific query settings
802
+	 * @return void
803
+	 * @throws Exception
804
+	 */
805
+	protected function addSysLanguageStatement($tableNameOrAlias, array &$statementParts, $querySettings)
806
+	{
807
+		$tableName = $this->resolveTableNameAlias($tableNameOrAlias);
808
+		if (is_array($GLOBALS['TCA'][$tableName]['ctrl'])) {
809
+			if (!empty($GLOBALS['TCA'][$tableName]['ctrl']['languageField'])) {
810
+				// Select all entries for the current language
811
+				$additionalWhereClause = $tableNameOrAlias . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . ' IN (' . intval($querySettings->getLanguageUid()) . ',-1)';
812
+				// If any language is set -> get those entries which are not translated yet
813
+				// They will be removed by t3lib_page::getRecordOverlay if not matching overlay mode
814
+				if (isset($GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'])
815
+					&& $querySettings->getLanguageUid() > 0
816
+				) {
817
+					$additionalWhereClause .= ' OR (' . $tableNameOrAlias . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . '=0' .
818
+						' AND ' . $tableNameOrAlias . '.uid NOT IN (SELECT ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'] .
819
+						' FROM ' . $tableName .
820
+						' WHERE ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'] . '>0' .
821
+						' AND ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . '>0';
822
+
823
+					// Add delete clause to ensure all entries are loaded
824
+					if (isset($GLOBALS['TCA'][$tableName]['ctrl']['delete'])) {
825
+						$additionalWhereClause .= ' AND ' . $tableNameOrAlias . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['delete'] . '=0';
826
+					}
827
+					$additionalWhereClause .= '))';
828
+				}
829
+				$statementParts['additionalWhereClause'][$tableNameOrAlias][] = '(' . $additionalWhereClause . ')';
830
+			}
831
+		}
832
+	}
833
+
834
+	/**
835
+	 * Transforms orderings into SQL.
836
+	 *
837
+	 * @param array $orderings An array of orderings (Tx_Extbase_Persistence_QOM_Ordering)
838
+	 * @param SourceInterface $source The source
839
+	 * @param array &$statementParts The query parts
840
+	 * @return void
841
+	 * @throws Exception\UnsupportedOrderException
842
+	 */
843
+	protected function parseOrderings(array $orderings, SourceInterface $source, array &$statementParts)
844
+	{
845
+		foreach ($orderings as $fieldNameAndPath => $order) {
846
+			switch ($order) {
847
+				case QueryInterface::ORDER_ASCENDING:
848
+					$order = 'ASC';
849
+					break;
850
+				case QueryInterface::ORDER_DESCENDING:
851
+					$order = 'DESC';
852
+					break;
853
+				default:
854
+					throw new UnsupportedOrderException('Unsupported order encountered.', 1456845126);
855
+			}
856
+
857
+			$tableName = $this->getFieldPathResolver()->getDataType($fieldNameAndPath, $this->query->getType());
858
+			$fieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath, $tableName);
859
+			$statementParts['orderings'][] = sprintf('%s.%s %s', $tableName, $fieldName, $order);
860
+		}
861
+	}
862
+
863
+	/**
864
+	 * Transforms limit and offset into SQL
865
+	 *
866
+	 * @param int $limit
867
+	 * @param int $offset
868
+	 * @param array &$statementParts
869
+	 * @return void
870
+	 */
871
+	protected function parseLimitAndOffset($limit, $offset, array &$statementParts)
872
+	{
873
+		if ($limit !== null && $offset !== null) {
874
+			$statementParts['limit'] = intval($offset) . ', ' . intval($limit);
875
+		} elseif ($limit !== null) {
876
+			$statementParts['limit'] = intval($limit);
877
+		}
878
+	}
879
+
880
+	/**
881
+	 * @param array $rows
882
+	 * @return array
883
+	 */
884
+	protected function getContentObjects(array $rows): array
885
+	{
886
+		$contentObjects = [];
887
+		foreach ($rows as $row) {
888
+
889
+			// Get language uid from querySettings.
890
+			// Ensure the backend handling is not broken (fallback to Get parameter 'L' if needed)
891
+			$overlaidRow = $this->doLanguageAndWorkspaceOverlay(
892
+				$row,
893
+				$this->query->getTypo3QuerySettings()
894
+			);
895
+
896
+			$contentObjects[] = GeneralUtility::makeInstance(
897
+				Content::class,
898
+				$this->query->getType(),
899
+				$overlaidRow
900
+			);
901
+		}
902
+
903
+		return $contentObjects;
904
+	}
905
+
906
+	/**
907
+	 * Performs workspace and language overlay on the given row array. The language and workspace id is automatically
908
+	 * detected (depending on FE or BE context). You can also explicitly set the language/workspace id.
909
+	 *
910
+	 * @param array $row
911
+	 * @param QuerySettingsInterface $querySettings The TYPO3 CMS specific query settings
912
+	 * @return array
913
+	 */
914
+	protected function doLanguageAndWorkspaceOverlay(array $row, $querySettings)
915
+	{
916
+		$tableName = $this->getTableName();
917
+
918
+		$pageRepository = $this->getPageRepository();
919
+		if (is_object($GLOBALS['TSFE'])) {
920
+			$languageMode = GeneralUtility::makeInstance(Context::class)->getPropertyFromAspect('language', 'legacyLanguageMode');
921
+			#if ($this->isBackendUserLogged() && $this->getBackendUser()->workspace !== 0) {
922
+			#    $pageRepository->versioningWorkspaceId = $this->getBackendUser()->workspace;
923
+			#}
924
+		} else {
925
+			$languageMode = '';
926
+			$workspaceUid = $this->getBackendUser()->workspace;
927
+			#$pageRepository->versioningWorkspaceId = $workspaceUid;
928
+			#if ($this->getBackendUser()->workspace !== 0) {
929
+			#    $pageRepository->versioningPreview = 1;
930
+			#}
931
+		}
932
+
933
+		// If current row is a translation select its parent
934
+		if (isset($GLOBALS['TCA'][$tableName]['ctrl']['languageField'])
935
+			&& isset($GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'])
936
+		) {
937
+			if (isset($row[$GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField']])
938
+				&& $row[$GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField']] > 0
939
+			) {
940
+				$queryBuilder = $this->getQueryBuilder();
941
+				$row = $queryBuilder
942
+					->select($tableName . '.*')
943
+					->from($tableName)
944
+					->andWhere(
945
+						$tableName . '.uid=' . (int)$row[$GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField']],
946
+						$tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . ' = 0'
947
+					)
948
+					->execute()
949
+					->fetch();
950
+			}
951
+		}
952
+
953
+		// Retrieve the original uid; Used for Workspaces!
954
+		if (ApplicationType::fromRequest($GLOBALS['TYPO3_REQUEST'])->isBackend()) {
955
+			$pageRepository->versionOL($tableName, $row, true, true);
956
+		} else {
957
+			\TYPO3\CMS\Backend\Utility\BackendUtility::workspaceOL($tableName, $row);
958
+		}
959
+		if (isset($row['_ORIG_uid'])) {
960
+			$row['uid'] = $row['_ORIG_uid'];
961
+		}
962
+
963
+		// Special case for table "pages"
964
+		if ($tableName == 'pages') {
965
+			$row = $pageRepository->getPageOverlay($row, $querySettings->getLanguageUid());
966
+		} elseif (isset($GLOBALS['TCA'][$tableName]['ctrl']['languageField'])
967
+			&& $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] !== ''
968
+		) {
969
+			if (in_array($row[$GLOBALS['TCA'][$tableName]['ctrl']['languageField']], array(-1, 0))) {
970
+				$overlayMode = $languageMode === 'strict' ? 'hideNonTranslated' : '';
971
+				$row = $pageRepository->getRecordOverlay($tableName, $row, $querySettings->getLanguageUid(), $overlayMode);
972
+			}
973
+		}
974
+
975
+		return $row;
976
+	}
977
+
978
+	/**
979
+	 * Return a resolved table name given a possible table name alias.
980
+	 *
981
+	 * @param string $tableNameOrAlias
982
+	 * @return string
983
+	 */
984
+	protected function resolveTableNameAlias($tableNameOrAlias)
985
+	{
986
+		$resolvedTableName = $tableNameOrAlias;
987
+		if (!empty($this->tableNameAliases['aliases'][$tableNameOrAlias])) {
988
+			$resolvedTableName = $this->tableNameAliases['aliases'][$tableNameOrAlias];
989
+		}
990
+		return $resolvedTableName;
991
+	}
992
+
993
+	/**
994
+	 * Generate a unique table name alias for the given table name.
995
+	 *
996
+	 * @param string $tableName
997
+	 * @return string
998
+	 */
999
+	protected function generateAlias($tableName)
1000
+	{
1001
+
1002
+		if (!isset($this->tableNameAliases['aliasIncrement'][$tableName])) {
1003
+			$this->tableNameAliases['aliasIncrement'][$tableName] = 0;
1004
+		}
1005
+
1006
+		$numberOfAliases = $this->tableNameAliases['aliasIncrement'][$tableName];
1007
+		$tableNameAlias = $tableName . $numberOfAliases;
1008
+
1009
+		$this->tableNameAliases['aliasIncrement'][$tableName]++;
1010
+		$this->tableNameAliases['aliases'][$tableNameAlias] = $tableName;
1011
+
1012
+		return $tableNameAlias;
1013
+	}
1014
+
1015
+	/**
1016
+	 * Replace the table names by its table name alias within the given statement.
1017
+	 *
1018
+	 * @param string $tableName
1019
+	 * @param string $tableNameAlias
1020
+	 * @param string $statement
1021
+	 * @return string
1022
+	 */
1023
+	protected function replaceTableNameByAlias($tableName, $tableNameAlias, $statement)
1024
+	{
1025
+		if ($statement && $tableName !== $tableNameAlias) {
1026
+			$statement = str_replace($tableName, $tableNameAlias, $statement);
1027
+		}
1028
+		return $statement;
1029
+	}
1030
+
1031
+	/**
1032
+	 * Returns an instance of the current Backend User.
1033
+	 *
1034
+	 * @return BackendUserAuthentication
1035
+	 */
1036
+	protected function getBackendUser()
1037
+	{
1038
+		return $GLOBALS['BE_USER'];
1039
+	}
1040
+
1041
+	/**
1042
+	 * Tell whether a Backend User is logged in.
1043
+	 *
1044
+	 * @return bool
1045
+	 */
1046
+	protected function isBackendUserLogged()
1047
+	{
1048
+		return is_object($GLOBALS['BE_USER']);
1049
+	}
1050
+
1051
+	/**
1052
+	 * @return PageRepository|object
1053
+	 */
1054
+	protected function getPageRepository()
1055
+	{
1056
+		if (!$this->pageRepository instanceof PageRepository) {
1057
+			if (ApplicationType::fromRequest($GLOBALS['TYPO3_REQUEST'])->isFrontend() && is_object($GLOBALS['TSFE'])) {
1058
+				$this->pageRepository = $GLOBALS['TSFE']->sys_page;
1059
+			} else {
1060
+				$this->pageRepository = GeneralUtility::makeInstance(PageRepository::class);
1061
+			}
1062
+		}
1063
+
1064
+		return $this->pageRepository;
1065
+	}
1066
+
1067
+	/**
1068
+	 * @return FieldPathResolver|object
1069
+	 */
1070
+	protected function getFieldPathResolver()
1071
+	{
1072
+		return GeneralUtility::makeInstance(FieldPathResolver::class);
1073
+	}
1074
+
1075
+	/**
1076
+	 * @return object|Connection
1077
+	 */
1078
+	protected function getConnection(): Connection
1079
+	{
1080
+		/** @var ConnectionPool $connectionPool */
1081
+		return GeneralUtility::makeInstance(ConnectionPool::class)
1082
+			->getConnectionForTable($this->getTableName());
1083
+	}
1084
+
1085
+	/**
1086
+	 * @return object|QueryBuilder
1087
+	 */
1088
+	protected function getQueryBuilder(): QueryBuilder
1089
+	{
1090
+		/** @var ConnectionPool $connectionPool */
1091
+		$connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
1092
+		return $connectionPool->getQueryBuilderForTable($this->getTableName());
1093
+	}
1094
+
1095
+	/**
1096
+	 * @return string
1097
+	 */
1098
+	public function getTableName(): string
1099
+	{
1100
+		return $this->query->getSource()->getNodeTypeName(); // getSelectorName()
1101
+	}
1102 1102
 
1103 1103
 }
Please login to merge, or discard this patch.
Classes/Grid/ColumnRendererAbstract.php 2 patches
Indentation   +186 added lines, -186 removed lines patch added patch discarded remove patch
@@ -19,191 +19,191 @@
 block discarded – undo
19 19
 abstract class ColumnRendererAbstract implements ColumnRendererInterface
20 20
 {
21 21
 
22
-    /**
23
-     * The content object.
24
-     *
25
-     * @var Content
26
-     */
27
-    protected $object;
28
-
29
-    /**
30
-     * @var string
31
-     */
32
-    protected $fieldName;
33
-
34
-    /**
35
-     * @var int
36
-     */
37
-    protected $rowIndex;
38
-
39
-    /**
40
-     * @var array
41
-     */
42
-    protected $fieldConfiguration = [];
43
-
44
-    /**
45
-     * @var array
46
-     */
47
-    protected $gridRendererConfiguration = [];
48
-
49
-    /**
50
-     * @var array
51
-     */
52
-    protected $configuration = [];
53
-
54
-    /**
55
-     * Constructor of a Generic component in Vidi.
56
-     *
57
-     * @param array $configuration
58
-     * @param array $legacyParameterConfiguration
59
-     */
60
-    public function __construct($configuration = [], $legacyParameterConfiguration = array())
61
-    {
62
-        if (is_string($configuration)) {
63
-            $configuration = $legacyParameterConfiguration;
64
-            trigger_error('ColumnRendererAbstract: first parameter must now be an array. Please edit me in ' . get_class($this), E_USER_DEPRECATED);
65
-        }
66
-        $this->configuration = $configuration;
67
-    }
68
-
69
-    /**
70
-     * @return array
71
-     */
72
-    public function getConfiguration()
73
-    {
74
-        return $this->configuration;
75
-    }
76
-
77
-    /**
78
-     * @return Content
79
-     */
80
-    public function getObject()
81
-    {
82
-        return $this->object;
83
-    }
84
-
85
-    /**
86
-     * @param Content $object
87
-     * @return $this
88
-     */
89
-    public function setObject($object)
90
-    {
91
-        $this->object = $object;
92
-        return $this;
93
-    }
94
-
95
-    /**
96
-     * @return string
97
-     */
98
-    public function getFieldName()
99
-    {
100
-        return $this->fieldName;
101
-    }
102
-
103
-    /**
104
-     * @param string $fieldName
105
-     * @return $this
106
-     */
107
-    public function setFieldName($fieldName)
108
-    {
109
-        $this->fieldName = $fieldName;
110
-        return $this;
111
-    }
112
-
113
-    /**
114
-     * @return int
115
-     */
116
-    public function getRowIndex()
117
-    {
118
-        return $this->rowIndex;
119
-    }
120
-
121
-    /**
122
-     * @param int $rowIndex
123
-     * @return $this
124
-     */
125
-    public function setRowIndex($rowIndex)
126
-    {
127
-        $this->rowIndex = $rowIndex;
128
-        return $this;
129
-    }
130
-
131
-    /**
132
-     * @return array
133
-     */
134
-    public function getFieldConfiguration()
135
-    {
136
-        return $this->fieldConfiguration;
137
-    }
138
-
139
-    /**
140
-     * @param array $fieldConfiguration
141
-     * @return $this
142
-     */
143
-    public function setFieldConfiguration($fieldConfiguration)
144
-    {
145
-        $this->fieldConfiguration = $fieldConfiguration;
146
-        return $this;
147
-    }
148
-
149
-    /**
150
-     * @return array
151
-     */
152
-    public function getGridRendererConfiguration()
153
-    {
154
-        return $this->gridRendererConfiguration;
155
-    }
156
-
157
-    /**
158
-     * @param array $gridRendererConfiguration
159
-     * @return $this
160
-     */
161
-    public function setGridRendererConfiguration($gridRendererConfiguration)
162
-    {
163
-        $this->gridRendererConfiguration = $gridRendererConfiguration;
164
-        return $this;
165
-    }
166
-
167
-    /**
168
-     * Escapes special characters with their escaped counterparts as needed using PHPs htmlentities() function.
169
-     *
170
-     * @param string $value string to format
171
-     * @param bool $keepQuotes if TRUE, single and double quotes won't be replaced (sets ENT_NOQUOTES flag)
172
-     * @param string $encoding
173
-     * @return string
174
-     * @see http://www.php.net/manual/function.htmlentities.php
175
-     * @api
176
-     */
177
-    protected function secure($value , $keepQuotes = false, $encoding = 'UTF-8')
178
-    {
179
-        $flags = $keepQuotes ? ENT_NOQUOTES : ENT_COMPAT;
180
-        return htmlspecialchars($value, $flags, $encoding);
181
-    }
182
-
183
-    /**
184
-     * Get the Vidi Module Loader.
185
-     *
186
-     * @return object|ModuleLoader
187
-     */
188
-    protected function getModuleLoader()
189
-    {
190
-        return GeneralUtility::makeInstance(ModuleLoader::class);
191
-    }
192
-
193
-    /**
194
-     * @return object|IconFactory
195
-     */
196
-    protected function getIconFactory()
197
-    {
198
-        return GeneralUtility::makeInstance(IconFactory::class);
199
-    }
200
-
201
-    /**
202
-     * @return object|LanguageService
203
-     */
204
-    protected function getLanguageService()
205
-    {
206
-        return GeneralUtility::makeInstance(LanguageService::class);
207
-    }
22
+	/**
23
+	 * The content object.
24
+	 *
25
+	 * @var Content
26
+	 */
27
+	protected $object;
28
+
29
+	/**
30
+	 * @var string
31
+	 */
32
+	protected $fieldName;
33
+
34
+	/**
35
+	 * @var int
36
+	 */
37
+	protected $rowIndex;
38
+
39
+	/**
40
+	 * @var array
41
+	 */
42
+	protected $fieldConfiguration = [];
43
+
44
+	/**
45
+	 * @var array
46
+	 */
47
+	protected $gridRendererConfiguration = [];
48
+
49
+	/**
50
+	 * @var array
51
+	 */
52
+	protected $configuration = [];
53
+
54
+	/**
55
+	 * Constructor of a Generic component in Vidi.
56
+	 *
57
+	 * @param array $configuration
58
+	 * @param array $legacyParameterConfiguration
59
+	 */
60
+	public function __construct($configuration = [], $legacyParameterConfiguration = array())
61
+	{
62
+		if (is_string($configuration)) {
63
+			$configuration = $legacyParameterConfiguration;
64
+			trigger_error('ColumnRendererAbstract: first parameter must now be an array. Please edit me in ' . get_class($this), E_USER_DEPRECATED);
65
+		}
66
+		$this->configuration = $configuration;
67
+	}
68
+
69
+	/**
70
+	 * @return array
71
+	 */
72
+	public function getConfiguration()
73
+	{
74
+		return $this->configuration;
75
+	}
76
+
77
+	/**
78
+	 * @return Content
79
+	 */
80
+	public function getObject()
81
+	{
82
+		return $this->object;
83
+	}
84
+
85
+	/**
86
+	 * @param Content $object
87
+	 * @return $this
88
+	 */
89
+	public function setObject($object)
90
+	{
91
+		$this->object = $object;
92
+		return $this;
93
+	}
94
+
95
+	/**
96
+	 * @return string
97
+	 */
98
+	public function getFieldName()
99
+	{
100
+		return $this->fieldName;
101
+	}
102
+
103
+	/**
104
+	 * @param string $fieldName
105
+	 * @return $this
106
+	 */
107
+	public function setFieldName($fieldName)
108
+	{
109
+		$this->fieldName = $fieldName;
110
+		return $this;
111
+	}
112
+
113
+	/**
114
+	 * @return int
115
+	 */
116
+	public function getRowIndex()
117
+	{
118
+		return $this->rowIndex;
119
+	}
120
+
121
+	/**
122
+	 * @param int $rowIndex
123
+	 * @return $this
124
+	 */
125
+	public function setRowIndex($rowIndex)
126
+	{
127
+		$this->rowIndex = $rowIndex;
128
+		return $this;
129
+	}
130
+
131
+	/**
132
+	 * @return array
133
+	 */
134
+	public function getFieldConfiguration()
135
+	{
136
+		return $this->fieldConfiguration;
137
+	}
138
+
139
+	/**
140
+	 * @param array $fieldConfiguration
141
+	 * @return $this
142
+	 */
143
+	public function setFieldConfiguration($fieldConfiguration)
144
+	{
145
+		$this->fieldConfiguration = $fieldConfiguration;
146
+		return $this;
147
+	}
148
+
149
+	/**
150
+	 * @return array
151
+	 */
152
+	public function getGridRendererConfiguration()
153
+	{
154
+		return $this->gridRendererConfiguration;
155
+	}
156
+
157
+	/**
158
+	 * @param array $gridRendererConfiguration
159
+	 * @return $this
160
+	 */
161
+	public function setGridRendererConfiguration($gridRendererConfiguration)
162
+	{
163
+		$this->gridRendererConfiguration = $gridRendererConfiguration;
164
+		return $this;
165
+	}
166
+
167
+	/**
168
+	 * Escapes special characters with their escaped counterparts as needed using PHPs htmlentities() function.
169
+	 *
170
+	 * @param string $value string to format
171
+	 * @param bool $keepQuotes if TRUE, single and double quotes won't be replaced (sets ENT_NOQUOTES flag)
172
+	 * @param string $encoding
173
+	 * @return string
174
+	 * @see http://www.php.net/manual/function.htmlentities.php
175
+	 * @api
176
+	 */
177
+	protected function secure($value , $keepQuotes = false, $encoding = 'UTF-8')
178
+	{
179
+		$flags = $keepQuotes ? ENT_NOQUOTES : ENT_COMPAT;
180
+		return htmlspecialchars($value, $flags, $encoding);
181
+	}
182
+
183
+	/**
184
+	 * Get the Vidi Module Loader.
185
+	 *
186
+	 * @return object|ModuleLoader
187
+	 */
188
+	protected function getModuleLoader()
189
+	{
190
+		return GeneralUtility::makeInstance(ModuleLoader::class);
191
+	}
192
+
193
+	/**
194
+	 * @return object|IconFactory
195
+	 */
196
+	protected function getIconFactory()
197
+	{
198
+		return GeneralUtility::makeInstance(IconFactory::class);
199
+	}
200
+
201
+	/**
202
+	 * @return object|LanguageService
203
+	 */
204
+	protected function getLanguageService()
205
+	{
206
+		return GeneralUtility::makeInstance(LanguageService::class);
207
+	}
208 208
 
209 209
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -61,7 +61,7 @@  discard block
 block discarded – undo
61 61
     {
62 62
         if (is_string($configuration)) {
63 63
             $configuration = $legacyParameterConfiguration;
64
-            trigger_error('ColumnRendererAbstract: first parameter must now be an array. Please edit me in ' . get_class($this), E_USER_DEPRECATED);
64
+            trigger_error('ColumnRendererAbstract: first parameter must now be an array. Please edit me in '.get_class($this), E_USER_DEPRECATED);
65 65
         }
66 66
         $this->configuration = $configuration;
67 67
     }
@@ -174,7 +174,7 @@  discard block
 block discarded – undo
174 174
      * @see http://www.php.net/manual/function.htmlentities.php
175 175
      * @api
176 176
      */
177
-    protected function secure($value , $keepQuotes = false, $encoding = 'UTF-8')
177
+    protected function secure($value, $keepQuotes = false, $encoding = 'UTF-8')
178 178
     {
179 179
         $flags = $keepQuotes ? ENT_NOQUOTES : ENT_COMPAT;
180 180
         return htmlspecialchars($value, $flags, $encoding);
Please login to merge, or discard this patch.
Classes/Grid/VisibilityRenderer.php 2 patches
Indentation   +78 added lines, -78 removed lines patch added patch discarded remove patch
@@ -21,83 +21,83 @@
 block discarded – undo
21 21
 class VisibilityRenderer extends ColumnRendererAbstract
22 22
 {
23 23
 
24
-    /**
25
-     * Render visibility for the Grid.
26
-     *
27
-     * @return string
28
-     */
29
-    public function render()
30
-    {
31
-
32
-        $output = '';
33
-        $hiddenField = Tca::table()->getHiddenField();
34
-
35
-        if ($hiddenField) {
36
-
37
-            $spriteName = $this->object[$hiddenField] ? 'actions-edit-unhide' : 'actions-edit-hide';
38
-
39
-            $label = $this->object[$hiddenField] ? 'unHide' : 'hide';
40
-
41
-            $output = $this->makeLinkButton()
42
-                ->setHref($this->getEditUri($this->object))
43
-                ->setClasses('btn-visibility-toggle')
44
-                ->setDataAttributes([
45
-                    'toggle' => 'tooltip',
46
-                ])
47
-                ->setTitle($this->getLabelService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf:' . $label))
48
-                ->setIcon($this->getIconFactory()->getIcon($spriteName, Icon::SIZE_SMALL))
49
-                ->render();
50
-        }
51
-        return $output;
52
-    }
53
-
54
-    /**
55
-     * @param Content $object
56
-     * @return string
57
-     */
58
-    protected function getEditUri(Content $object)
59
-    {
60
-        $hiddenField = Tca::table()->getHiddenField();
61
-
62
-        $additionalParameters = array(
63
-            $this->getModuleLoader()->getParameterPrefix() => [
64
-                'controller' => 'Content',
65
-                'action' => 'update',
66
-                'format' => 'json',
67
-                'fieldNameAndPath' => Tca::table()->getHiddenField(),
68
-                'matches' => [
69
-                    'uid' => $object->getUid(),
70
-                ],
71
-                'content' => [$hiddenField => (int)!$this->object[$hiddenField]],
72
-            ],
73
-        );
74
-
75
-        return $this->getModuleLoader()->getModuleUrl($additionalParameters);
76
-    }
77
-
78
-    /**
79
-     * @return LinkButton
80
-     */
81
-    protected function makeLinkButton()
82
-    {
83
-        return GeneralUtility::makeInstance(LinkButton::class);
84
-    }
85
-
86
-
87
-    /**
88
-     * @return IconFactory
89
-     */
90
-    protected function getIconFactory()
91
-    {
92
-        return GeneralUtility::makeInstance(IconFactory::class);
93
-    }
94
-
95
-    /**
96
-     * @return LanguageService
97
-     */
98
-    protected function getLabelService()
99
-    {
100
-        return $GLOBALS['LANG'];
101
-    }
24
+	/**
25
+	 * Render visibility for the Grid.
26
+	 *
27
+	 * @return string
28
+	 */
29
+	public function render()
30
+	{
31
+
32
+		$output = '';
33
+		$hiddenField = Tca::table()->getHiddenField();
34
+
35
+		if ($hiddenField) {
36
+
37
+			$spriteName = $this->object[$hiddenField] ? 'actions-edit-unhide' : 'actions-edit-hide';
38
+
39
+			$label = $this->object[$hiddenField] ? 'unHide' : 'hide';
40
+
41
+			$output = $this->makeLinkButton()
42
+				->setHref($this->getEditUri($this->object))
43
+				->setClasses('btn-visibility-toggle')
44
+				->setDataAttributes([
45
+					'toggle' => 'tooltip',
46
+				])
47
+				->setTitle($this->getLabelService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf:' . $label))
48
+				->setIcon($this->getIconFactory()->getIcon($spriteName, Icon::SIZE_SMALL))
49
+				->render();
50
+		}
51
+		return $output;
52
+	}
53
+
54
+	/**
55
+	 * @param Content $object
56
+	 * @return string
57
+	 */
58
+	protected function getEditUri(Content $object)
59
+	{
60
+		$hiddenField = Tca::table()->getHiddenField();
61
+
62
+		$additionalParameters = array(
63
+			$this->getModuleLoader()->getParameterPrefix() => [
64
+				'controller' => 'Content',
65
+				'action' => 'update',
66
+				'format' => 'json',
67
+				'fieldNameAndPath' => Tca::table()->getHiddenField(),
68
+				'matches' => [
69
+					'uid' => $object->getUid(),
70
+				],
71
+				'content' => [$hiddenField => (int)!$this->object[$hiddenField]],
72
+			],
73
+		);
74
+
75
+		return $this->getModuleLoader()->getModuleUrl($additionalParameters);
76
+	}
77
+
78
+	/**
79
+	 * @return LinkButton
80
+	 */
81
+	protected function makeLinkButton()
82
+	{
83
+		return GeneralUtility::makeInstance(LinkButton::class);
84
+	}
85
+
86
+
87
+	/**
88
+	 * @return IconFactory
89
+	 */
90
+	protected function getIconFactory()
91
+	{
92
+		return GeneralUtility::makeInstance(IconFactory::class);
93
+	}
94
+
95
+	/**
96
+	 * @return LanguageService
97
+	 */
98
+	protected function getLabelService()
99
+	{
100
+		return $GLOBALS['LANG'];
101
+	}
102 102
 
103 103
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -44,7 +44,7 @@
 block discarded – undo
44 44
                 ->setDataAttributes([
45 45
                     'toggle' => 'tooltip',
46 46
                 ])
47
-                ->setTitle($this->getLabelService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf:' . $label))
47
+                ->setTitle($this->getLabelService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf:'.$label))
48 48
                 ->setIcon($this->getIconFactory()->getIcon($spriteName, Icon::SIZE_SMALL))
49 49
                 ->render();
50 50
         }
Please login to merge, or discard this patch.