Completed
Push — master ( 080764...892a3f )
by Fabien
52:24
created
Classes/Resolver/FieldPathResolver.php 1 patch
Indentation   +107 added lines, -107 removed lines patch added patch discarded remove patch
@@ -25,111 +25,111 @@
 block discarded – undo
25 25
 class FieldPathResolver implements SingletonInterface
26 26
 {
27 27
 
28
-    /**
29
-     * Remove the prefixing path from the file name.
30
-     *
31
-     * @param string $fieldNameAndPath
32
-     * @param string $dataType
33
-     * @return string
34
-     */
35
-    public function stripFieldPath($fieldNameAndPath, $dataType = '')
36
-    {
37
-
38
-        $dataType = $this->getContextualDataType($dataType);
39
-
40
-        if ($this->containsPath($fieldNameAndPath, $dataType)) {
41
-
42
-            // Corresponds to the field name of the foreign table.
43
-            $fieldParts = GeneralUtility::trimExplode('.', $fieldNameAndPath);
44
-            $fieldName = $fieldParts[1];
45
-        } else {
46
-            $fieldName = $fieldNameAndPath;
47
-        }
48
-        return $fieldName;
49
-    }
50
-
51
-    /**
52
-     * Remove the suffixing field name
53
-     *
54
-     * @param string $fieldNameAndPath
55
-     * @param string $dataType
56
-     * @return string
57
-     */
58
-    public function stripFieldName($fieldNameAndPath, $dataType = '')
59
-    {
60
-
61
-        $dataType = $this->getContextualDataType($dataType);
62
-
63
-        if ($this->containsPath($fieldNameAndPath, $dataType)) {
64
-
65
-            // Corresponds to the field name of the foreign table.
66
-            $fieldParts = GeneralUtility::trimExplode('.', $fieldNameAndPath);
67
-            $fieldName = $fieldParts[0];
68
-        } else {
69
-            $fieldName = $fieldNameAndPath;
70
-        }
71
-        return $fieldName;
72
-    }
73
-
74
-    /**
75
-     * Returns the class names to be applied to a cell ("td").
76
-     *
77
-     * @param string $fieldNameAndPath
78
-     * @param string $dataType
79
-     * @return string
80
-     */
81
-    public function getDataType($fieldNameAndPath, $dataType = '')
82
-    {
83
-
84
-        $dataType = $this->getContextualDataType($dataType);
85
-
86
-        if ($this->containsPath($fieldNameAndPath, $dataType)) {
87
-
88
-            // Compute the foreign data type.
89
-            $fieldParts = GeneralUtility::trimExplode('.', $fieldNameAndPath);
90
-            $fieldNameAndPath = $fieldParts[0];
91
-            $dataType = Tca::table($dataType)->field($fieldNameAndPath)->getForeignTable();
92
-        }
93
-        return $dataType;
94
-    }
95
-
96
-    /**
97
-     * Return the data type according to the context.
98
-     *
99
-     * @param $dataType
100
-     * @return string
101
-     */
102
-    public function getContextualDataType($dataType)
103
-    {
104
-
105
-        if (!$dataType) {
106
-            $dataType = $this->getModuleLoader()->getDataType();
107
-        }
108
-        return $dataType;
109
-    }
110
-
111
-    /**
112
-     * Tell whether the field name contains a path, e.g. metadata.title
113
-     * But resolves the case when the field is composite e.g "items.sys_file_metadata" and looks as field path but is not!
114
-     * A composite field = a field for a MM relation  of type "group" where the table name is appended.
115
-     *
116
-     * @param string $fieldNameAndPath
117
-     * @param string $dataType
118
-     * @return boolean
119
-     */
120
-    public function containsPath($fieldNameAndPath, $dataType)
121
-    {
122
-        $doesContainPath = strpos($fieldNameAndPath, '.') > 0 && !Tca::table($dataType)->hasField($fieldNameAndPath); // -> will make sure it is not a composite field name.
123
-        return $doesContainPath;
124
-    }
125
-
126
-    /**
127
-     * Get the Vidi Module Loader.
128
-     *
129
-     * @return ModuleLoader
130
-     */
131
-    protected function getModuleLoader()
132
-    {
133
-        return GeneralUtility::makeInstance(ModuleLoader::class);
134
-    }
28
+	/**
29
+	 * Remove the prefixing path from the file name.
30
+	 *
31
+	 * @param string $fieldNameAndPath
32
+	 * @param string $dataType
33
+	 * @return string
34
+	 */
35
+	public function stripFieldPath($fieldNameAndPath, $dataType = '')
36
+	{
37
+
38
+		$dataType = $this->getContextualDataType($dataType);
39
+
40
+		if ($this->containsPath($fieldNameAndPath, $dataType)) {
41
+
42
+			// Corresponds to the field name of the foreign table.
43
+			$fieldParts = GeneralUtility::trimExplode('.', $fieldNameAndPath);
44
+			$fieldName = $fieldParts[1];
45
+		} else {
46
+			$fieldName = $fieldNameAndPath;
47
+		}
48
+		return $fieldName;
49
+	}
50
+
51
+	/**
52
+	 * Remove the suffixing field name
53
+	 *
54
+	 * @param string $fieldNameAndPath
55
+	 * @param string $dataType
56
+	 * @return string
57
+	 */
58
+	public function stripFieldName($fieldNameAndPath, $dataType = '')
59
+	{
60
+
61
+		$dataType = $this->getContextualDataType($dataType);
62
+
63
+		if ($this->containsPath($fieldNameAndPath, $dataType)) {
64
+
65
+			// Corresponds to the field name of the foreign table.
66
+			$fieldParts = GeneralUtility::trimExplode('.', $fieldNameAndPath);
67
+			$fieldName = $fieldParts[0];
68
+		} else {
69
+			$fieldName = $fieldNameAndPath;
70
+		}
71
+		return $fieldName;
72
+	}
73
+
74
+	/**
75
+	 * Returns the class names to be applied to a cell ("td").
76
+	 *
77
+	 * @param string $fieldNameAndPath
78
+	 * @param string $dataType
79
+	 * @return string
80
+	 */
81
+	public function getDataType($fieldNameAndPath, $dataType = '')
82
+	{
83
+
84
+		$dataType = $this->getContextualDataType($dataType);
85
+
86
+		if ($this->containsPath($fieldNameAndPath, $dataType)) {
87
+
88
+			// Compute the foreign data type.
89
+			$fieldParts = GeneralUtility::trimExplode('.', $fieldNameAndPath);
90
+			$fieldNameAndPath = $fieldParts[0];
91
+			$dataType = Tca::table($dataType)->field($fieldNameAndPath)->getForeignTable();
92
+		}
93
+		return $dataType;
94
+	}
95
+
96
+	/**
97
+	 * Return the data type according to the context.
98
+	 *
99
+	 * @param $dataType
100
+	 * @return string
101
+	 */
102
+	public function getContextualDataType($dataType)
103
+	{
104
+
105
+		if (!$dataType) {
106
+			$dataType = $this->getModuleLoader()->getDataType();
107
+		}
108
+		return $dataType;
109
+	}
110
+
111
+	/**
112
+	 * Tell whether the field name contains a path, e.g. metadata.title
113
+	 * But resolves the case when the field is composite e.g "items.sys_file_metadata" and looks as field path but is not!
114
+	 * A composite field = a field for a MM relation  of type "group" where the table name is appended.
115
+	 *
116
+	 * @param string $fieldNameAndPath
117
+	 * @param string $dataType
118
+	 * @return boolean
119
+	 */
120
+	public function containsPath($fieldNameAndPath, $dataType)
121
+	{
122
+		$doesContainPath = strpos($fieldNameAndPath, '.') > 0 && !Tca::table($dataType)->hasField($fieldNameAndPath); // -> will make sure it is not a composite field name.
123
+		return $doesContainPath;
124
+	}
125
+
126
+	/**
127
+	 * Get the Vidi Module Loader.
128
+	 *
129
+	 * @return ModuleLoader
130
+	 */
131
+	protected function getModuleLoader()
132
+	{
133
+		return GeneralUtility::makeInstance(ModuleLoader::class);
134
+	}
135 135
 }
Please login to merge, or discard this patch.
Classes/Processor/MarkerProcessor.php 2 patches
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -105,7 +105,7 @@
 block discarded – undo
105 105
             $replace = $structure[2];
106 106
 
107 107
             // Perhaps needs to be improved here if $search contains "/" precisely.
108
-            $updateValue = preg_replace('/' . $search . '/isU', $replace, $currentValue);
108
+            $updateValue = preg_replace('/'.$search.'/isU', $replace, $currentValue);
109 109
         }
110 110
         return $updateValue;
111 111
     }
Please login to merge, or discard this patch.
Indentation   +109 added lines, -109 removed lines patch added patch discarded remove patch
@@ -20,114 +20,114 @@
 block discarded – undo
20 20
 class MarkerProcessor implements SingletonInterface
21 21
 {
22 22
 
23
-    /**
24
-     * @var array
25
-     */
26
-    protected $wellKnownMarkers = array(
27
-        '{*}',
28
-        '{counter}',
29
-        '{date}',
30
-        '{creation_date}'
31
-    );
32
-
33
-    /**
34
-     * @param ProcessContentDataSignalArguments $signalArguments
35
-     * @return array
36
-     */
37
-    public function processMarkers(ProcessContentDataSignalArguments $signalArguments)
38
-    {
39
-
40
-        $contentData = $signalArguments->getContentData();
41
-        $creationTime = $this->getCreationTime($signalArguments);
42
-
43
-        // Process markers
44
-        foreach ($signalArguments->getContentData() as $fieldName => $updateValue) {
45
-            if (is_scalar($updateValue)) {
46
-
47
-                $currentValue = $this->getContentObjectResolver()->getValue(
48
-                    $signalArguments->getContentObject(),
49
-                    $signalArguments->getFieldNameAndPath(),
50
-                    $fieldName,
51
-                    $signalArguments->getLanguage()
52
-                );
53
-                $counter = $signalArguments->getCounter();
54
-
55
-                $updateValue = $this->searchAndReplace($updateValue, $currentValue);
56
-                $updateValue = $this->replaceWellKnownMarkers($updateValue, $currentValue, $counter, $creationTime);
57
-
58
-                $contentData[$fieldName] = $updateValue;
59
-            }
60
-        }
61
-
62
-        $signalArguments->setContentData($contentData);
63
-        return array($signalArguments);
64
-    }
65
-
66
-    /**
67
-     * @param string $updateValue
68
-     * @param string $currentValue
69
-     * @param int $counter
70
-     * @param $creationTime
71
-     * @return string
72
-     */
73
-    protected function replaceWellKnownMarkers($updateValue, $currentValue, $counter, $creationTime)
74
-    {
75
-
76
-        // Replaces values.
77
-        $replaces = array(
78
-            $currentValue,
79
-            $counter,
80
-            date($GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy']),
81
-            date($GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'], $creationTime),
82
-        );
83
-
84
-        // Replace me!
85
-        return str_replace($this->wellKnownMarkers, $replaces, $updateValue);
86
-    }
87
-
88
-    /**
89
-     * @param string $updateValue
90
-     * @param string $currentValue
91
-     * @return string
92
-     */
93
-    protected function searchAndReplace($updateValue, $currentValue)
94
-    {
95
-
96
-        if (strpos($updateValue, 's/') !== false) {
97
-            $structure = explode('/', $updateValue);
98
-            $search = $structure[1];
99
-            $replace = $structure[2];
100
-
101
-            // Perhaps needs to be improved here if $search contains "/" precisely.
102
-            $updateValue = preg_replace('/' . $search . '/isU', $replace, $currentValue);
103
-        }
104
-        return $updateValue;
105
-    }
106
-
107
-    /**
108
-     * @param ProcessContentDataSignalArguments $signalArguments
109
-     * @return int
110
-     */
111
-    protected function getCreationTime(ProcessContentDataSignalArguments $signalArguments)
112
-    {
113
-        $creationTime = 0;
114
-        $creationTimeField = Tca::table($signalArguments->getContentObject()->getDataType())->getTimeCreationField();
115
-        if ($creationTimeField) {
116
-            $creationTime = $this->getContentObjectResolver()->getValue(
117
-                $signalArguments->getContentObject(),
118
-                $signalArguments->getFieldNameAndPath(),
119
-                $creationTimeField
120
-            );
121
-        }
122
-        return $creationTime;
123
-    }
124
-
125
-    /**
126
-     * @return ContentObjectResolver
127
-     */
128
-    protected function getContentObjectResolver()
129
-    {
130
-        return GeneralUtility::makeInstance(ContentObjectResolver::class);
131
-    }
23
+	/**
24
+	 * @var array
25
+	 */
26
+	protected $wellKnownMarkers = array(
27
+		'{*}',
28
+		'{counter}',
29
+		'{date}',
30
+		'{creation_date}'
31
+	);
32
+
33
+	/**
34
+	 * @param ProcessContentDataSignalArguments $signalArguments
35
+	 * @return array
36
+	 */
37
+	public function processMarkers(ProcessContentDataSignalArguments $signalArguments)
38
+	{
39
+
40
+		$contentData = $signalArguments->getContentData();
41
+		$creationTime = $this->getCreationTime($signalArguments);
42
+
43
+		// Process markers
44
+		foreach ($signalArguments->getContentData() as $fieldName => $updateValue) {
45
+			if (is_scalar($updateValue)) {
46
+
47
+				$currentValue = $this->getContentObjectResolver()->getValue(
48
+					$signalArguments->getContentObject(),
49
+					$signalArguments->getFieldNameAndPath(),
50
+					$fieldName,
51
+					$signalArguments->getLanguage()
52
+				);
53
+				$counter = $signalArguments->getCounter();
54
+
55
+				$updateValue = $this->searchAndReplace($updateValue, $currentValue);
56
+				$updateValue = $this->replaceWellKnownMarkers($updateValue, $currentValue, $counter, $creationTime);
57
+
58
+				$contentData[$fieldName] = $updateValue;
59
+			}
60
+		}
61
+
62
+		$signalArguments->setContentData($contentData);
63
+		return array($signalArguments);
64
+	}
65
+
66
+	/**
67
+	 * @param string $updateValue
68
+	 * @param string $currentValue
69
+	 * @param int $counter
70
+	 * @param $creationTime
71
+	 * @return string
72
+	 */
73
+	protected function replaceWellKnownMarkers($updateValue, $currentValue, $counter, $creationTime)
74
+	{
75
+
76
+		// Replaces values.
77
+		$replaces = array(
78
+			$currentValue,
79
+			$counter,
80
+			date($GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy']),
81
+			date($GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'], $creationTime),
82
+		);
83
+
84
+		// Replace me!
85
+		return str_replace($this->wellKnownMarkers, $replaces, $updateValue);
86
+	}
87
+
88
+	/**
89
+	 * @param string $updateValue
90
+	 * @param string $currentValue
91
+	 * @return string
92
+	 */
93
+	protected function searchAndReplace($updateValue, $currentValue)
94
+	{
95
+
96
+		if (strpos($updateValue, 's/') !== false) {
97
+			$structure = explode('/', $updateValue);
98
+			$search = $structure[1];
99
+			$replace = $structure[2];
100
+
101
+			// Perhaps needs to be improved here if $search contains "/" precisely.
102
+			$updateValue = preg_replace('/' . $search . '/isU', $replace, $currentValue);
103
+		}
104
+		return $updateValue;
105
+	}
106
+
107
+	/**
108
+	 * @param ProcessContentDataSignalArguments $signalArguments
109
+	 * @return int
110
+	 */
111
+	protected function getCreationTime(ProcessContentDataSignalArguments $signalArguments)
112
+	{
113
+		$creationTime = 0;
114
+		$creationTimeField = Tca::table($signalArguments->getContentObject()->getDataType())->getTimeCreationField();
115
+		if ($creationTimeField) {
116
+			$creationTime = $this->getContentObjectResolver()->getValue(
117
+				$signalArguments->getContentObject(),
118
+				$signalArguments->getFieldNameAndPath(),
119
+				$creationTimeField
120
+			);
121
+		}
122
+		return $creationTime;
123
+	}
124
+
125
+	/**
126
+	 * @return ContentObjectResolver
127
+	 */
128
+	protected function getContentObjectResolver()
129
+	{
130
+		return GeneralUtility::makeInstance(ContentObjectResolver::class);
131
+	}
132 132
 
133 133
 }
Please login to merge, or discard this patch.
Classes/Processor/ContentObjectProcessor.php 2 patches
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -71,7 +71,7 @@
 block discarded – undo
71 71
                 $relatedValues = $this->getRelatedValues($object, $fieldNameAndPath, $fieldName);
72 72
 
73 73
                 foreach ($values as $value) {
74
-                    $appendOrRemove = $savingBehavior . 'Relations';
74
+                    $appendOrRemove = $savingBehavior.'Relations';
75 75
                     $relatedValues = $this->$appendOrRemove($value, $relatedValues);
76 76
                 }
77 77
 
Please login to merge, or discard this patch.
Indentation   +117 added lines, -117 removed lines patch added patch discarded remove patch
@@ -23,121 +23,121 @@
 block discarded – undo
23 23
 class ContentObjectProcessor implements SingletonInterface
24 24
 {
25 25
 
26
-    /**
27
-     * @param ProcessContentDataSignalArguments $signalArguments
28
-     * @return array
29
-     */
30
-    public function processRelations(ProcessContentDataSignalArguments $signalArguments)
31
-    {
32
-
33
-        $contentObject = $signalArguments->getContentObject();
34
-        $fieldNameAndPath = $signalArguments->getFieldNameAndPath();
35
-        $contentData = $signalArguments->getContentData();
36
-        $savingBehavior = $signalArguments->getSavingBehavior();
37
-
38
-        if ($savingBehavior !== SavingBehavior::REPLACE) {
39
-            $contentData = $this->appendOrRemoveRelations($contentObject, $fieldNameAndPath, $contentData, $savingBehavior);
40
-            $signalArguments->setContentData($contentData);
41
-        }
42
-
43
-        return array($signalArguments);
44
-    }
45
-
46
-    /**
47
-     * @param Content $object
48
-     * @param $fieldNameAndPath
49
-     * @param array $contentData
50
-     * @param string $savingBehavior
51
-     * @return array
52
-     */
53
-    protected function appendOrRemoveRelations(Content $object, $fieldNameAndPath, array $contentData, $savingBehavior)
54
-    {
55
-
56
-        foreach ($contentData as $fieldName => $values) {
57
-
58
-            $resolvedObject = $this->getContentObjectResolver()->getObject($object, $fieldNameAndPath);
59
-
60
-            if (Tca::table($resolvedObject)->field($fieldName)->hasMany()) {
61
-
62
-                // true means CSV values must be converted to array.
63
-                if (!is_array($values)) {
64
-                    $values = GeneralUtility::trimExplode(',', $values);
65
-                }
66
-                $relatedValues = $this->getRelatedValues($object, $fieldNameAndPath, $fieldName);
67
-
68
-                foreach ($values as $value) {
69
-                    $appendOrRemove = $savingBehavior . 'Relations';
70
-                    $relatedValues = $this->$appendOrRemove($value, $relatedValues);
71
-                }
72
-
73
-                $contentData[$fieldName] = $relatedValues;
74
-            }
75
-        }
76
-        return $contentData;
77
-    }
78
-
79
-    /**
80
-     * @param $value
81
-     * @param array $relatedValues
82
-     * @return array
83
-     */
84
-    protected function appendRelations($value, array $relatedValues)
85
-    {
86
-        if (!in_array($value, $relatedValues)) {
87
-            $relatedValues[] = $value;
88
-        }
89
-        return $relatedValues;
90
-    }
91
-
92
-    /**
93
-     * @param $value
94
-     * @param array $relatedValues
95
-     * @return array
96
-     */
97
-    protected function removeRelations($value, array $relatedValues)
98
-    {
99
-        if (in_array($value, $relatedValues)) {
100
-            $key = array_search($value, $relatedValues);
101
-            unset($relatedValues[$key]);
102
-        }
103
-        return $relatedValues;
104
-    }
105
-
106
-    /**
107
-     * @param Content $object
108
-     * @param string $fieldNameAndPath
109
-     * @param string $fieldName
110
-     * @return array
111
-     */
112
-    protected function getRelatedValues(Content $object, $fieldNameAndPath, $fieldName)
113
-    {
114
-
115
-        $values = [];
116
-        $relatedContentObjects = $this->getContentObjectResolver()->getValue($object, $fieldNameAndPath, $fieldName);
117
-
118
-        if (is_array($relatedContentObjects)) {
119
-            /** @var Content $relatedContentObject */
120
-            foreach ($relatedContentObjects as $relatedContentObject) {
121
-                $values[] = $relatedContentObject->getUid();
122
-            }
123
-        }
124
-
125
-        return $values;
126
-    }
127
-
128
-    /**
129
-     * @return ContentObjectResolver|object
130
-     */
131
-    protected function getContentObjectResolver()
132
-    {
133
-        return GeneralUtility::makeInstance(ContentObjectResolver::class);
134
-    }
135
-
136
-    /**
137
-     * @return FieldPathResolver|object
138
-     */
139
-    protected function getFieldPathResolver()
140
-    {
141
-        return GeneralUtility::makeInstance(FieldPathResolver::class);
142
-    }
26
+	/**
27
+	 * @param ProcessContentDataSignalArguments $signalArguments
28
+	 * @return array
29
+	 */
30
+	public function processRelations(ProcessContentDataSignalArguments $signalArguments)
31
+	{
32
+
33
+		$contentObject = $signalArguments->getContentObject();
34
+		$fieldNameAndPath = $signalArguments->getFieldNameAndPath();
35
+		$contentData = $signalArguments->getContentData();
36
+		$savingBehavior = $signalArguments->getSavingBehavior();
37
+
38
+		if ($savingBehavior !== SavingBehavior::REPLACE) {
39
+			$contentData = $this->appendOrRemoveRelations($contentObject, $fieldNameAndPath, $contentData, $savingBehavior);
40
+			$signalArguments->setContentData($contentData);
41
+		}
42
+
43
+		return array($signalArguments);
44
+	}
45
+
46
+	/**
47
+	 * @param Content $object
48
+	 * @param $fieldNameAndPath
49
+	 * @param array $contentData
50
+	 * @param string $savingBehavior
51
+	 * @return array
52
+	 */
53
+	protected function appendOrRemoveRelations(Content $object, $fieldNameAndPath, array $contentData, $savingBehavior)
54
+	{
55
+
56
+		foreach ($contentData as $fieldName => $values) {
57
+
58
+			$resolvedObject = $this->getContentObjectResolver()->getObject($object, $fieldNameAndPath);
59
+
60
+			if (Tca::table($resolvedObject)->field($fieldName)->hasMany()) {
61
+
62
+				// true means CSV values must be converted to array.
63
+				if (!is_array($values)) {
64
+					$values = GeneralUtility::trimExplode(',', $values);
65
+				}
66
+				$relatedValues = $this->getRelatedValues($object, $fieldNameAndPath, $fieldName);
67
+
68
+				foreach ($values as $value) {
69
+					$appendOrRemove = $savingBehavior . 'Relations';
70
+					$relatedValues = $this->$appendOrRemove($value, $relatedValues);
71
+				}
72
+
73
+				$contentData[$fieldName] = $relatedValues;
74
+			}
75
+		}
76
+		return $contentData;
77
+	}
78
+
79
+	/**
80
+	 * @param $value
81
+	 * @param array $relatedValues
82
+	 * @return array
83
+	 */
84
+	protected function appendRelations($value, array $relatedValues)
85
+	{
86
+		if (!in_array($value, $relatedValues)) {
87
+			$relatedValues[] = $value;
88
+		}
89
+		return $relatedValues;
90
+	}
91
+
92
+	/**
93
+	 * @param $value
94
+	 * @param array $relatedValues
95
+	 * @return array
96
+	 */
97
+	protected function removeRelations($value, array $relatedValues)
98
+	{
99
+		if (in_array($value, $relatedValues)) {
100
+			$key = array_search($value, $relatedValues);
101
+			unset($relatedValues[$key]);
102
+		}
103
+		return $relatedValues;
104
+	}
105
+
106
+	/**
107
+	 * @param Content $object
108
+	 * @param string $fieldNameAndPath
109
+	 * @param string $fieldName
110
+	 * @return array
111
+	 */
112
+	protected function getRelatedValues(Content $object, $fieldNameAndPath, $fieldName)
113
+	{
114
+
115
+		$values = [];
116
+		$relatedContentObjects = $this->getContentObjectResolver()->getValue($object, $fieldNameAndPath, $fieldName);
117
+
118
+		if (is_array($relatedContentObjects)) {
119
+			/** @var Content $relatedContentObject */
120
+			foreach ($relatedContentObjects as $relatedContentObject) {
121
+				$values[] = $relatedContentObject->getUid();
122
+			}
123
+		}
124
+
125
+		return $values;
126
+	}
127
+
128
+	/**
129
+	 * @return ContentObjectResolver|object
130
+	 */
131
+	protected function getContentObjectResolver()
132
+	{
133
+		return GeneralUtility::makeInstance(ContentObjectResolver::class);
134
+	}
135
+
136
+	/**
137
+	 * @return FieldPathResolver|object
138
+	 */
139
+	protected function getFieldPathResolver()
140
+	{
141
+		return GeneralUtility::makeInstance(FieldPathResolver::class);
142
+	}
143 143
 }
Please login to merge, or discard this patch.
Classes/Domain/Validator/LanguageValidator.php 2 patches
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -33,7 +33,7 @@
 block discarded – undo
33 33
     {
34 34
 
35 35
         if (!$this->getLanguageService()->languageExists((int)$language)) {
36
-            throw new \Exception('The language "' . $language . '" does not exist', 1351605542);
36
+            throw new \Exception('The language "'.$language.'" does not exist', 1351605542);
37 37
         }
38 38
     }
39 39
 
Please login to merge, or discard this patch.
Indentation   +20 added lines, -20 removed lines patch added patch discarded remove patch
@@ -16,27 +16,27 @@
 block discarded – undo
16 16
 class LanguageValidator
17 17
 {
18 18
 
19
-    /**
20
-     * Check whether the $language is valid.
21
-     *
22
-     * @param int $language
23
-     * @throws \Exception
24
-     * @return void
25
-     */
26
-    public function validate($language)
27
-    {
19
+	/**
20
+	 * Check whether the $language is valid.
21
+	 *
22
+	 * @param int $language
23
+	 * @throws \Exception
24
+	 * @return void
25
+	 */
26
+	public function validate($language)
27
+	{
28 28
 
29
-        if (!$this->getLanguageService()->languageExists((int)$language)) {
30
-            throw new \Exception('The language "' . $language . '" does not exist', 1351605542);
31
-        }
32
-    }
29
+		if (!$this->getLanguageService()->languageExists((int)$language)) {
30
+			throw new \Exception('The language "' . $language . '" does not exist', 1351605542);
31
+		}
32
+	}
33 33
 
34
-    /**
35
-     * @return LanguageService|object
36
-     */
37
-    protected function getLanguageService()
38
-    {
39
-        return GeneralUtility::makeInstance(LanguageService::class);
40
-    }
34
+	/**
35
+	 * @return LanguageService|object
36
+	 */
37
+	protected function getLanguageService()
38
+	{
39
+		return GeneralUtility::makeInstance(LanguageService::class);
40
+	}
41 41
 
42 42
 }
Please login to merge, or discard this patch.
Classes/Domain/Repository/ContentRepository.php 2 patches
Spacing   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -211,7 +211,7 @@  discard block
 block discarded – undo
211 211
             foreach ($order->getOrderings() as $ordering => $direction) {
212 212
                 if ($this->hasForeignRelationIn($ordering)) {
213 213
                     $relationalField = $this->getForeignRelationFrom($ordering);
214
-                    $matcher->like($relationalField . '.uid', '');
214
+                    $matcher->like($relationalField.'.uid', '');
215 215
                 }
216 216
             }
217 217
         }
@@ -446,16 +446,16 @@  discard block
 block discarded – undo
446 446
     public function __call($methodName, $arguments)
447 447
     {
448 448
         if (substr($methodName, 0, 6) === 'findBy' && strlen($methodName) > 7) {
449
-            $propertyName = strtolower(substr(substr($methodName, 6), 0, 1)) . substr(substr($methodName, 6), 1);
449
+            $propertyName = strtolower(substr(substr($methodName, 6), 0, 1)).substr(substr($methodName, 6), 1);
450 450
             $result = $this->processMagicCall($propertyName, $arguments[0]);
451 451
         } elseif (substr($methodName, 0, 9) === 'findOneBy' && strlen($methodName) > 10) {
452
-            $propertyName = strtolower(substr(substr($methodName, 9), 0, 1)) . substr(substr($methodName, 9), 1);
452
+            $propertyName = strtolower(substr(substr($methodName, 9), 0, 1)).substr(substr($methodName, 9), 1);
453 453
             $result = $this->processMagicCall($propertyName, $arguments[0], 'one');
454 454
         } elseif (substr($methodName, 0, 7) === 'countBy' && strlen($methodName) > 8) {
455
-            $propertyName = strtolower(substr(substr($methodName, 7), 0, 1)) . substr(substr($methodName, 7), 1);
455
+            $propertyName = strtolower(substr(substr($methodName, 7), 0, 1)).substr(substr($methodName, 7), 1);
456 456
             $result = $this->processMagicCall($propertyName, $arguments[0], 'count');
457 457
         } else {
458
-            throw new UnsupportedMethodException('The method "' . $methodName . '" is not supported by the repository.', 1360838010);
458
+            throw new UnsupportedMethodException('The method "'.$methodName.'" is not supported by the repository.', 1360838010);
459 459
         }
460 460
         return $result;
461 461
     }
@@ -640,7 +640,7 @@  discard block
 block discarded – undo
640 640
 
641 641
                     if (Tca::table($dataType)->hasField($fieldName) && Tca::table($dataType)->field($fieldName)->hasRelation()) {
642 642
                         $foreignTable = Tca::table($dataType)->field($fieldName)->getForeignTable();
643
-                        $fieldNameAndPath = $fieldNameAndPath . '.' . Tca::table($foreignTable)->getLabelField();
643
+                        $fieldNameAndPath = $fieldNameAndPath.'.'.Tca::table($foreignTable)->getLabelField();
644 644
                     }
645 645
                     $constraints[] = $query->like($fieldNameAndPath, $likeClause);
646 646
                 }
@@ -712,17 +712,17 @@  discard block
 block discarded – undo
712 712
 
713 713
                 if (Tca::table($dataType)->field($fieldName)->hasRelation()) {
714 714
                     if (MathUtility::canBeInterpretedAsInteger($operand)) {
715
-                        $fieldNameAndPath = $fieldName . '.uid';
715
+                        $fieldNameAndPath = $fieldName.'.uid';
716 716
                     } else {
717 717
                         $foreignTableName = Tca::table($dataType)->field($fieldName)->getForeignTable();
718 718
                         $foreignTable = Tca::table($foreignTableName);
719
-                        $fieldNameAndPath = $fieldName . '.' . $foreignTable->getLabelField();
719
+                        $fieldNameAndPath = $fieldName.'.'.$foreignTable->getLabelField();
720 720
                     }
721 721
 
722 722
                     // If different means we should restore the prepended path segment for proper SQL parser.
723 723
                     // This is true for a composite field, e.g items.sys_file_metadata for categories.
724 724
                     if ($fieldName !== $fieldPath) {
725
-                        $fieldNameAndPath = $fieldPath . '.' . $fieldNameAndPath;
725
+                        $fieldNameAndPath = $fieldPath.'.'.$fieldNameAndPath;
726 726
                     }
727 727
                 }
728 728
 
@@ -768,7 +768,7 @@  discard block
 block discarded – undo
768 768
         if ($table->field($fieldName)->isGroup()) {
769 769
 
770 770
             $valueParts = explode('.', $value, 2);
771
-            $fieldName = $fieldName . '.' . $valueParts[0];
771
+            $fieldName = $fieldName.'.'.$valueParts[0];
772 772
             $value = $valueParts[1];
773 773
         }
774 774
 
Please login to merge, or discard this patch.
Indentation   +853 added lines, -853 removed lines patch added patch discarded remove patch
@@ -39,858 +39,858 @@
 block discarded – undo
39 39
 class ContentRepository implements RepositoryInterface
40 40
 {
41 41
 
42
-    /**
43
-     * Tell whether it is a raw result (array) or object being returned.
44
-     *
45
-     * @var bool
46
-     */
47
-    protected $rawResult = false;
48
-
49
-    /**
50
-     * The data type to be returned, e.g fe_users, fe_groups, tt_content, etc...
51
-     *
52
-     * @var string
53
-     */
54
-    protected $dataType;
55
-
56
-    /**
57
-     * The source field is useful in the context of MM relations to know who is the caller
58
-     * e.g findByItems which eventually corresponds to a field name.
59
-     *
60
-     * @var string
61
-     */
62
-    protected $sourceFieldName = '';
63
-
64
-    /**
65
-     * @var array
66
-     */
67
-    protected $errorMessages = [];
68
-
69
-    /**
70
-     * @var QuerySettingsInterface
71
-     */
72
-    protected $defaultQuerySettings;
73
-
74
-    /**
75
-     * @var DataHandler
76
-     */
77
-    protected $dataHandler;
78
-
79
-    /**
80
-     * Constructor
81
-     *
82
-     * @param string $dataType
83
-     */
84
-    public function __construct($dataType)
85
-    {
86
-        $this->dataType = $dataType;
87
-    }
88
-
89
-    /**
90
-     * Returns all objects of this repository.
91
-     *
92
-     * @return Content[]
93
-     */
94
-    public function findAll()
95
-    {
96
-        $query = $this->createQuery();
97
-        return $query->execute();
98
-    }
99
-
100
-    /**
101
-     * Returns all "distinct" values for a given property.
102
-     *
103
-     * @param string $propertyName
104
-     * @param Matcher $matcher
105
-     * @param Order|null $order
106
-     * @return Content[]
107
-     */
108
-    public function findDistinctValues($propertyName, Matcher $matcher = null, Order $order = null): array
109
-    {
110
-        $query = $this->createQuery();
111
-        $query->setDistinct($propertyName);
112
-
113
-        // Remove empty values from selection.
114
-        $constraint = $query->logicalNot($query->equals($propertyName, ''));
115
-
116
-        // Add some additional constraints from the Matcher object.
117
-        $matcherConstraint = null;
118
-        if ($matcher !== null) {
119
-            $matcherConstraint = $this->computeConstraints($query, $matcher);
120
-        }
121
-
122
-        // Assemble the final constraints or not.
123
-        if ($matcherConstraint) {
124
-            $query->logicalAnd($matcherConstraint, $constraint);
125
-            $query->matching($query->logicalAnd($matcherConstraint, $constraint));
126
-        } else {
127
-            $query->matching($constraint);
128
-        }
129
-
130
-        if ($order) {
131
-            $query->setOrderings($order->getOrderings());
132
-        }
133
-
134
-        return $query->execute();
135
-    }
136
-
137
-    /**
138
-     * Returns all "distinct" values for a given property.
139
-     *
140
-     * @param string $propertyName
141
-     * @param Matcher $matcher
142
-     * @return int
143
-     */
144
-    public function countDistinctValues($propertyName, Matcher $matcher = null): int
145
-    {
146
-        $query = $this->createQuery();
147
-        $query->setDistinct($propertyName);
148
-
149
-        // Remove empty values from selection.
150
-        $constraint = $query->logicalNot($query->equals($propertyName, ''));
151
-
152
-        // Add some additional constraints from the Matcher object.
153
-        $matcherConstraint = null;
154
-        if (!is_null($matcher)) {
155
-            $matcherConstraint = $this->computeConstraints($query, $matcher);
156
-        }
157
-
158
-        // Assemble the final constraints or not.
159
-        if ($matcherConstraint) {
160
-            $query->logicalAnd($matcherConstraint, $constraint);
161
-            $query->matching($query->logicalAnd($matcherConstraint, $constraint));
162
-        } else {
163
-            $query->matching($constraint);
164
-        }
165
-
166
-        return $query->count();
167
-    }
168
-
169
-    /**
170
-     * Finds an object matching the given identifier.
171
-     *
172
-     * @param int $uid The identifier of the object to find
173
-     * @return Content|null
174
-     * @api
175
-     */
176
-    public function findByUid($uid)
177
-    {
178
-        return $this->findByIdentifier($uid);
179
-    }
180
-
181
-    /**
182
-     * Finds all Contents given specified matches.
183
-     *
184
-     * @param string $propertyName
185
-     * @param array $values
186
-     * @return Content[]
187
-     */
188
-    public function findIn($propertyName, array $values): array
189
-    {
190
-        $query = $this->createQuery();
191
-        $query->matching($query->in($propertyName, $values));
192
-        return $query->execute();
193
-    }
194
-
195
-    /**
196
-     * Finds all Contents given specified matches.
197
-     *
198
-     * @param Matcher $matcher
199
-     * @param Order $order The order
200
-     * @param int $limit
201
-     * @param int $offset
202
-     * @return Content[]
203
-     */
204
-    public function findBy(Matcher $matcher, Order $order = null, $limit = null, $offset = null): array
205
-    {
206
-
207
-        $query = $this->createQuery();
208
-
209
-        $limit = (int)$limit; // make sure to cast
210
-        if ($limit > 0) {
211
-            $query->setLimit($limit);
212
-        }
213
-
214
-        if ($order) {
215
-            $query->setOrderings($order->getOrderings());
216
-
217
-            // Loops around the orderings adding if necessary a dummy condition
218
-            // to make sure the relations can be resolved when transforming the query to plain SQL.
219
-            foreach ($order->getOrderings() as $ordering => $direction) {
220
-                if ($this->hasForeignRelationIn($ordering)) {
221
-                    $relationalField = $this->getForeignRelationFrom($ordering);
222
-                    $matcher->like($relationalField . '.uid', '');
223
-                }
224
-            }
225
-        }
226
-
227
-        if ($offset) {
228
-            $query->setOffset($offset);
229
-        }
230
-
231
-        $constraints = $this->computeConstraints($query, $matcher);
232
-
233
-        if ($constraints) {
234
-            $query->matching($constraints);
235
-        }
236
-
237
-        return $query->execute();
238
-    }
239
-
240
-    /**
241
-     * Find one Content object given specified matches.
242
-     *
243
-     * @param Matcher $matcher
244
-     * @return Content
245
-     */
246
-    public function findOneBy(Matcher $matcher): Content
247
-    {
248
-
249
-        $query = $this->createQuery();
250
-
251
-        $constraints = $this->computeConstraints($query, $matcher);
252
-
253
-        if ($constraints) {
254
-            $query->matching($constraints);
255
-        }
256
-
257
-        $query->setLimit(1); // only take one!
258
-
259
-        $resultSet = $query->execute();
260
-        if ($resultSet) {
261
-            $resultSet = current($resultSet);
262
-        }
263
-        return $resultSet;
264
-    }
265
-
266
-    /**
267
-     * Count all Contents given specified matches.
268
-     *
269
-     * @param Matcher $matcher
270
-     * @return int
271
-     */
272
-    public function countBy(Matcher $matcher): int
273
-    {
274
-
275
-        $query = $this->createQuery();
276
-
277
-        $constraints = $this->computeConstraints($query, $matcher);
278
-
279
-        if ($constraints) {
280
-            $query->matching($constraints);
281
-        }
282
-
283
-        return $query->count();
284
-    }
285
-
286
-    /**
287
-     * Update a content with new information.
288
-     *
289
-     * @param Content $content
290
-     * @param $language
291
-     * @return bool
292
-     */
293
-    public function localize($content, $language): bool
294
-    {
295
-
296
-        // Security check
297
-        $this->getContentValidator()->validate($content);
298
-        $this->getLanguageValidator()->validate($language);
299
-
300
-        $dataType = $content->getDataType();
301
-        $handler = $this->getDataHandlerFactory()->action(ProcessAction::LOCALIZE)->forType($dataType)->getDataHandler();
302
-
303
-        $handlerResult = $handler->processLocalize($content, $language);
304
-        $this->errorMessages = $handler->getErrorMessages();
305
-        return $handlerResult;
306
-    }
307
-
308
-    /**
309
-     * Update a content with new information.
310
-     *
311
-     * @param Content $content
312
-     * @return bool
313
-     */
314
-    public function update($content)
315
-    {
316
-
317
-        // Security check.
318
-        $this->getContentValidator()->validate($content);
319
-
320
-        $dataType = $content->getDataType();
321
-        $handler = $this->getDataHandlerFactory()->action(ProcessAction::UPDATE)->forType($dataType)->getDataHandler();
322
-
323
-        $handlerResult = $handler->processUpdate($content);
324
-        $this->errorMessages = $handler->getErrorMessages();
325
-        return $handlerResult;
326
-    }
327
-
328
-    /**
329
-     * Removes an object from this repository.
330
-     *
331
-     * @param Content $content
332
-     * @return boolean
333
-     */
334
-    public function remove($content)
335
-    {
336
-        $dataType = $content->getDataType();
337
-        $handler = $this->getDataHandlerFactory()->action(ProcessAction::REMOVE)->forType($dataType)->getDataHandler();
338
-
339
-        $handlerResult = $handler->processRemove($content);
340
-        $this->errorMessages = $handler->getErrorMessages();
341
-        return $handlerResult;
342
-    }
343
-
344
-    /**
345
-     * Move a content within this repository.
346
-     * The $target corresponds to the pid to move the records to.
347
-     * It can also be a negative value in case of sorting. The negative value would be the uid of its predecessor.
348
-     *
349
-     * @param Content $content
350
-     * @param string $target
351
-     * @return bool
352
-     */
353
-    public function move($content, $target): bool
354
-    {
355
-
356
-        // Security check.
357
-        $this->getContentValidator()->validate($content);
358
-
359
-        $dataType = $content->getDataType();
360
-        $handler = $this->getDataHandlerFactory()->action(ProcessAction::MOVE)->forType($dataType)->getDataHandler();
361
-
362
-        $handlerResult = $handler->processMove($content, $target);
363
-        $this->errorMessages = $handler->getErrorMessages();
364
-        return $handlerResult;
365
-    }
366
-
367
-    /**
368
-     * Copy a content within this repository.
369
-     *
370
-     * @param Content $content
371
-     * @return bool
372
-     */
373
-    public function copy($content, $target): bool
374
-    {
375
-
376
-        // Security check.
377
-        $this->getContentValidator()->validate($content);
378
-
379
-        $dataType = $content->getDataType();
380
-        $handler = $this->getDataHandlerFactory()->action(ProcessAction::COPY)->forType($dataType)->getDataHandler();
381
-
382
-        $handlerResult = $handler->processCopy($content, $target);
383
-        $this->errorMessages = $handler->getErrorMessages();
384
-        return $handlerResult;
385
-    }
386
-
387
-    /**
388
-     * Adds an object to this repository.
389
-     *
390
-     * @param object $object The object to add
391
-     * @return void
392
-     * @api
393
-     */
394
-    public function add($object)
395
-    {
396
-        throw new \BadMethodCallException('Repository does not support the add() method.', 1375805599);
397
-    }
398
-
399
-    /**
400
-     * Returns the total number objects of this repository.
401
-     *
402
-     * @return integer The object count
403
-     * @api
404
-     */
405
-    public function countAll()
406
-    {
407
-        $query = $this->createQuery();
408
-        return $query->count();
409
-    }
410
-
411
-    /**
412
-     * Removes all objects of this repository as if remove() was called for
413
-     * all of them.
414
-     *
415
-     * @return void
416
-     * @api
417
-     */
418
-    public function removeAll()
419
-    {
420
-        // TODO: Implement removeAll() method.
421
-    }
422
-
423
-    /**
424
-     * Finds an object matching the given identifier.
425
-     *
426
-     * @param mixed $identifier The identifier of the object to find
427
-     * @return Content|null
428
-     * @api
429
-     */
430
-    public function findByIdentifier($identifier)
431
-    {
432
-        $query = $this->createQuery();
433
-
434
-        $result = $query->matching(
435
-            $query->equals('uid', $identifier)
436
-        )
437
-            ->execute();
438
-
439
-        if (is_array($result)) {
440
-            $result = current($result);
441
-        }
442
-
443
-        return $result;
444
-    }
445
-
446
-    /**
447
-     * Dispatches magic methods (findBy[Property]())
448
-     *
449
-     * @param string $methodName The name of the magic method
450
-     * @param string $arguments The arguments of the magic method
451
-     * @return mixed
452
-     * @api
453
-     */
454
-    public function __call($methodName, $arguments)
455
-    {
456
-        if (substr($methodName, 0, 6) === 'findBy' && strlen($methodName) > 7) {
457
-            $propertyName = strtolower(substr(substr($methodName, 6), 0, 1)) . substr(substr($methodName, 6), 1);
458
-            $result = $this->processMagicCall($propertyName, $arguments[0]);
459
-        } elseif (substr($methodName, 0, 9) === 'findOneBy' && strlen($methodName) > 10) {
460
-            $propertyName = strtolower(substr(substr($methodName, 9), 0, 1)) . substr(substr($methodName, 9), 1);
461
-            $result = $this->processMagicCall($propertyName, $arguments[0], 'one');
462
-        } elseif (substr($methodName, 0, 7) === 'countBy' && strlen($methodName) > 8) {
463
-            $propertyName = strtolower(substr(substr($methodName, 7), 0, 1)) . substr(substr($methodName, 7), 1);
464
-            $result = $this->processMagicCall($propertyName, $arguments[0], 'count');
465
-        } else {
466
-            throw new UnsupportedMethodException('The method "' . $methodName . '" is not supported by the repository.', 1360838010);
467
-        }
468
-        return $result;
469
-    }
470
-
471
-    /**
472
-     * Returns a query for objects of this repository
473
-     *
474
-     * @return Query
475
-     * @api
476
-     */
477
-    public function createQuery()
478
-    {
479
-        /** @var Query $query */
480
-        $query = $this->getObjectManager()->get(Query::class, $this->dataType);
481
-        $query->setSourceFieldName($this->sourceFieldName);
482
-
483
-        if ($this->defaultQuerySettings) {
484
-            $query->setQuerySettings($this->defaultQuerySettings);
485
-        } else {
486
-
487
-            // Initialize and pass the query settings at this level.
488
-            /** @var QuerySettings $querySettings */
489
-            $querySettings = $this->getObjectManager()->get(QuerySettings::class);
490
-
491
-            // Default choice for the BE.
492
-            if ($this->isBackendMode()) {
493
-                $querySettings->setIgnoreEnableFields(true);
494
-            }
495
-
496
-            $query->setQuerySettings($querySettings);
497
-        }
498
-
499
-        return $query;
500
-    }
501
-
502
-    /**
503
-     * Sets the property names to order the result by per default.
504
-     * Expected like this:
505
-     * array(
506
-     * 'foo' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING,
507
-     * 'bar' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING
508
-     * )
509
-     *
510
-     * @param array $defaultOrderings The property names to order by
511
-     * @return void
512
-     * @api
513
-     */
514
-    public function setDefaultOrderings(array $defaultOrderings)
515
-    {
516
-        throw new \BadMethodCallException('Repository does not support the setDefaultOrderings() method.', 1375805598);
517
-    }
518
-
519
-    /**
520
-     * Sets the default query settings to be used in this repository
521
-     *
522
-     * @param QuerySettingsInterface $defaultQuerySettings The query settings to be used by default
523
-     * @return void
524
-     * @api
525
-     */
526
-    public function setDefaultQuerySettings(QuerySettingsInterface $defaultQuerySettings)
527
-    {
528
-        $this->defaultQuerySettings = $defaultQuerySettings;
529
-    }
530
-
531
-    /**
532
-     * @return void
533
-     */
534
-    public function resetDefaultQuerySettings(): void
535
-    {
536
-        $this->defaultQuerySettings = null;
537
-    }
538
-
539
-
540
-    /**
541
-     * @return array
542
-     */
543
-    public function getErrorMessages(): array
544
-    {
545
-        return $this->errorMessages;
546
-    }
547
-
548
-    /**
549
-     * @param string $sourceFieldName
550
-     * @return $this
551
-     */
552
-    public function setSourceFieldName($sourceFieldName): self
553
-    {
554
-        $this->sourceFieldName = $sourceFieldName;
555
-        return $this;
556
-    }
557
-
558
-    /**
559
-     * @return string
560
-     */
561
-    public function getDataType(): string
562
-    {
563
-        return $this->dataType;
564
-    }
565
-
566
-    /**
567
-     * Tell whether the order has a foreign table in its expression, e.g. "metadata.title".
568
-     *
569
-     * @param string $ordering
570
-     * @return bool
571
-     */
572
-    protected function hasForeignRelationIn($ordering): bool
573
-    {
574
-        return strpos($ordering, '.') !== false;
575
-    }
576
-
577
-    /**
578
-     * Extract the foreign relation of the ordering "metadata.title" -> "metadata"
579
-     *
580
-     * @param string $ordering
581
-     * @return string
582
-     */
583
-    protected function getForeignRelationFrom($ordering): string
584
-    {
585
-        $parts = explode('.', $ordering);
586
-        return $parts[0];
587
-    }
588
-
589
-    /**
590
-     * Get the constraints
591
-     *
592
-     * @param Query $query
593
-     * @param Matcher $matcher
594
-     * @return ConstraintInterface|null
595
-     */
596
-    protected function computeConstraints(Query $query, Matcher $matcher): ?ConstraintInterface
597
-    {
598
-        $constraints = null;
599
-
600
-        $collectedConstraints = [];
601
-
602
-        // Search term
603
-        $constraint = $this->computeSearchTermConstraint($query, $matcher);
604
-        if ($constraint) {
605
-            $collectedConstraints[] = $constraint;
606
-        }
607
-
608
-        foreach ($matcher->getSupportedOperators() as $operator) {
609
-            $constraint = $this->computeConstraint($query, $matcher, $operator);
610
-            if ($constraint) {
611
-                $collectedConstraints[] = $constraint;
612
-            }
613
-        }
614
-
615
-        if (count($collectedConstraints) > 1) {
616
-            $logical = $matcher->getDefaultLogicalSeparator();
617
-            $constraints = $query->$logical($collectedConstraints);
618
-        } elseif (!empty($collectedConstraints)) {
619
-
620
-            // true means there is one constraint only and should become the result
621
-            $constraints = current($collectedConstraints);
622
-        }
623
-
624
-        // Trigger signal for post processing the computed constraints object.
625
-        $constraints = $this->emitPostProcessConstraintsSignal($query, $constraints);
626
-
627
-        return $constraints;
628
-    }
629
-
630
-    /**
631
-     * Computes the search constraint and returns it.
632
-     *
633
-     * @param Query $query
634
-     * @param Matcher $matcher
635
-     * @return ConstraintInterface|null
636
-     */
637
-    protected function computeSearchTermConstraint(Query $query, Matcher $matcher): ?ConstraintInterface
638
-    {
639
-
640
-        $result = null;
641
-
642
-        // Search term case
643
-        if ($matcher->getSearchTerm()) {
644
-
645
-            $fields = GeneralUtility::trimExplode(',', Tca::table($this->dataType)->getSearchFields(), true);
646
-
647
-            $constraints = [];
648
-            $likeClause = sprintf('%%%s%%', $matcher->getSearchTerm());
649
-            foreach ($fields as $fieldNameAndPath) {
650
-                if ($this->isSuitableForLike($fieldNameAndPath, $matcher->getSearchTerm())) {
651
-
652
-                    $dataType = $this->getFieldPathResolver()->getDataType($fieldNameAndPath, $this->dataType);
653
-                    $fieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath, $this->dataType);
654
-
655
-                    if (Tca::table($dataType)->hasField($fieldName) && Tca::table($dataType)->field($fieldName)->hasRelation()) {
656
-                        $foreignTable = Tca::table($dataType)->field($fieldName)->getForeignTable();
657
-                        $fieldNameAndPath = $fieldNameAndPath . '.' . Tca::table($foreignTable)->getLabelField();
658
-                    }
659
-                    $constraints[] = $query->like($fieldNameAndPath, $likeClause);
660
-                }
661
-            }
662
-            $logical = $matcher->getLogicalSeparatorForSearchTerm();
663
-            $result = $query->$logical($constraints);
664
-        }
665
-
666
-        return $result;
667
-    }
668
-
669
-    /**
670
-     * It does not make sense to have a "like" in presence of numerical field, e.g "uid".
671
-     * Tell whether the given value makes sense for a "like" clause.
672
-     *
673
-     * @param string $fieldNameAndPath
674
-     * @param string $value
675
-     * @return bool
676
-     */
677
-    protected function isSuitableForLike($fieldNameAndPath, $value): bool
678
-    {
679
-        $isSuitable = true;
680
-
681
-        // true means it is a string
682
-        if (!MathUtility::canBeInterpretedAsInteger($value)) {
683
-
684
-            $dataType = $this->getFieldPathResolver()->getDataType($fieldNameAndPath, $this->dataType);
685
-            $fieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath, $this->dataType);
686
-
687
-            if (Tca::table($dataType)->field($fieldName)->isNumerical()
688
-                && !Tca::table($dataType)->field($fieldName)->hasRelation()
689
-            ) {
690
-                $isSuitable = false;
691
-            }
692
-        }
693
-
694
-        return $isSuitable;
695
-    }
696
-
697
-    /**
698
-     * Computes the constraint for matches and returns it.
699
-     *
700
-     * @param Query $query
701
-     * @param Matcher $matcher
702
-     * @param string $operator
703
-     * @return ConstraintInterface|null
704
-     */
705
-    protected function computeConstraint(Query $query, Matcher $matcher, $operator): ?ConstraintInterface
706
-    {
707
-        $result = null;
708
-
709
-        $operatorName = ucfirst($operator);
710
-        $getCriteria = sprintf('get%s', $operatorName);
711
-        $criteria = $matcher->$getCriteria();
712
-
713
-        if (!empty($criteria)) {
714
-            $constraints = [];
715
-
716
-            foreach ($criteria as $criterion) {
717
-
718
-                $fieldNameAndPath = $criterion['fieldNameAndPath'];
719
-                $operand = $criterion['operand'];
720
-
721
-                // Compute a few variables...
722
-                // $dataType is generally equals to $this->dataType but not always... if fieldName is a path.
723
-                $dataType = $this->getFieldPathResolver()->getDataType($fieldNameAndPath, $this->dataType);
724
-                $fieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath, $this->dataType);
725
-                $fieldPath = $this->getFieldPathResolver()->stripFieldName($fieldNameAndPath, $this->dataType);
726
-
727
-                if (Tca::table($dataType)->field($fieldName)->hasRelation()) {
728
-                    if (MathUtility::canBeInterpretedAsInteger($operand)) {
729
-                        $fieldNameAndPath = $fieldName . '.uid';
730
-                    } else {
731
-                        $foreignTableName = Tca::table($dataType)->field($fieldName)->getForeignTable();
732
-                        $foreignTable = Tca::table($foreignTableName);
733
-                        $fieldNameAndPath = $fieldName . '.' . $foreignTable->getLabelField();
734
-                    }
735
-
736
-                    // If different means we should restore the prepended path segment for proper SQL parser.
737
-                    // This is true for a composite field, e.g items.sys_file_metadata for categories.
738
-                    if ($fieldName !== $fieldPath) {
739
-                        $fieldNameAndPath = $fieldPath . '.' . $fieldNameAndPath;
740
-                    }
741
-                }
742
-
743
-                if (strpos($operator, 'not') === 0) {
744
-                    $strippedOperator = strtolower(substr($operator, 3));
745
-                    $constraints[] = $query->logicalNot($query->$strippedOperator($fieldNameAndPath, $criterion['operand']));
746
-                } else {
747
-                    $constraints[] = $query->$operator($fieldNameAndPath, $criterion['operand']);
748
-                }
749
-            }
750
-
751
-            $getLogicalSeparator = sprintf('getLogicalSeparatorFor%s', $operatorName);
752
-            $logical = method_exists($matcher, $getLogicalSeparator)
753
-                ? $matcher->$getLogicalSeparator()
754
-                : $matcher->getDefaultLogicalSeparator();
755
-
756
-            $result = $query->$logical($constraints);
757
-        }
758
-
759
-        return $result;
760
-    }
761
-
762
-    /**
763
-     * @return DataHandler
764
-     */
765
-    protected function getDataHandler(): DataHandler
766
-    {
767
-        if (!$this->dataHandler) {
768
-            $this->dataHandler = GeneralUtility::makeInstance(DataHandler::class);
769
-        }
770
-        return $this->dataHandler;
771
-    }
772
-
773
-    /**
774
-     * Handle the magic call by properly creating a Query object and returning its result.
775
-     *
776
-     * @param string $propertyName
777
-     * @param string $value
778
-     * @param string $flag
779
-     * @return mixed
780
-     */
781
-    protected function processMagicCall($propertyName, $value, $flag = '')
782
-    {
783
-
784
-        $fieldName = Property::name($propertyName)->of($this->dataType)->toFieldName();
785
-
786
-        /** @var $matcher Matcher */
787
-        $matcher = GeneralUtility::makeInstance(Matcher::class, [], $this->getDataType());
788
-
789
-        $table = Tca::table($this->dataType);
790
-        if ($table->field($fieldName)->isGroup()) {
791
-
792
-            $valueParts = explode('.', $value, 2);
793
-            $fieldName = $fieldName . '.' . $valueParts[0];
794
-            $value = $valueParts[1];
795
-        }
796
-
797
-        $matcher->equals($fieldName, $value);
798
-
799
-        if ($flag === 'count') {
800
-            $result = $this->countBy($matcher);
801
-        } else {
802
-            $result = $this->findBy($matcher);
803
-        }
804
-        return $flag === 'one' && !empty($result) ? reset($result) : $result;
805
-    }
806
-
807
-    /**
808
-     * @return DataHandlerFactory|object
809
-     */
810
-    protected function getDataHandlerFactory()
811
-    {
812
-        return GeneralUtility::makeInstance(DataHandlerFactory::class);
813
-    }
814
-
815
-    /**
816
-     * Returns whether the current mode is Backend
817
-     *
818
-     * @return bool
819
-     */
820
-    protected function isBackendMode(): bool
821
-    {
822
-        return ApplicationType::fromRequest($GLOBALS['TYPO3_REQUEST'])->isBackend();
823
-    }
824
-
825
-    /**
826
-     * @return FieldPathResolver|object
827
-     */
828
-    protected function getFieldPathResolver()
829
-    {
830
-        return GeneralUtility::makeInstance(FieldPathResolver::class);
831
-    }
832
-
833
-    /**
834
-     * @return ObjectManager|object
835
-     */
836
-    protected function getObjectManager(): ObjectManager
837
-    {
838
-        return GeneralUtility::makeInstance(ObjectManager::class);
839
-    }
840
-
841
-    /**
842
-     * @return ContentValidator|object
843
-     */
844
-    protected function getContentValidator(): ContentValidator
845
-    {
846
-        return GeneralUtility::makeInstance(ContentValidator::class);
847
-    }
848
-
849
-    /**
850
-     * @return LanguageValidator|object
851
-     */
852
-    protected function getLanguageValidator(): LanguageValidator
853
-    {
854
-        return GeneralUtility::makeInstance(LanguageValidator::class);
855
-    }
856
-
857
-    /**
858
-     * Signal that is called for post-processing the computed constraints object.
859
-     *
860
-     * @param Query $query
861
-     * @param ConstraintInterface|null $constraints
862
-     * @return ConstraintInterface|null $constraints
863
-     */
864
-    protected function emitPostProcessConstraintsSignal(Query $query, $constraints): ?ConstraintInterface
865
-    {
866
-        /** @var ConstraintContainer $constraintContainer */
867
-        $constraintContainer = GeneralUtility::makeInstance(ConstraintContainer::class);
868
-        $result = $this->getSignalSlotDispatcher()->dispatch(
869
-            self::class,
870
-            'postProcessConstraintsObject',
871
-            [
872
-                $query,
873
-                $constraints,
874
-                $constraintContainer
875
-            ]
876
-        );
877
-
878
-        // Backward compatibility.
879
-        $processedConstraints = $result[1];
880
-
881
-        // New way to transmit the constraints.
882
-        if ($constraintContainer->getConstraint()) {
883
-            $processedConstraints = $constraintContainer->getConstraint();
884
-        }
885
-        return $processedConstraints;
886
-    }
887
-
888
-    /**
889
-     * @return Dispatcher
890
-     */
891
-    protected function getSignalSlotDispatcher(): Dispatcher
892
-    {
893
-        return $this->getObjectManager()->get(Dispatcher::class);
894
-    }
42
+	/**
43
+	 * Tell whether it is a raw result (array) or object being returned.
44
+	 *
45
+	 * @var bool
46
+	 */
47
+	protected $rawResult = false;
48
+
49
+	/**
50
+	 * The data type to be returned, e.g fe_users, fe_groups, tt_content, etc...
51
+	 *
52
+	 * @var string
53
+	 */
54
+	protected $dataType;
55
+
56
+	/**
57
+	 * The source field is useful in the context of MM relations to know who is the caller
58
+	 * e.g findByItems which eventually corresponds to a field name.
59
+	 *
60
+	 * @var string
61
+	 */
62
+	protected $sourceFieldName = '';
63
+
64
+	/**
65
+	 * @var array
66
+	 */
67
+	protected $errorMessages = [];
68
+
69
+	/**
70
+	 * @var QuerySettingsInterface
71
+	 */
72
+	protected $defaultQuerySettings;
73
+
74
+	/**
75
+	 * @var DataHandler
76
+	 */
77
+	protected $dataHandler;
78
+
79
+	/**
80
+	 * Constructor
81
+	 *
82
+	 * @param string $dataType
83
+	 */
84
+	public function __construct($dataType)
85
+	{
86
+		$this->dataType = $dataType;
87
+	}
88
+
89
+	/**
90
+	 * Returns all objects of this repository.
91
+	 *
92
+	 * @return Content[]
93
+	 */
94
+	public function findAll()
95
+	{
96
+		$query = $this->createQuery();
97
+		return $query->execute();
98
+	}
99
+
100
+	/**
101
+	 * Returns all "distinct" values for a given property.
102
+	 *
103
+	 * @param string $propertyName
104
+	 * @param Matcher $matcher
105
+	 * @param Order|null $order
106
+	 * @return Content[]
107
+	 */
108
+	public function findDistinctValues($propertyName, Matcher $matcher = null, Order $order = null): array
109
+	{
110
+		$query = $this->createQuery();
111
+		$query->setDistinct($propertyName);
112
+
113
+		// Remove empty values from selection.
114
+		$constraint = $query->logicalNot($query->equals($propertyName, ''));
115
+
116
+		// Add some additional constraints from the Matcher object.
117
+		$matcherConstraint = null;
118
+		if ($matcher !== null) {
119
+			$matcherConstraint = $this->computeConstraints($query, $matcher);
120
+		}
121
+
122
+		// Assemble the final constraints or not.
123
+		if ($matcherConstraint) {
124
+			$query->logicalAnd($matcherConstraint, $constraint);
125
+			$query->matching($query->logicalAnd($matcherConstraint, $constraint));
126
+		} else {
127
+			$query->matching($constraint);
128
+		}
129
+
130
+		if ($order) {
131
+			$query->setOrderings($order->getOrderings());
132
+		}
133
+
134
+		return $query->execute();
135
+	}
136
+
137
+	/**
138
+	 * Returns all "distinct" values for a given property.
139
+	 *
140
+	 * @param string $propertyName
141
+	 * @param Matcher $matcher
142
+	 * @return int
143
+	 */
144
+	public function countDistinctValues($propertyName, Matcher $matcher = null): int
145
+	{
146
+		$query = $this->createQuery();
147
+		$query->setDistinct($propertyName);
148
+
149
+		// Remove empty values from selection.
150
+		$constraint = $query->logicalNot($query->equals($propertyName, ''));
151
+
152
+		// Add some additional constraints from the Matcher object.
153
+		$matcherConstraint = null;
154
+		if (!is_null($matcher)) {
155
+			$matcherConstraint = $this->computeConstraints($query, $matcher);
156
+		}
157
+
158
+		// Assemble the final constraints or not.
159
+		if ($matcherConstraint) {
160
+			$query->logicalAnd($matcherConstraint, $constraint);
161
+			$query->matching($query->logicalAnd($matcherConstraint, $constraint));
162
+		} else {
163
+			$query->matching($constraint);
164
+		}
165
+
166
+		return $query->count();
167
+	}
168
+
169
+	/**
170
+	 * Finds an object matching the given identifier.
171
+	 *
172
+	 * @param int $uid The identifier of the object to find
173
+	 * @return Content|null
174
+	 * @api
175
+	 */
176
+	public function findByUid($uid)
177
+	{
178
+		return $this->findByIdentifier($uid);
179
+	}
180
+
181
+	/**
182
+	 * Finds all Contents given specified matches.
183
+	 *
184
+	 * @param string $propertyName
185
+	 * @param array $values
186
+	 * @return Content[]
187
+	 */
188
+	public function findIn($propertyName, array $values): array
189
+	{
190
+		$query = $this->createQuery();
191
+		$query->matching($query->in($propertyName, $values));
192
+		return $query->execute();
193
+	}
194
+
195
+	/**
196
+	 * Finds all Contents given specified matches.
197
+	 *
198
+	 * @param Matcher $matcher
199
+	 * @param Order $order The order
200
+	 * @param int $limit
201
+	 * @param int $offset
202
+	 * @return Content[]
203
+	 */
204
+	public function findBy(Matcher $matcher, Order $order = null, $limit = null, $offset = null): array
205
+	{
206
+
207
+		$query = $this->createQuery();
208
+
209
+		$limit = (int)$limit; // make sure to cast
210
+		if ($limit > 0) {
211
+			$query->setLimit($limit);
212
+		}
213
+
214
+		if ($order) {
215
+			$query->setOrderings($order->getOrderings());
216
+
217
+			// Loops around the orderings adding if necessary a dummy condition
218
+			// to make sure the relations can be resolved when transforming the query to plain SQL.
219
+			foreach ($order->getOrderings() as $ordering => $direction) {
220
+				if ($this->hasForeignRelationIn($ordering)) {
221
+					$relationalField = $this->getForeignRelationFrom($ordering);
222
+					$matcher->like($relationalField . '.uid', '');
223
+				}
224
+			}
225
+		}
226
+
227
+		if ($offset) {
228
+			$query->setOffset($offset);
229
+		}
230
+
231
+		$constraints = $this->computeConstraints($query, $matcher);
232
+
233
+		if ($constraints) {
234
+			$query->matching($constraints);
235
+		}
236
+
237
+		return $query->execute();
238
+	}
239
+
240
+	/**
241
+	 * Find one Content object given specified matches.
242
+	 *
243
+	 * @param Matcher $matcher
244
+	 * @return Content
245
+	 */
246
+	public function findOneBy(Matcher $matcher): Content
247
+	{
248
+
249
+		$query = $this->createQuery();
250
+
251
+		$constraints = $this->computeConstraints($query, $matcher);
252
+
253
+		if ($constraints) {
254
+			$query->matching($constraints);
255
+		}
256
+
257
+		$query->setLimit(1); // only take one!
258
+
259
+		$resultSet = $query->execute();
260
+		if ($resultSet) {
261
+			$resultSet = current($resultSet);
262
+		}
263
+		return $resultSet;
264
+	}
265
+
266
+	/**
267
+	 * Count all Contents given specified matches.
268
+	 *
269
+	 * @param Matcher $matcher
270
+	 * @return int
271
+	 */
272
+	public function countBy(Matcher $matcher): int
273
+	{
274
+
275
+		$query = $this->createQuery();
276
+
277
+		$constraints = $this->computeConstraints($query, $matcher);
278
+
279
+		if ($constraints) {
280
+			$query->matching($constraints);
281
+		}
282
+
283
+		return $query->count();
284
+	}
285
+
286
+	/**
287
+	 * Update a content with new information.
288
+	 *
289
+	 * @param Content $content
290
+	 * @param $language
291
+	 * @return bool
292
+	 */
293
+	public function localize($content, $language): bool
294
+	{
295
+
296
+		// Security check
297
+		$this->getContentValidator()->validate($content);
298
+		$this->getLanguageValidator()->validate($language);
299
+
300
+		$dataType = $content->getDataType();
301
+		$handler = $this->getDataHandlerFactory()->action(ProcessAction::LOCALIZE)->forType($dataType)->getDataHandler();
302
+
303
+		$handlerResult = $handler->processLocalize($content, $language);
304
+		$this->errorMessages = $handler->getErrorMessages();
305
+		return $handlerResult;
306
+	}
307
+
308
+	/**
309
+	 * Update a content with new information.
310
+	 *
311
+	 * @param Content $content
312
+	 * @return bool
313
+	 */
314
+	public function update($content)
315
+	{
316
+
317
+		// Security check.
318
+		$this->getContentValidator()->validate($content);
319
+
320
+		$dataType = $content->getDataType();
321
+		$handler = $this->getDataHandlerFactory()->action(ProcessAction::UPDATE)->forType($dataType)->getDataHandler();
322
+
323
+		$handlerResult = $handler->processUpdate($content);
324
+		$this->errorMessages = $handler->getErrorMessages();
325
+		return $handlerResult;
326
+	}
327
+
328
+	/**
329
+	 * Removes an object from this repository.
330
+	 *
331
+	 * @param Content $content
332
+	 * @return boolean
333
+	 */
334
+	public function remove($content)
335
+	{
336
+		$dataType = $content->getDataType();
337
+		$handler = $this->getDataHandlerFactory()->action(ProcessAction::REMOVE)->forType($dataType)->getDataHandler();
338
+
339
+		$handlerResult = $handler->processRemove($content);
340
+		$this->errorMessages = $handler->getErrorMessages();
341
+		return $handlerResult;
342
+	}
343
+
344
+	/**
345
+	 * Move a content within this repository.
346
+	 * The $target corresponds to the pid to move the records to.
347
+	 * It can also be a negative value in case of sorting. The negative value would be the uid of its predecessor.
348
+	 *
349
+	 * @param Content $content
350
+	 * @param string $target
351
+	 * @return bool
352
+	 */
353
+	public function move($content, $target): bool
354
+	{
355
+
356
+		// Security check.
357
+		$this->getContentValidator()->validate($content);
358
+
359
+		$dataType = $content->getDataType();
360
+		$handler = $this->getDataHandlerFactory()->action(ProcessAction::MOVE)->forType($dataType)->getDataHandler();
361
+
362
+		$handlerResult = $handler->processMove($content, $target);
363
+		$this->errorMessages = $handler->getErrorMessages();
364
+		return $handlerResult;
365
+	}
366
+
367
+	/**
368
+	 * Copy a content within this repository.
369
+	 *
370
+	 * @param Content $content
371
+	 * @return bool
372
+	 */
373
+	public function copy($content, $target): bool
374
+	{
375
+
376
+		// Security check.
377
+		$this->getContentValidator()->validate($content);
378
+
379
+		$dataType = $content->getDataType();
380
+		$handler = $this->getDataHandlerFactory()->action(ProcessAction::COPY)->forType($dataType)->getDataHandler();
381
+
382
+		$handlerResult = $handler->processCopy($content, $target);
383
+		$this->errorMessages = $handler->getErrorMessages();
384
+		return $handlerResult;
385
+	}
386
+
387
+	/**
388
+	 * Adds an object to this repository.
389
+	 *
390
+	 * @param object $object The object to add
391
+	 * @return void
392
+	 * @api
393
+	 */
394
+	public function add($object)
395
+	{
396
+		throw new \BadMethodCallException('Repository does not support the add() method.', 1375805599);
397
+	}
398
+
399
+	/**
400
+	 * Returns the total number objects of this repository.
401
+	 *
402
+	 * @return integer The object count
403
+	 * @api
404
+	 */
405
+	public function countAll()
406
+	{
407
+		$query = $this->createQuery();
408
+		return $query->count();
409
+	}
410
+
411
+	/**
412
+	 * Removes all objects of this repository as if remove() was called for
413
+	 * all of them.
414
+	 *
415
+	 * @return void
416
+	 * @api
417
+	 */
418
+	public function removeAll()
419
+	{
420
+		// TODO: Implement removeAll() method.
421
+	}
422
+
423
+	/**
424
+	 * Finds an object matching the given identifier.
425
+	 *
426
+	 * @param mixed $identifier The identifier of the object to find
427
+	 * @return Content|null
428
+	 * @api
429
+	 */
430
+	public function findByIdentifier($identifier)
431
+	{
432
+		$query = $this->createQuery();
433
+
434
+		$result = $query->matching(
435
+			$query->equals('uid', $identifier)
436
+		)
437
+			->execute();
438
+
439
+		if (is_array($result)) {
440
+			$result = current($result);
441
+		}
442
+
443
+		return $result;
444
+	}
445
+
446
+	/**
447
+	 * Dispatches magic methods (findBy[Property]())
448
+	 *
449
+	 * @param string $methodName The name of the magic method
450
+	 * @param string $arguments The arguments of the magic method
451
+	 * @return mixed
452
+	 * @api
453
+	 */
454
+	public function __call($methodName, $arguments)
455
+	{
456
+		if (substr($methodName, 0, 6) === 'findBy' && strlen($methodName) > 7) {
457
+			$propertyName = strtolower(substr(substr($methodName, 6), 0, 1)) . substr(substr($methodName, 6), 1);
458
+			$result = $this->processMagicCall($propertyName, $arguments[0]);
459
+		} elseif (substr($methodName, 0, 9) === 'findOneBy' && strlen($methodName) > 10) {
460
+			$propertyName = strtolower(substr(substr($methodName, 9), 0, 1)) . substr(substr($methodName, 9), 1);
461
+			$result = $this->processMagicCall($propertyName, $arguments[0], 'one');
462
+		} elseif (substr($methodName, 0, 7) === 'countBy' && strlen($methodName) > 8) {
463
+			$propertyName = strtolower(substr(substr($methodName, 7), 0, 1)) . substr(substr($methodName, 7), 1);
464
+			$result = $this->processMagicCall($propertyName, $arguments[0], 'count');
465
+		} else {
466
+			throw new UnsupportedMethodException('The method "' . $methodName . '" is not supported by the repository.', 1360838010);
467
+		}
468
+		return $result;
469
+	}
470
+
471
+	/**
472
+	 * Returns a query for objects of this repository
473
+	 *
474
+	 * @return Query
475
+	 * @api
476
+	 */
477
+	public function createQuery()
478
+	{
479
+		/** @var Query $query */
480
+		$query = $this->getObjectManager()->get(Query::class, $this->dataType);
481
+		$query->setSourceFieldName($this->sourceFieldName);
482
+
483
+		if ($this->defaultQuerySettings) {
484
+			$query->setQuerySettings($this->defaultQuerySettings);
485
+		} else {
486
+
487
+			// Initialize and pass the query settings at this level.
488
+			/** @var QuerySettings $querySettings */
489
+			$querySettings = $this->getObjectManager()->get(QuerySettings::class);
490
+
491
+			// Default choice for the BE.
492
+			if ($this->isBackendMode()) {
493
+				$querySettings->setIgnoreEnableFields(true);
494
+			}
495
+
496
+			$query->setQuerySettings($querySettings);
497
+		}
498
+
499
+		return $query;
500
+	}
501
+
502
+	/**
503
+	 * Sets the property names to order the result by per default.
504
+	 * Expected like this:
505
+	 * array(
506
+	 * 'foo' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING,
507
+	 * 'bar' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING
508
+	 * )
509
+	 *
510
+	 * @param array $defaultOrderings The property names to order by
511
+	 * @return void
512
+	 * @api
513
+	 */
514
+	public function setDefaultOrderings(array $defaultOrderings)
515
+	{
516
+		throw new \BadMethodCallException('Repository does not support the setDefaultOrderings() method.', 1375805598);
517
+	}
518
+
519
+	/**
520
+	 * Sets the default query settings to be used in this repository
521
+	 *
522
+	 * @param QuerySettingsInterface $defaultQuerySettings The query settings to be used by default
523
+	 * @return void
524
+	 * @api
525
+	 */
526
+	public function setDefaultQuerySettings(QuerySettingsInterface $defaultQuerySettings)
527
+	{
528
+		$this->defaultQuerySettings = $defaultQuerySettings;
529
+	}
530
+
531
+	/**
532
+	 * @return void
533
+	 */
534
+	public function resetDefaultQuerySettings(): void
535
+	{
536
+		$this->defaultQuerySettings = null;
537
+	}
538
+
539
+
540
+	/**
541
+	 * @return array
542
+	 */
543
+	public function getErrorMessages(): array
544
+	{
545
+		return $this->errorMessages;
546
+	}
547
+
548
+	/**
549
+	 * @param string $sourceFieldName
550
+	 * @return $this
551
+	 */
552
+	public function setSourceFieldName($sourceFieldName): self
553
+	{
554
+		$this->sourceFieldName = $sourceFieldName;
555
+		return $this;
556
+	}
557
+
558
+	/**
559
+	 * @return string
560
+	 */
561
+	public function getDataType(): string
562
+	{
563
+		return $this->dataType;
564
+	}
565
+
566
+	/**
567
+	 * Tell whether the order has a foreign table in its expression, e.g. "metadata.title".
568
+	 *
569
+	 * @param string $ordering
570
+	 * @return bool
571
+	 */
572
+	protected function hasForeignRelationIn($ordering): bool
573
+	{
574
+		return strpos($ordering, '.') !== false;
575
+	}
576
+
577
+	/**
578
+	 * Extract the foreign relation of the ordering "metadata.title" -> "metadata"
579
+	 *
580
+	 * @param string $ordering
581
+	 * @return string
582
+	 */
583
+	protected function getForeignRelationFrom($ordering): string
584
+	{
585
+		$parts = explode('.', $ordering);
586
+		return $parts[0];
587
+	}
588
+
589
+	/**
590
+	 * Get the constraints
591
+	 *
592
+	 * @param Query $query
593
+	 * @param Matcher $matcher
594
+	 * @return ConstraintInterface|null
595
+	 */
596
+	protected function computeConstraints(Query $query, Matcher $matcher): ?ConstraintInterface
597
+	{
598
+		$constraints = null;
599
+
600
+		$collectedConstraints = [];
601
+
602
+		// Search term
603
+		$constraint = $this->computeSearchTermConstraint($query, $matcher);
604
+		if ($constraint) {
605
+			$collectedConstraints[] = $constraint;
606
+		}
607
+
608
+		foreach ($matcher->getSupportedOperators() as $operator) {
609
+			$constraint = $this->computeConstraint($query, $matcher, $operator);
610
+			if ($constraint) {
611
+				$collectedConstraints[] = $constraint;
612
+			}
613
+		}
614
+
615
+		if (count($collectedConstraints) > 1) {
616
+			$logical = $matcher->getDefaultLogicalSeparator();
617
+			$constraints = $query->$logical($collectedConstraints);
618
+		} elseif (!empty($collectedConstraints)) {
619
+
620
+			// true means there is one constraint only and should become the result
621
+			$constraints = current($collectedConstraints);
622
+		}
623
+
624
+		// Trigger signal for post processing the computed constraints object.
625
+		$constraints = $this->emitPostProcessConstraintsSignal($query, $constraints);
626
+
627
+		return $constraints;
628
+	}
629
+
630
+	/**
631
+	 * Computes the search constraint and returns it.
632
+	 *
633
+	 * @param Query $query
634
+	 * @param Matcher $matcher
635
+	 * @return ConstraintInterface|null
636
+	 */
637
+	protected function computeSearchTermConstraint(Query $query, Matcher $matcher): ?ConstraintInterface
638
+	{
639
+
640
+		$result = null;
641
+
642
+		// Search term case
643
+		if ($matcher->getSearchTerm()) {
644
+
645
+			$fields = GeneralUtility::trimExplode(',', Tca::table($this->dataType)->getSearchFields(), true);
646
+
647
+			$constraints = [];
648
+			$likeClause = sprintf('%%%s%%', $matcher->getSearchTerm());
649
+			foreach ($fields as $fieldNameAndPath) {
650
+				if ($this->isSuitableForLike($fieldNameAndPath, $matcher->getSearchTerm())) {
651
+
652
+					$dataType = $this->getFieldPathResolver()->getDataType($fieldNameAndPath, $this->dataType);
653
+					$fieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath, $this->dataType);
654
+
655
+					if (Tca::table($dataType)->hasField($fieldName) && Tca::table($dataType)->field($fieldName)->hasRelation()) {
656
+						$foreignTable = Tca::table($dataType)->field($fieldName)->getForeignTable();
657
+						$fieldNameAndPath = $fieldNameAndPath . '.' . Tca::table($foreignTable)->getLabelField();
658
+					}
659
+					$constraints[] = $query->like($fieldNameAndPath, $likeClause);
660
+				}
661
+			}
662
+			$logical = $matcher->getLogicalSeparatorForSearchTerm();
663
+			$result = $query->$logical($constraints);
664
+		}
665
+
666
+		return $result;
667
+	}
668
+
669
+	/**
670
+	 * It does not make sense to have a "like" in presence of numerical field, e.g "uid".
671
+	 * Tell whether the given value makes sense for a "like" clause.
672
+	 *
673
+	 * @param string $fieldNameAndPath
674
+	 * @param string $value
675
+	 * @return bool
676
+	 */
677
+	protected function isSuitableForLike($fieldNameAndPath, $value): bool
678
+	{
679
+		$isSuitable = true;
680
+
681
+		// true means it is a string
682
+		if (!MathUtility::canBeInterpretedAsInteger($value)) {
683
+
684
+			$dataType = $this->getFieldPathResolver()->getDataType($fieldNameAndPath, $this->dataType);
685
+			$fieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath, $this->dataType);
686
+
687
+			if (Tca::table($dataType)->field($fieldName)->isNumerical()
688
+				&& !Tca::table($dataType)->field($fieldName)->hasRelation()
689
+			) {
690
+				$isSuitable = false;
691
+			}
692
+		}
693
+
694
+		return $isSuitable;
695
+	}
696
+
697
+	/**
698
+	 * Computes the constraint for matches and returns it.
699
+	 *
700
+	 * @param Query $query
701
+	 * @param Matcher $matcher
702
+	 * @param string $operator
703
+	 * @return ConstraintInterface|null
704
+	 */
705
+	protected function computeConstraint(Query $query, Matcher $matcher, $operator): ?ConstraintInterface
706
+	{
707
+		$result = null;
708
+
709
+		$operatorName = ucfirst($operator);
710
+		$getCriteria = sprintf('get%s', $operatorName);
711
+		$criteria = $matcher->$getCriteria();
712
+
713
+		if (!empty($criteria)) {
714
+			$constraints = [];
715
+
716
+			foreach ($criteria as $criterion) {
717
+
718
+				$fieldNameAndPath = $criterion['fieldNameAndPath'];
719
+				$operand = $criterion['operand'];
720
+
721
+				// Compute a few variables...
722
+				// $dataType is generally equals to $this->dataType but not always... if fieldName is a path.
723
+				$dataType = $this->getFieldPathResolver()->getDataType($fieldNameAndPath, $this->dataType);
724
+				$fieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath, $this->dataType);
725
+				$fieldPath = $this->getFieldPathResolver()->stripFieldName($fieldNameAndPath, $this->dataType);
726
+
727
+				if (Tca::table($dataType)->field($fieldName)->hasRelation()) {
728
+					if (MathUtility::canBeInterpretedAsInteger($operand)) {
729
+						$fieldNameAndPath = $fieldName . '.uid';
730
+					} else {
731
+						$foreignTableName = Tca::table($dataType)->field($fieldName)->getForeignTable();
732
+						$foreignTable = Tca::table($foreignTableName);
733
+						$fieldNameAndPath = $fieldName . '.' . $foreignTable->getLabelField();
734
+					}
735
+
736
+					// If different means we should restore the prepended path segment for proper SQL parser.
737
+					// This is true for a composite field, e.g items.sys_file_metadata for categories.
738
+					if ($fieldName !== $fieldPath) {
739
+						$fieldNameAndPath = $fieldPath . '.' . $fieldNameAndPath;
740
+					}
741
+				}
742
+
743
+				if (strpos($operator, 'not') === 0) {
744
+					$strippedOperator = strtolower(substr($operator, 3));
745
+					$constraints[] = $query->logicalNot($query->$strippedOperator($fieldNameAndPath, $criterion['operand']));
746
+				} else {
747
+					$constraints[] = $query->$operator($fieldNameAndPath, $criterion['operand']);
748
+				}
749
+			}
750
+
751
+			$getLogicalSeparator = sprintf('getLogicalSeparatorFor%s', $operatorName);
752
+			$logical = method_exists($matcher, $getLogicalSeparator)
753
+				? $matcher->$getLogicalSeparator()
754
+				: $matcher->getDefaultLogicalSeparator();
755
+
756
+			$result = $query->$logical($constraints);
757
+		}
758
+
759
+		return $result;
760
+	}
761
+
762
+	/**
763
+	 * @return DataHandler
764
+	 */
765
+	protected function getDataHandler(): DataHandler
766
+	{
767
+		if (!$this->dataHandler) {
768
+			$this->dataHandler = GeneralUtility::makeInstance(DataHandler::class);
769
+		}
770
+		return $this->dataHandler;
771
+	}
772
+
773
+	/**
774
+	 * Handle the magic call by properly creating a Query object and returning its result.
775
+	 *
776
+	 * @param string $propertyName
777
+	 * @param string $value
778
+	 * @param string $flag
779
+	 * @return mixed
780
+	 */
781
+	protected function processMagicCall($propertyName, $value, $flag = '')
782
+	{
783
+
784
+		$fieldName = Property::name($propertyName)->of($this->dataType)->toFieldName();
785
+
786
+		/** @var $matcher Matcher */
787
+		$matcher = GeneralUtility::makeInstance(Matcher::class, [], $this->getDataType());
788
+
789
+		$table = Tca::table($this->dataType);
790
+		if ($table->field($fieldName)->isGroup()) {
791
+
792
+			$valueParts = explode('.', $value, 2);
793
+			$fieldName = $fieldName . '.' . $valueParts[0];
794
+			$value = $valueParts[1];
795
+		}
796
+
797
+		$matcher->equals($fieldName, $value);
798
+
799
+		if ($flag === 'count') {
800
+			$result = $this->countBy($matcher);
801
+		} else {
802
+			$result = $this->findBy($matcher);
803
+		}
804
+		return $flag === 'one' && !empty($result) ? reset($result) : $result;
805
+	}
806
+
807
+	/**
808
+	 * @return DataHandlerFactory|object
809
+	 */
810
+	protected function getDataHandlerFactory()
811
+	{
812
+		return GeneralUtility::makeInstance(DataHandlerFactory::class);
813
+	}
814
+
815
+	/**
816
+	 * Returns whether the current mode is Backend
817
+	 *
818
+	 * @return bool
819
+	 */
820
+	protected function isBackendMode(): bool
821
+	{
822
+		return ApplicationType::fromRequest($GLOBALS['TYPO3_REQUEST'])->isBackend();
823
+	}
824
+
825
+	/**
826
+	 * @return FieldPathResolver|object
827
+	 */
828
+	protected function getFieldPathResolver()
829
+	{
830
+		return GeneralUtility::makeInstance(FieldPathResolver::class);
831
+	}
832
+
833
+	/**
834
+	 * @return ObjectManager|object
835
+	 */
836
+	protected function getObjectManager(): ObjectManager
837
+	{
838
+		return GeneralUtility::makeInstance(ObjectManager::class);
839
+	}
840
+
841
+	/**
842
+	 * @return ContentValidator|object
843
+	 */
844
+	protected function getContentValidator(): ContentValidator
845
+	{
846
+		return GeneralUtility::makeInstance(ContentValidator::class);
847
+	}
848
+
849
+	/**
850
+	 * @return LanguageValidator|object
851
+	 */
852
+	protected function getLanguageValidator(): LanguageValidator
853
+	{
854
+		return GeneralUtility::makeInstance(LanguageValidator::class);
855
+	}
856
+
857
+	/**
858
+	 * Signal that is called for post-processing the computed constraints object.
859
+	 *
860
+	 * @param Query $query
861
+	 * @param ConstraintInterface|null $constraints
862
+	 * @return ConstraintInterface|null $constraints
863
+	 */
864
+	protected function emitPostProcessConstraintsSignal(Query $query, $constraints): ?ConstraintInterface
865
+	{
866
+		/** @var ConstraintContainer $constraintContainer */
867
+		$constraintContainer = GeneralUtility::makeInstance(ConstraintContainer::class);
868
+		$result = $this->getSignalSlotDispatcher()->dispatch(
869
+			self::class,
870
+			'postProcessConstraintsObject',
871
+			[
872
+				$query,
873
+				$constraints,
874
+				$constraintContainer
875
+			]
876
+		);
877
+
878
+		// Backward compatibility.
879
+		$processedConstraints = $result[1];
880
+
881
+		// New way to transmit the constraints.
882
+		if ($constraintContainer->getConstraint()) {
883
+			$processedConstraints = $constraintContainer->getConstraint();
884
+		}
885
+		return $processedConstraints;
886
+	}
887
+
888
+	/**
889
+	 * @return Dispatcher
890
+	 */
891
+	protected function getSignalSlotDispatcher(): Dispatcher
892
+	{
893
+		return $this->getObjectManager()->get(Dispatcher::class);
894
+	}
895 895
 
896 896
 }
Please login to merge, or discard this patch.
Classes/Tca/FieldService.php 2 patches
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -484,7 +484,7 @@
 block discarded – undo
484 484
             && isset($this->tca['exclude'])
485 485
             && $this->tca['exclude']
486 486
         ) {
487
-            $hasAccess = $this->getBackendUser()->check('non_exclude_fields', $this->tableName . ':' . $this->fieldName);
487
+            $hasAccess = $this->getBackendUser()->check('non_exclude_fields', $this->tableName.':'.$this->fieldName);
488 488
         }
489 489
         return $hasAccess;
490 490
     }
Please login to merge, or discard this patch.
Indentation   +772 added lines, -772 removed lines patch added patch discarded remove patch
@@ -17,777 +17,777 @@
 block discarded – undo
17 17
 class FieldService extends AbstractTca
18 18
 {
19 19
 
20
-    /**
21
-     * @var string
22
-     */
23
-    protected $fieldName;
24
-
25
-    /**
26
-     * @var string
27
-     */
28
-    protected $compositeField;
29
-
30
-    /**
31
-     * @var string
32
-     */
33
-    protected $tableName;
34
-
35
-    /**
36
-     * @var array
37
-     */
38
-    protected $tca;
39
-
40
-    /**
41
-     * @param string $fieldName
42
-     * @param array $tca
43
-     * @param string $tableName
44
-     * @param string $compositeField
45
-     * @return \Fab\Vidi\Tca\FieldService
46
-     */
47
-    public function __construct($fieldName, array $tca, $tableName, $compositeField = '')
48
-    {
49
-        $this->fieldName = $fieldName;
50
-        $this->tca = $tca;
51
-        $this->tableName = $tableName;
52
-        $this->compositeField = $compositeField;
53
-    }
54
-
55
-    /**
56
-     * Tells whether the field is considered as system field, e.g. uid, crdate, tstamp, etc...
57
-     *
58
-     * @return bool
59
-     */
60
-    public function isSystem()
61
-    {
62
-        return in_array($this->fieldName, Tca::getSystemFields());
63
-    }
64
-
65
-    /**
66
-     * Tells the opposition of isSystem()
67
-     *
68
-     * @return bool
69
-     */
70
-    public function isNotSystem()
71
-    {
72
-        return !$this->isSystem();
73
-    }
74
-
75
-    /**
76
-     * Returns the configuration for a $field
77
-     *
78
-     * @throws \Exception
79
-     * @return array
80
-     */
81
-    public function getConfiguration()
82
-    {
83
-        return empty($this->tca['config']) ? [] : $this->tca['config'];
84
-    }
85
-
86
-    /**
87
-     * Returns a key of the configuration.
88
-     * If the key can not to be found, returns null.
89
-     *
90
-     * @param string $key
91
-     * @return mixed
92
-     */
93
-    public function get($key)
94
-    {
95
-        $configuration = $this->getConfiguration();
96
-        return empty($configuration[$key]) ? null : $configuration[$key];
97
-    }
98
-
99
-    /**
100
-     * Returns the foreign field of a given field (opposite relational field).
101
-     * If no relation exists, returns null.
102
-     *
103
-     * @return string|null
104
-     */
105
-    public function getForeignField()
106
-    {
107
-        $result = null;
108
-        $configuration = $this->getConfiguration();
109
-
110
-        if (!empty($configuration['foreign_field'])) {
111
-            $result = $configuration['foreign_field'];
112
-        } elseif ($this->hasRelationManyToMany()) {
113
-
114
-            $foreignTable = $this->getForeignTable();
115
-            $manyToManyTable = $this->getManyToManyTable();
116
-
117
-            // Load TCA service of foreign field.
118
-            $tcaForeignTableService = Tca::table($foreignTable);
119
-
120
-            // Look into the MM relations checking for the opposite field
121
-            foreach ($tcaForeignTableService->getFields() as $fieldName) {
122
-                if ($manyToManyTable == $tcaForeignTableService->field($fieldName)->getManyToManyTable()) {
123
-                    $result = $fieldName;
124
-                    break;
125
-                }
126
-            }
127
-        }
128
-        return $result;
129
-    }
130
-
131
-    /**
132
-     * Returns the foreign table of a given field (opposite relational table).
133
-     * If no relation exists, returns null.
134
-     *
135
-     * @return string|null
136
-     */
137
-    public function getForeignTable()
138
-    {
139
-        $result = null;
140
-        $configuration = $this->getConfiguration();
141
-
142
-        if (!empty($configuration['foreign_table'])) {
143
-            $result = $configuration['foreign_table'];
144
-        } elseif ($this->isGroup()) {
145
-            $fieldParts = explode('.', $this->compositeField, 2);
146
-            $result = $fieldParts[1];
147
-        }
148
-        return $result;
149
-    }
150
-
151
-    /**
152
-     * Returns the foreign clause.
153
-     * If no foreign order exists, returns empty string.
154
-     *
155
-     * @return string
156
-     */
157
-    public function getForeignClause()
158
-    {
159
-        $result = '';
160
-        $configuration = $this->getConfiguration();
161
-
162
-        if (!empty($configuration['foreign_table_where'])) {
163
-            $parts = explode('ORDER BY', $configuration['foreign_table_where']);
164
-            if (!empty($parts[0])) {
165
-                $result = $parts[0];
166
-            }
167
-        }
168
-
169
-        // Substitute some variables
170
-        return $this->substituteKnownMarkers($result);
171
-    }
172
-
173
-    /**
174
-     * Substitute some known markers from the where clause in the Frontend Context.
175
-     *
176
-     * @param string $clause
177
-     * @return string
178
-     */
179
-    protected function substituteKnownMarkers($clause)
180
-    {
181
-        if ($clause && $this->isFrontendMode()) {
182
-
183
-            $searches = array(
184
-                '###CURRENT_PID###',
185
-                '###REC_FIELD_sys_language_uid###'
186
-            );
187
-
188
-            $replaces = array(
189
-                $this->getFrontendObject()->id,
190
-                $this->getFrontendObject()->sys_language_uid,
191
-            );
192
-
193
-            $clause = str_replace($searches, $replaces, $clause);
194
-        }
195
-        return $clause;
196
-    }
197
-
198
-    /**
199
-     * Returns the foreign order of the current field.
200
-     * If no foreign order exists, returns empty string.
201
-     *
202
-     * @return string
203
-     */
204
-    public function getForeignOrder()
205
-    {
206
-        $result = '';
207
-        $configuration = $this->getConfiguration();
208
-
209
-        if (!empty($configuration['foreign_table_where'])) {
210
-            $parts = explode('ORDER BY', $configuration['foreign_table_where']);
211
-            if (!empty($parts[1])) {
212
-                $result = $parts[1];
213
-            }
214
-        }
215
-        return $result;
216
-    }
217
-
218
-    /**
219
-     * Returns the MM table of a field.
220
-     * If no relation exists, returns null.
221
-     *
222
-     * @return string|null
223
-     */
224
-    public function getManyToManyTable()
225
-    {
226
-        $configuration = $this->getConfiguration();
227
-        return empty($configuration['MM']) ? null : $configuration['MM'];
228
-    }
229
-
230
-    /**
231
-     * Returns a possible additional table name used in MM relations.
232
-     * If no table name exists, returns null.
233
-     *
234
-     * @return string|null
235
-     */
236
-    public function getAdditionalTableNameCondition()
237
-    {
238
-        $result = null;
239
-        $configuration = $this->getConfiguration();
240
-
241
-        if (!empty($configuration['MM_match_fields']['tablenames'])) {
242
-            $result = $configuration['MM_match_fields']['tablenames'];
243
-        } elseif ($this->isGroup()) {
244
-
245
-            // @todo check if $this->fieldName could be simply used as $result
246
-            $fieldParts = explode('.', $this->compositeField, 2);
247
-            $result = $fieldParts[1];
248
-        }
249
-
250
-        return $result;
251
-    }
252
-
253
-    /**
254
-     * Returns a possible additional conditions for MM tables such as "tablenames", "fieldname", etc...
255
-     *
256
-     * @return array
257
-     */
258
-    public function getAdditionalMMCondition()
259
-    {
260
-        $additionalMMConditions = [];
261
-        $configuration = $this->getConfiguration();
262
-
263
-        if (!empty($configuration['MM_match_fields'])) {
264
-            $additionalMMConditions = $configuration['MM_match_fields'];
265
-        }
266
-
267
-        // Add in any case a table name for "group"
268
-        if ($this->isGroup()) {
269
-
270
-            // @todo check if $this->fieldName could be simply used as $result
271
-            $fieldParts = explode('.', $this->compositeField, 2);
272
-            $additionalMMConditions = array(
273
-                'tablenames' => $fieldParts[1],
274
-            );
275
-        }
276
-        return $additionalMMConditions;
277
-    }
278
-
279
-    /**
280
-     * Returns whether the field name is the opposite in MM relation.
281
-     *
282
-     * @return bool
283
-     */
284
-    public function isOppositeRelation()
285
-    {
286
-        $configuration = $this->getConfiguration();
287
-        return isset($configuration['MM_opposite_field']);
288
-    }
289
-
290
-    /**
291
-     * Returns the configuration for a $field.
292
-     *
293
-     * @throws \Exception
294
-     * @return string
295
-     */
296
-    public function getType()
297
-    {
298
-
299
-        if ($this->isSystem()) {
300
-            $fieldType = FieldType::NUMBER;
301
-        } else {
302
-            $configuration = $this->getConfiguration();
303
-
304
-            if (empty($configuration['type'])) {
305
-                throw new \Exception(sprintf('No field type found for "%s" in table "%s"', $this->fieldName, $this->tableName), 1385556627);
306
-            }
307
-
308
-            $fieldType = $configuration['type'];
309
-
310
-            if ($configuration['type'] === FieldType::SELECT && !empty($configuration['size']) && $configuration['size'] > 1) {
311
-                $fieldType = FieldType::MULTISELECT;
312
-            } elseif (!empty($configuration['foreign_table'])
313
-                && ($configuration['foreign_table'] == 'sys_file_reference' || $configuration['foreign_table'] == 'sys_file')
314
-            ) {
315
-                $fieldType = FieldType::FILE;
316
-            } elseif (!empty($configuration['eval'])) {
317
-                $parts = GeneralUtility::trimExplode(',', $configuration['eval']);
318
-                if (in_array('datetime', $parts)) {
319
-                    $fieldType = FieldType::DATETIME;
320
-                } elseif (in_array('date', $parts)) {
321
-                    $fieldType = FieldType::DATE;
322
-                } elseif (in_array('email', $parts)) {
323
-                    $fieldType = FieldType::EMAIL;
324
-                } elseif (in_array('int', $parts) || in_array('double2', $parts)) {
325
-                    $fieldType = FieldType::NUMBER;
326
-                }
327
-            }
328
-
329
-            // Do some legacy conversion
330
-            if ($fieldType === 'input') {
331
-                $fieldType = FieldType::TEXT;
332
-            } elseif ($fieldType === 'text') {
333
-                $fieldType = FieldType::TEXTAREA;
334
-            }
335
-        }
336
-        return $fieldType;
337
-    }
338
-
339
-    /**
340
-     * Return the default value.
341
-     *
342
-     * @return bool
343
-     */
344
-    public function getDefaultValue()
345
-    {
346
-        $configuration = $this->getConfiguration();
347
-        return isset($configuration['default']) ? $configuration['default'] : null;
348
-    }
349
-
350
-    /**
351
-     * Get the translation of a label given a column.
352
-     *
353
-     * @return string
354
-     */
355
-    public function getLabel()
356
-    {
357
-        $label = '';
358
-        if ($this->hasLabel()) {
359
-            try {
360
-                $label = LocalizationUtility::translate($this->tca['label'], '');
361
-            } catch (\InvalidArgumentException $e) {
362
-            }
363
-            if (empty($label)) {
364
-                $label = $this->tca['label'];
365
-            }
366
-        }
367
-        return $label;
368
-    }
369
-
370
-    /**
371
-     * Get the translation of a label given a column.
372
-     *
373
-     * @param string $itemValue the item value to search for.
374
-     * @return string
375
-     */
376
-    public function getLabelForItem($itemValue)
377
-    {
378
-
379
-        // Early return whether there is nothing to be translated as label.
380
-        if (is_null($itemValue)) {
381
-            return '';
382
-        } elseif (is_string($itemValue) && $itemValue === '') {
383
-            return $itemValue;
384
-        }
385
-
386
-        $configuration = $this->getConfiguration();
387
-        if (!empty($configuration['items']) && is_array($configuration['items'])) {
388
-            foreach ($configuration['items'] as $item) {
389
-                if ($item[1] == $itemValue) {
390
-                    try {
391
-                        $label = LocalizationUtility::translate($item[0], '');
392
-                    } catch (\InvalidArgumentException $e) {
393
-                    }
394
-                    if (empty($label)) {
395
-                        $label = $item[0];
396
-                    }
397
-                    break;
398
-                }
399
-            }
400
-        }
401
-
402
-        // Try fetching a label from a possible itemsProcFunc
403
-        if (!isset($label) && is_scalar($itemValue)) {
404
-            $items = $this->fetchItemsFromUserFunction();
405
-            if (!empty($items[$itemValue])) {
406
-                $label = $items[$itemValue];
407
-            }
408
-        }
409
-
410
-        // Returns a label if it has been found, otherwise returns the item value as fallback.
411
-        return isset($label) ? $label : $itemValue;
412
-    }
413
-
414
-    /**
415
-     * Retrieve items from User Function.
416
-     *
417
-     * @return array
418
-     */
419
-    protected function fetchItemsFromUserFunction()
420
-    {
421
-        $values = [];
422
-
423
-        $configuration = $this->getConfiguration();
424
-        if (!empty($configuration['itemsProcFunc'])) {
425
-            $parts = explode('php:', $configuration['itemsProcFunc']);
426
-            if (!empty($parts[1])) {
427
-
428
-                list($class, $method) = explode('->', $parts[1]);
429
-
430
-                $parameters['items'] = [];
431
-                $object = GeneralUtility::makeInstance($class);
432
-                $object->$method($parameters);
433
-
434
-                foreach ($parameters['items'] as $items) {
435
-                    $values[$items[1]] = $items[0];
436
-                }
437
-            }
438
-        }
439
-        return $values;
440
-    }
441
-
442
-    /**
443
-     * Get a possible icon given a field name an an item.
444
-     *
445
-     * @param string $itemValue the item value to search for.
446
-     * @return string
447
-     */
448
-    public function getIconForItem($itemValue)
449
-    {
450
-        $result = '';
451
-        $configuration = $this->getConfiguration();
452
-        if (!empty($configuration['items']) && is_array($configuration['items'])) {
453
-            foreach ($configuration['items'] as $item) {
454
-                if ($item[1] == $itemValue) {
455
-                    $result = empty($item[2]) ? '' : $item[2];
456
-                    break;
457
-                }
458
-            }
459
-        }
460
-        return $result;
461
-    }
462
-
463
-    /**
464
-     * Returns whether the field has a label.
465
-     *
466
-     * @return bool
467
-     */
468
-    public function hasLabel()
469
-    {
470
-        return empty($this->tca['label']) ? false : true;
471
-    }
472
-
473
-    /**
474
-     * Tell whether the current BE User has access to this field.
475
-     *
476
-     * @return bool
477
-     */
478
-    public function hasAccess()
479
-    {
480
-        $hasAccess = true;
481
-        if ($this->isBackendMode()
482
-            && Tca::table($this->tableName)->hasAccess()
483
-            && isset($this->tca['exclude'])
484
-            && $this->tca['exclude']
485
-        ) {
486
-            $hasAccess = $this->getBackendUser()->check('non_exclude_fields', $this->tableName . ':' . $this->fieldName);
487
-        }
488
-        return $hasAccess;
489
-    }
490
-
491
-    /**
492
-     * Returns whether the field is numerical.
493
-     *
494
-     * @return bool
495
-     */
496
-    public function isNumerical()
497
-    {
498
-        $result = $this->isSystem();
499
-        if ($result === false) {
500
-            $configuration = $this->getConfiguration();
501
-            $parts = [];
502
-            if (!empty($configuration['eval'])) {
503
-                $parts = GeneralUtility::trimExplode(',', $configuration['eval']);
504
-            }
505
-            $result = in_array('int', $parts) || in_array('float', $parts);
506
-        }
507
-        return $result;
508
-    }
509
-
510
-    /**
511
-     * Returns whether the field is of type text area.
512
-     *
513
-     * @return bool
514
-     */
515
-    public function isTextArea()
516
-    {
517
-        return $this->getType() === FieldType::TEXTAREA;
518
-    }
519
-    /**
520
-     * Returns whether the field is of type text area.
521
-     *
522
-     * @return bool
523
-     */
524
-    public function isText()
525
-    {
526
-        return $this->getType() === FieldType::TEXT;
527
-    }
528
-
529
-    /**
530
-     * Returns whether the field is displayed as a tree.
531
-     *
532
-     * @return bool
533
-     */
534
-    public function isRenderModeTree()
535
-    {
536
-        $configuration = $this->getConfiguration();
537
-        return isset($configuration['renderMode']) && $configuration['renderMode'] == FieldType::TREE;
538
-    }
539
-
540
-    /**
541
-     * Returns whether the field is of type select.
542
-     *
543
-     * @return bool
544
-     */
545
-    public function isSelect()
546
-    {
547
-        return $this->getType() === FieldType::SELECT;
548
-    }
549
-
550
-    /**
551
-     * Returns whether the field is of type select.
552
-     *
553
-     * @return bool
554
-     */
555
-    public function isMultipleSelect()
556
-    {
557
-        return $this->getType() === FieldType::MULTISELECT;
558
-    }
559
-
560
-    /**
561
-     * Returns whether the field is of type select.
562
-     *
563
-     * @return bool
564
-     */
565
-    public function isCheckBox()
566
-    {
567
-        return $this->getType() === FieldType::CHECKBOX;
568
-    }
569
-
570
-    /**
571
-     * Returns whether the field is of type db.
572
-     *
573
-     * @return bool
574
-     */
575
-    public function isGroup()
576
-    {
577
-        return $this->getType() === 'group';
578
-    }
579
-
580
-    /**
581
-     * Returns whether the field is language aware.
582
-     *
583
-     * @return bool
584
-     */
585
-    public function isLocalized()
586
-    {
587
-        $isLocalized = false;
588
-        if (isset($this->tca['l10n_mode'])) {
589
-
590
-            if ($this->tca['l10n_mode'] == 'prefixLangTitle' || $this->tca['l10n_mode'] == 'mergeIfNotBlank') {
591
-                $isLocalized = true;
592
-            }
593
-        }
594
-        return $isLocalized;
595
-    }
596
-
597
-    /**
598
-     * Returns whether the field is required.
599
-     *
600
-     * @return bool
601
-     */
602
-    public function isRequired()
603
-    {
604
-        $configuration = $this->getConfiguration();
605
-
606
-        $isRequired = false;
607
-        if (isset($configuration['minitems'])) {
608
-            // is required of a select?
609
-            $isRequired = $configuration['minitems'] == 1 ? true : false;
610
-        } elseif (isset($configuration['eval'])) {
611
-            $parts = GeneralUtility::trimExplode(',', $configuration['eval'], true);
612
-            $isRequired = in_array('required', $parts);
613
-        }
614
-        return $isRequired;
615
-    }
616
-
617
-    /**
618
-     * Returns an array containing the configuration of a column.
619
-     *
620
-     * @return array
621
-     */
622
-    public function getField()
623
-    {
624
-        return $this->tca;
625
-    }
626
-
627
-    /**
628
-     * Returns the relation type
629
-     *
630
-     * @return string
631
-     */
632
-    public function relationDataType()
633
-    {
634
-        $configuration = $this->getConfiguration();
635
-        return empty($configuration['foreign_table']) ? '' : $configuration['foreign_table'];
636
-    }
637
-
638
-    /**
639
-     * Returns whether the field has relation (one to many, many to many)
640
-     *
641
-     * @return bool
642
-     */
643
-    public function hasRelation()
644
-    {
645
-        return null !== $this->getForeignTable();
646
-    }
647
-
648
-    /**
649
-     * Returns whether the field has no relation (one to many, many to many)
650
-     *
651
-     * @return bool
652
-     */
653
-    public function hasNoRelation()
654
-    {
655
-        return !$this->hasRelation();
656
-    }
657
-
658
-    /**
659
-     * Returns whether the field has a "many" objects connected including "many-to-many" or "one-to-many".
660
-     *
661
-     * @return bool
662
-     */
663
-    public function hasMany()
664
-    {
665
-        $configuration = $this->getConfiguration();
666
-        return $this->hasRelation() && ($configuration['maxitems'] > 1 || isset($configuration['foreign_table_field']));
667
-    }
668
-
669
-    /**
670
-     * Returns whether the field has relation "one" object connected including of "one-to-one" or "many-to-one".
671
-     *
672
-     * @return bool
673
-     */
674
-    public function hasOne()
675
-    {
676
-        $configuration = $this->getConfiguration();
677
-        return !isset($configuration['MM']) && $this->hasRelation() && ($configuration['maxitems'] == 1 || !isset($configuration['maxitems']));
678
-    }
679
-
680
-    /**
681
-     * Returns whether the field has many-to-one relation.
682
-     *
683
-     * @return bool
684
-     */
685
-    public function hasRelationManyToOne()
686
-    {
687
-        $result = false;
688
-
689
-        $foreignField = $this->getForeignField();
690
-        if (!empty($foreignField)) {
691
-
692
-            // Load TCA service of the foreign field.
693
-            $foreignTable = $this->getForeignTable();
694
-            $result = $this->hasOne() && Tca::table($foreignTable)->field($foreignField)->hasMany();
695
-        }
696
-        return $result;
697
-    }
698
-
699
-    /**
700
-     * Returns whether the field has one-to-many relation.
701
-     *
702
-     * @return bool
703
-     */
704
-    public function hasRelationOneToMany()
705
-    {
706
-        $result = false;
707
-
708
-        $foreignField = $this->getForeignField();
709
-        if (!empty($foreignField)) {
710
-
711
-            // Load TCA service of the foreign field.
712
-            $foreignTable = $this->getForeignTable();
713
-            $result = $this->hasMany() && Tca::table($foreignTable)->field($foreignField)->hasOne();
714
-        }
715
-        return $result;
716
-    }
717
-
718
-    /**
719
-     * Returns whether the field has one-to-one relation.
720
-     *
721
-     * @return bool
722
-     */
723
-    public function hasRelationOneToOne()
724
-    {
725
-        $result = false;
726
-
727
-        $foreignField = $this->getForeignField();
728
-        if (!empty($foreignField)) {
729
-
730
-            // Load TCA service of foreign field.
731
-            $foreignTable = $this->getForeignTable();
732
-            $result = $this->hasOne() && Tca::table($foreignTable)->field($foreignField)->hasOne();
733
-        }
734
-        return $result;
735
-    }
736
-
737
-    /**
738
-     * Returns whether the field has many to many relation.
739
-     *
740
-     * @return bool
741
-     */
742
-    public function hasRelationManyToMany()
743
-    {
744
-        $configuration = $this->getConfiguration();
745
-        return $this->hasRelation() && (isset($configuration['MM']) || isset($configuration['foreign_table_field']));
746
-    }
747
-
748
-    /**
749
-     * Returns whether the field has many to many relation using comma separated values (legacy).
750
-     *
751
-     * @return bool
752
-     */
753
-    public function hasRelationWithCommaSeparatedValues()
754
-    {
755
-        $configuration = $this->getConfiguration();
756
-        return $this->hasRelation() && !isset($configuration['MM']) && !isset($configuration['foreign_field']) && $configuration['maxitems'] > 1;
757
-    }
758
-
759
-    /**
760
-     * @return array
761
-     */
762
-    public function getTca()
763
-    {
764
-        return $this->tca['columns'];
765
-    }
766
-
767
-    /**
768
-     * @return string
769
-     */
770
-    public function getCompositeField()
771
-    {
772
-        return $this->compositeField;
773
-    }
774
-
775
-    /**
776
-     * @param string $compositeField
777
-     */
778
-    public function setCompositeField($compositeField)
779
-    {
780
-        $this->compositeField = $compositeField;
781
-    }
782
-
783
-    /**
784
-     * Returns an instance of the Frontend object.
785
-     *
786
-     * @return TypoScriptFrontendController
787
-     */
788
-    protected function getFrontendObject()
789
-    {
790
-        return $GLOBALS['TSFE'];
791
-    }
20
+	/**
21
+	 * @var string
22
+	 */
23
+	protected $fieldName;
24
+
25
+	/**
26
+	 * @var string
27
+	 */
28
+	protected $compositeField;
29
+
30
+	/**
31
+	 * @var string
32
+	 */
33
+	protected $tableName;
34
+
35
+	/**
36
+	 * @var array
37
+	 */
38
+	protected $tca;
39
+
40
+	/**
41
+	 * @param string $fieldName
42
+	 * @param array $tca
43
+	 * @param string $tableName
44
+	 * @param string $compositeField
45
+	 * @return \Fab\Vidi\Tca\FieldService
46
+	 */
47
+	public function __construct($fieldName, array $tca, $tableName, $compositeField = '')
48
+	{
49
+		$this->fieldName = $fieldName;
50
+		$this->tca = $tca;
51
+		$this->tableName = $tableName;
52
+		$this->compositeField = $compositeField;
53
+	}
54
+
55
+	/**
56
+	 * Tells whether the field is considered as system field, e.g. uid, crdate, tstamp, etc...
57
+	 *
58
+	 * @return bool
59
+	 */
60
+	public function isSystem()
61
+	{
62
+		return in_array($this->fieldName, Tca::getSystemFields());
63
+	}
64
+
65
+	/**
66
+	 * Tells the opposition of isSystem()
67
+	 *
68
+	 * @return bool
69
+	 */
70
+	public function isNotSystem()
71
+	{
72
+		return !$this->isSystem();
73
+	}
74
+
75
+	/**
76
+	 * Returns the configuration for a $field
77
+	 *
78
+	 * @throws \Exception
79
+	 * @return array
80
+	 */
81
+	public function getConfiguration()
82
+	{
83
+		return empty($this->tca['config']) ? [] : $this->tca['config'];
84
+	}
85
+
86
+	/**
87
+	 * Returns a key of the configuration.
88
+	 * If the key can not to be found, returns null.
89
+	 *
90
+	 * @param string $key
91
+	 * @return mixed
92
+	 */
93
+	public function get($key)
94
+	{
95
+		$configuration = $this->getConfiguration();
96
+		return empty($configuration[$key]) ? null : $configuration[$key];
97
+	}
98
+
99
+	/**
100
+	 * Returns the foreign field of a given field (opposite relational field).
101
+	 * If no relation exists, returns null.
102
+	 *
103
+	 * @return string|null
104
+	 */
105
+	public function getForeignField()
106
+	{
107
+		$result = null;
108
+		$configuration = $this->getConfiguration();
109
+
110
+		if (!empty($configuration['foreign_field'])) {
111
+			$result = $configuration['foreign_field'];
112
+		} elseif ($this->hasRelationManyToMany()) {
113
+
114
+			$foreignTable = $this->getForeignTable();
115
+			$manyToManyTable = $this->getManyToManyTable();
116
+
117
+			// Load TCA service of foreign field.
118
+			$tcaForeignTableService = Tca::table($foreignTable);
119
+
120
+			// Look into the MM relations checking for the opposite field
121
+			foreach ($tcaForeignTableService->getFields() as $fieldName) {
122
+				if ($manyToManyTable == $tcaForeignTableService->field($fieldName)->getManyToManyTable()) {
123
+					$result = $fieldName;
124
+					break;
125
+				}
126
+			}
127
+		}
128
+		return $result;
129
+	}
130
+
131
+	/**
132
+	 * Returns the foreign table of a given field (opposite relational table).
133
+	 * If no relation exists, returns null.
134
+	 *
135
+	 * @return string|null
136
+	 */
137
+	public function getForeignTable()
138
+	{
139
+		$result = null;
140
+		$configuration = $this->getConfiguration();
141
+
142
+		if (!empty($configuration['foreign_table'])) {
143
+			$result = $configuration['foreign_table'];
144
+		} elseif ($this->isGroup()) {
145
+			$fieldParts = explode('.', $this->compositeField, 2);
146
+			$result = $fieldParts[1];
147
+		}
148
+		return $result;
149
+	}
150
+
151
+	/**
152
+	 * Returns the foreign clause.
153
+	 * If no foreign order exists, returns empty string.
154
+	 *
155
+	 * @return string
156
+	 */
157
+	public function getForeignClause()
158
+	{
159
+		$result = '';
160
+		$configuration = $this->getConfiguration();
161
+
162
+		if (!empty($configuration['foreign_table_where'])) {
163
+			$parts = explode('ORDER BY', $configuration['foreign_table_where']);
164
+			if (!empty($parts[0])) {
165
+				$result = $parts[0];
166
+			}
167
+		}
168
+
169
+		// Substitute some variables
170
+		return $this->substituteKnownMarkers($result);
171
+	}
172
+
173
+	/**
174
+	 * Substitute some known markers from the where clause in the Frontend Context.
175
+	 *
176
+	 * @param string $clause
177
+	 * @return string
178
+	 */
179
+	protected function substituteKnownMarkers($clause)
180
+	{
181
+		if ($clause && $this->isFrontendMode()) {
182
+
183
+			$searches = array(
184
+				'###CURRENT_PID###',
185
+				'###REC_FIELD_sys_language_uid###'
186
+			);
187
+
188
+			$replaces = array(
189
+				$this->getFrontendObject()->id,
190
+				$this->getFrontendObject()->sys_language_uid,
191
+			);
192
+
193
+			$clause = str_replace($searches, $replaces, $clause);
194
+		}
195
+		return $clause;
196
+	}
197
+
198
+	/**
199
+	 * Returns the foreign order of the current field.
200
+	 * If no foreign order exists, returns empty string.
201
+	 *
202
+	 * @return string
203
+	 */
204
+	public function getForeignOrder()
205
+	{
206
+		$result = '';
207
+		$configuration = $this->getConfiguration();
208
+
209
+		if (!empty($configuration['foreign_table_where'])) {
210
+			$parts = explode('ORDER BY', $configuration['foreign_table_where']);
211
+			if (!empty($parts[1])) {
212
+				$result = $parts[1];
213
+			}
214
+		}
215
+		return $result;
216
+	}
217
+
218
+	/**
219
+	 * Returns the MM table of a field.
220
+	 * If no relation exists, returns null.
221
+	 *
222
+	 * @return string|null
223
+	 */
224
+	public function getManyToManyTable()
225
+	{
226
+		$configuration = $this->getConfiguration();
227
+		return empty($configuration['MM']) ? null : $configuration['MM'];
228
+	}
229
+
230
+	/**
231
+	 * Returns a possible additional table name used in MM relations.
232
+	 * If no table name exists, returns null.
233
+	 *
234
+	 * @return string|null
235
+	 */
236
+	public function getAdditionalTableNameCondition()
237
+	{
238
+		$result = null;
239
+		$configuration = $this->getConfiguration();
240
+
241
+		if (!empty($configuration['MM_match_fields']['tablenames'])) {
242
+			$result = $configuration['MM_match_fields']['tablenames'];
243
+		} elseif ($this->isGroup()) {
244
+
245
+			// @todo check if $this->fieldName could be simply used as $result
246
+			$fieldParts = explode('.', $this->compositeField, 2);
247
+			$result = $fieldParts[1];
248
+		}
249
+
250
+		return $result;
251
+	}
252
+
253
+	/**
254
+	 * Returns a possible additional conditions for MM tables such as "tablenames", "fieldname", etc...
255
+	 *
256
+	 * @return array
257
+	 */
258
+	public function getAdditionalMMCondition()
259
+	{
260
+		$additionalMMConditions = [];
261
+		$configuration = $this->getConfiguration();
262
+
263
+		if (!empty($configuration['MM_match_fields'])) {
264
+			$additionalMMConditions = $configuration['MM_match_fields'];
265
+		}
266
+
267
+		// Add in any case a table name for "group"
268
+		if ($this->isGroup()) {
269
+
270
+			// @todo check if $this->fieldName could be simply used as $result
271
+			$fieldParts = explode('.', $this->compositeField, 2);
272
+			$additionalMMConditions = array(
273
+				'tablenames' => $fieldParts[1],
274
+			);
275
+		}
276
+		return $additionalMMConditions;
277
+	}
278
+
279
+	/**
280
+	 * Returns whether the field name is the opposite in MM relation.
281
+	 *
282
+	 * @return bool
283
+	 */
284
+	public function isOppositeRelation()
285
+	{
286
+		$configuration = $this->getConfiguration();
287
+		return isset($configuration['MM_opposite_field']);
288
+	}
289
+
290
+	/**
291
+	 * Returns the configuration for a $field.
292
+	 *
293
+	 * @throws \Exception
294
+	 * @return string
295
+	 */
296
+	public function getType()
297
+	{
298
+
299
+		if ($this->isSystem()) {
300
+			$fieldType = FieldType::NUMBER;
301
+		} else {
302
+			$configuration = $this->getConfiguration();
303
+
304
+			if (empty($configuration['type'])) {
305
+				throw new \Exception(sprintf('No field type found for "%s" in table "%s"', $this->fieldName, $this->tableName), 1385556627);
306
+			}
307
+
308
+			$fieldType = $configuration['type'];
309
+
310
+			if ($configuration['type'] === FieldType::SELECT && !empty($configuration['size']) && $configuration['size'] > 1) {
311
+				$fieldType = FieldType::MULTISELECT;
312
+			} elseif (!empty($configuration['foreign_table'])
313
+				&& ($configuration['foreign_table'] == 'sys_file_reference' || $configuration['foreign_table'] == 'sys_file')
314
+			) {
315
+				$fieldType = FieldType::FILE;
316
+			} elseif (!empty($configuration['eval'])) {
317
+				$parts = GeneralUtility::trimExplode(',', $configuration['eval']);
318
+				if (in_array('datetime', $parts)) {
319
+					$fieldType = FieldType::DATETIME;
320
+				} elseif (in_array('date', $parts)) {
321
+					$fieldType = FieldType::DATE;
322
+				} elseif (in_array('email', $parts)) {
323
+					$fieldType = FieldType::EMAIL;
324
+				} elseif (in_array('int', $parts) || in_array('double2', $parts)) {
325
+					$fieldType = FieldType::NUMBER;
326
+				}
327
+			}
328
+
329
+			// Do some legacy conversion
330
+			if ($fieldType === 'input') {
331
+				$fieldType = FieldType::TEXT;
332
+			} elseif ($fieldType === 'text') {
333
+				$fieldType = FieldType::TEXTAREA;
334
+			}
335
+		}
336
+		return $fieldType;
337
+	}
338
+
339
+	/**
340
+	 * Return the default value.
341
+	 *
342
+	 * @return bool
343
+	 */
344
+	public function getDefaultValue()
345
+	{
346
+		$configuration = $this->getConfiguration();
347
+		return isset($configuration['default']) ? $configuration['default'] : null;
348
+	}
349
+
350
+	/**
351
+	 * Get the translation of a label given a column.
352
+	 *
353
+	 * @return string
354
+	 */
355
+	public function getLabel()
356
+	{
357
+		$label = '';
358
+		if ($this->hasLabel()) {
359
+			try {
360
+				$label = LocalizationUtility::translate($this->tca['label'], '');
361
+			} catch (\InvalidArgumentException $e) {
362
+			}
363
+			if (empty($label)) {
364
+				$label = $this->tca['label'];
365
+			}
366
+		}
367
+		return $label;
368
+	}
369
+
370
+	/**
371
+	 * Get the translation of a label given a column.
372
+	 *
373
+	 * @param string $itemValue the item value to search for.
374
+	 * @return string
375
+	 */
376
+	public function getLabelForItem($itemValue)
377
+	{
378
+
379
+		// Early return whether there is nothing to be translated as label.
380
+		if (is_null($itemValue)) {
381
+			return '';
382
+		} elseif (is_string($itemValue) && $itemValue === '') {
383
+			return $itemValue;
384
+		}
385
+
386
+		$configuration = $this->getConfiguration();
387
+		if (!empty($configuration['items']) && is_array($configuration['items'])) {
388
+			foreach ($configuration['items'] as $item) {
389
+				if ($item[1] == $itemValue) {
390
+					try {
391
+						$label = LocalizationUtility::translate($item[0], '');
392
+					} catch (\InvalidArgumentException $e) {
393
+					}
394
+					if (empty($label)) {
395
+						$label = $item[0];
396
+					}
397
+					break;
398
+				}
399
+			}
400
+		}
401
+
402
+		// Try fetching a label from a possible itemsProcFunc
403
+		if (!isset($label) && is_scalar($itemValue)) {
404
+			$items = $this->fetchItemsFromUserFunction();
405
+			if (!empty($items[$itemValue])) {
406
+				$label = $items[$itemValue];
407
+			}
408
+		}
409
+
410
+		// Returns a label if it has been found, otherwise returns the item value as fallback.
411
+		return isset($label) ? $label : $itemValue;
412
+	}
413
+
414
+	/**
415
+	 * Retrieve items from User Function.
416
+	 *
417
+	 * @return array
418
+	 */
419
+	protected function fetchItemsFromUserFunction()
420
+	{
421
+		$values = [];
422
+
423
+		$configuration = $this->getConfiguration();
424
+		if (!empty($configuration['itemsProcFunc'])) {
425
+			$parts = explode('php:', $configuration['itemsProcFunc']);
426
+			if (!empty($parts[1])) {
427
+
428
+				list($class, $method) = explode('->', $parts[1]);
429
+
430
+				$parameters['items'] = [];
431
+				$object = GeneralUtility::makeInstance($class);
432
+				$object->$method($parameters);
433
+
434
+				foreach ($parameters['items'] as $items) {
435
+					$values[$items[1]] = $items[0];
436
+				}
437
+			}
438
+		}
439
+		return $values;
440
+	}
441
+
442
+	/**
443
+	 * Get a possible icon given a field name an an item.
444
+	 *
445
+	 * @param string $itemValue the item value to search for.
446
+	 * @return string
447
+	 */
448
+	public function getIconForItem($itemValue)
449
+	{
450
+		$result = '';
451
+		$configuration = $this->getConfiguration();
452
+		if (!empty($configuration['items']) && is_array($configuration['items'])) {
453
+			foreach ($configuration['items'] as $item) {
454
+				if ($item[1] == $itemValue) {
455
+					$result = empty($item[2]) ? '' : $item[2];
456
+					break;
457
+				}
458
+			}
459
+		}
460
+		return $result;
461
+	}
462
+
463
+	/**
464
+	 * Returns whether the field has a label.
465
+	 *
466
+	 * @return bool
467
+	 */
468
+	public function hasLabel()
469
+	{
470
+		return empty($this->tca['label']) ? false : true;
471
+	}
472
+
473
+	/**
474
+	 * Tell whether the current BE User has access to this field.
475
+	 *
476
+	 * @return bool
477
+	 */
478
+	public function hasAccess()
479
+	{
480
+		$hasAccess = true;
481
+		if ($this->isBackendMode()
482
+			&& Tca::table($this->tableName)->hasAccess()
483
+			&& isset($this->tca['exclude'])
484
+			&& $this->tca['exclude']
485
+		) {
486
+			$hasAccess = $this->getBackendUser()->check('non_exclude_fields', $this->tableName . ':' . $this->fieldName);
487
+		}
488
+		return $hasAccess;
489
+	}
490
+
491
+	/**
492
+	 * Returns whether the field is numerical.
493
+	 *
494
+	 * @return bool
495
+	 */
496
+	public function isNumerical()
497
+	{
498
+		$result = $this->isSystem();
499
+		if ($result === false) {
500
+			$configuration = $this->getConfiguration();
501
+			$parts = [];
502
+			if (!empty($configuration['eval'])) {
503
+				$parts = GeneralUtility::trimExplode(',', $configuration['eval']);
504
+			}
505
+			$result = in_array('int', $parts) || in_array('float', $parts);
506
+		}
507
+		return $result;
508
+	}
509
+
510
+	/**
511
+	 * Returns whether the field is of type text area.
512
+	 *
513
+	 * @return bool
514
+	 */
515
+	public function isTextArea()
516
+	{
517
+		return $this->getType() === FieldType::TEXTAREA;
518
+	}
519
+	/**
520
+	 * Returns whether the field is of type text area.
521
+	 *
522
+	 * @return bool
523
+	 */
524
+	public function isText()
525
+	{
526
+		return $this->getType() === FieldType::TEXT;
527
+	}
528
+
529
+	/**
530
+	 * Returns whether the field is displayed as a tree.
531
+	 *
532
+	 * @return bool
533
+	 */
534
+	public function isRenderModeTree()
535
+	{
536
+		$configuration = $this->getConfiguration();
537
+		return isset($configuration['renderMode']) && $configuration['renderMode'] == FieldType::TREE;
538
+	}
539
+
540
+	/**
541
+	 * Returns whether the field is of type select.
542
+	 *
543
+	 * @return bool
544
+	 */
545
+	public function isSelect()
546
+	{
547
+		return $this->getType() === FieldType::SELECT;
548
+	}
549
+
550
+	/**
551
+	 * Returns whether the field is of type select.
552
+	 *
553
+	 * @return bool
554
+	 */
555
+	public function isMultipleSelect()
556
+	{
557
+		return $this->getType() === FieldType::MULTISELECT;
558
+	}
559
+
560
+	/**
561
+	 * Returns whether the field is of type select.
562
+	 *
563
+	 * @return bool
564
+	 */
565
+	public function isCheckBox()
566
+	{
567
+		return $this->getType() === FieldType::CHECKBOX;
568
+	}
569
+
570
+	/**
571
+	 * Returns whether the field is of type db.
572
+	 *
573
+	 * @return bool
574
+	 */
575
+	public function isGroup()
576
+	{
577
+		return $this->getType() === 'group';
578
+	}
579
+
580
+	/**
581
+	 * Returns whether the field is language aware.
582
+	 *
583
+	 * @return bool
584
+	 */
585
+	public function isLocalized()
586
+	{
587
+		$isLocalized = false;
588
+		if (isset($this->tca['l10n_mode'])) {
589
+
590
+			if ($this->tca['l10n_mode'] == 'prefixLangTitle' || $this->tca['l10n_mode'] == 'mergeIfNotBlank') {
591
+				$isLocalized = true;
592
+			}
593
+		}
594
+		return $isLocalized;
595
+	}
596
+
597
+	/**
598
+	 * Returns whether the field is required.
599
+	 *
600
+	 * @return bool
601
+	 */
602
+	public function isRequired()
603
+	{
604
+		$configuration = $this->getConfiguration();
605
+
606
+		$isRequired = false;
607
+		if (isset($configuration['minitems'])) {
608
+			// is required of a select?
609
+			$isRequired = $configuration['minitems'] == 1 ? true : false;
610
+		} elseif (isset($configuration['eval'])) {
611
+			$parts = GeneralUtility::trimExplode(',', $configuration['eval'], true);
612
+			$isRequired = in_array('required', $parts);
613
+		}
614
+		return $isRequired;
615
+	}
616
+
617
+	/**
618
+	 * Returns an array containing the configuration of a column.
619
+	 *
620
+	 * @return array
621
+	 */
622
+	public function getField()
623
+	{
624
+		return $this->tca;
625
+	}
626
+
627
+	/**
628
+	 * Returns the relation type
629
+	 *
630
+	 * @return string
631
+	 */
632
+	public function relationDataType()
633
+	{
634
+		$configuration = $this->getConfiguration();
635
+		return empty($configuration['foreign_table']) ? '' : $configuration['foreign_table'];
636
+	}
637
+
638
+	/**
639
+	 * Returns whether the field has relation (one to many, many to many)
640
+	 *
641
+	 * @return bool
642
+	 */
643
+	public function hasRelation()
644
+	{
645
+		return null !== $this->getForeignTable();
646
+	}
647
+
648
+	/**
649
+	 * Returns whether the field has no relation (one to many, many to many)
650
+	 *
651
+	 * @return bool
652
+	 */
653
+	public function hasNoRelation()
654
+	{
655
+		return !$this->hasRelation();
656
+	}
657
+
658
+	/**
659
+	 * Returns whether the field has a "many" objects connected including "many-to-many" or "one-to-many".
660
+	 *
661
+	 * @return bool
662
+	 */
663
+	public function hasMany()
664
+	{
665
+		$configuration = $this->getConfiguration();
666
+		return $this->hasRelation() && ($configuration['maxitems'] > 1 || isset($configuration['foreign_table_field']));
667
+	}
668
+
669
+	/**
670
+	 * Returns whether the field has relation "one" object connected including of "one-to-one" or "many-to-one".
671
+	 *
672
+	 * @return bool
673
+	 */
674
+	public function hasOne()
675
+	{
676
+		$configuration = $this->getConfiguration();
677
+		return !isset($configuration['MM']) && $this->hasRelation() && ($configuration['maxitems'] == 1 || !isset($configuration['maxitems']));
678
+	}
679
+
680
+	/**
681
+	 * Returns whether the field has many-to-one relation.
682
+	 *
683
+	 * @return bool
684
+	 */
685
+	public function hasRelationManyToOne()
686
+	{
687
+		$result = false;
688
+
689
+		$foreignField = $this->getForeignField();
690
+		if (!empty($foreignField)) {
691
+
692
+			// Load TCA service of the foreign field.
693
+			$foreignTable = $this->getForeignTable();
694
+			$result = $this->hasOne() && Tca::table($foreignTable)->field($foreignField)->hasMany();
695
+		}
696
+		return $result;
697
+	}
698
+
699
+	/**
700
+	 * Returns whether the field has one-to-many relation.
701
+	 *
702
+	 * @return bool
703
+	 */
704
+	public function hasRelationOneToMany()
705
+	{
706
+		$result = false;
707
+
708
+		$foreignField = $this->getForeignField();
709
+		if (!empty($foreignField)) {
710
+
711
+			// Load TCA service of the foreign field.
712
+			$foreignTable = $this->getForeignTable();
713
+			$result = $this->hasMany() && Tca::table($foreignTable)->field($foreignField)->hasOne();
714
+		}
715
+		return $result;
716
+	}
717
+
718
+	/**
719
+	 * Returns whether the field has one-to-one relation.
720
+	 *
721
+	 * @return bool
722
+	 */
723
+	public function hasRelationOneToOne()
724
+	{
725
+		$result = false;
726
+
727
+		$foreignField = $this->getForeignField();
728
+		if (!empty($foreignField)) {
729
+
730
+			// Load TCA service of foreign field.
731
+			$foreignTable = $this->getForeignTable();
732
+			$result = $this->hasOne() && Tca::table($foreignTable)->field($foreignField)->hasOne();
733
+		}
734
+		return $result;
735
+	}
736
+
737
+	/**
738
+	 * Returns whether the field has many to many relation.
739
+	 *
740
+	 * @return bool
741
+	 */
742
+	public function hasRelationManyToMany()
743
+	{
744
+		$configuration = $this->getConfiguration();
745
+		return $this->hasRelation() && (isset($configuration['MM']) || isset($configuration['foreign_table_field']));
746
+	}
747
+
748
+	/**
749
+	 * Returns whether the field has many to many relation using comma separated values (legacy).
750
+	 *
751
+	 * @return bool
752
+	 */
753
+	public function hasRelationWithCommaSeparatedValues()
754
+	{
755
+		$configuration = $this->getConfiguration();
756
+		return $this->hasRelation() && !isset($configuration['MM']) && !isset($configuration['foreign_field']) && $configuration['maxitems'] > 1;
757
+	}
758
+
759
+	/**
760
+	 * @return array
761
+	 */
762
+	public function getTca()
763
+	{
764
+		return $this->tca['columns'];
765
+	}
766
+
767
+	/**
768
+	 * @return string
769
+	 */
770
+	public function getCompositeField()
771
+	{
772
+		return $this->compositeField;
773
+	}
774
+
775
+	/**
776
+	 * @param string $compositeField
777
+	 */
778
+	public function setCompositeField($compositeField)
779
+	{
780
+		$this->compositeField = $compositeField;
781
+	}
782
+
783
+	/**
784
+	 * Returns an instance of the Frontend object.
785
+	 *
786
+	 * @return TypoScriptFrontendController
787
+	 */
788
+	protected function getFrontendObject()
789
+	{
790
+		return $GLOBALS['TSFE'];
791
+	}
792 792
 
793 793
 }
Please login to merge, or discard this patch.
Classes/Tca/TableService.php 2 patches
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -240,7 +240,7 @@
 block discarded – undo
240 240
     public function getDefaultOrderSql()
241 241
     {
242 242
         // "sortby" typically has "sorting" as value.
243
-        $order = $this->get('sortby') ? $this->get('sortby') . ' ASC' : $this->get('default_sortby');
243
+        $order = $this->get('sortby') ? $this->get('sortby').' ASC' : $this->get('default_sortby');
244 244
         return $order;
245 245
     }
246 246
 
Please login to merge, or discard this patch.
Indentation   +442 added lines, -442 removed lines patch added patch discarded remove patch
@@ -20,447 +20,447 @@
 block discarded – undo
20 20
 class TableService extends AbstractTca
21 21
 {
22 22
 
23
-    /**
24
-     * @var array
25
-     */
26
-    protected $tca;
27
-
28
-    /**
29
-     * @var array
30
-     */
31
-    protected $columnTca;
32
-
33
-    /**
34
-     * @var string
35
-     */
36
-    protected $tableName;
37
-
38
-    /**
39
-     * @var array
40
-     */
41
-    protected $instances;
42
-
43
-    /**
44
-     * @throws InvalidKeyInArrayException
45
-     * @param string $tableName
46
-     * @return \Fab\Vidi\Tca\TableService
47
-     */
48
-    public function __construct($tableName)
49
-    {
50
-        $this->tableName = $tableName;
51
-        if (empty($GLOBALS['TCA'][$this->tableName])) {
52
-            throw new InvalidKeyInArrayException(sprintf('No TCA existence for table "%s"', $this->tableName), 1356945106);
53
-        }
54
-        $this->tca = $GLOBALS['TCA'][$this->tableName]['ctrl'];
55
-        $this->columnTca = $GLOBALS['TCA'][$this->tableName]['columns'];
56
-    }
57
-
58
-    /**
59
-     * Tell whether the table has a label field.
60
-     *
61
-     * @throws InvalidKeyInArrayException
62
-     * @return string
63
-     */
64
-    public function hasLabelField()
65
-    {
66
-        return $this->has('label');
67
-    }
68
-
69
-    /**
70
-     * Get the label name of table name.
71
-     *
72
-     * @throws InvalidKeyInArrayException
73
-     * @return string
74
-     */
75
-    public function getLabelField()
76
-    {
77
-        $labelField = $this->get('label');
78
-        if (empty($labelField)) {
79
-            throw new InvalidKeyInArrayException(sprintf('No label configured for table "%s"', $this->tableName), 1385586726);
80
-        }
81
-        return $labelField;
82
-    }
83
-
84
-    /**
85
-     * Returns the translated label of the table name.
86
-     *
87
-     * @return string
88
-     */
89
-    public function getLabel()
90
-    {
91
-        $label = '';
92
-        try {
93
-            $label = LocalizationUtility::translate($this->getLabelField(), '');
94
-        } catch (\InvalidArgumentException $e) {
95
-        }
96
-        if (empty($label)) {
97
-            $label = $this->getLabelField();
98
-        }
99
-        return $label;
100
-    }
101
-
102
-    /**
103
-     * Returns the title of the table.
104
-     *
105
-     * @return string
106
-     */
107
-    public function getTitle()
108
-    {
109
-        $title = '';
110
-        try {
111
-            $title = LocalizationUtility::translate((string)$this->get('title'), '');
112
-        } catch (\InvalidArgumentException $e) {
113
-        }
114
-        if (empty($title)) {
115
-            $title = $this->get('title');
116
-        }
117
-        return $title;
118
-    }
119
-
120
-    /**
121
-     * Return the "disabled" field.
122
-     *
123
-     * @throws InvalidKeyInArrayException
124
-     * @return string|null
125
-     */
126
-    public function getHiddenField()
127
-    {
128
-        $hiddenField = null;
129
-        $enableColumns = $this->get('enablecolumns');
130
-        if (is_array($enableColumns) && !empty($enableColumns['disabled'])) {
131
-            $hiddenField = $enableColumns['disabled'];
132
-        }
133
-        return $hiddenField;
134
-    }
135
-
136
-    /**
137
-     * Return the "starttime" field.
138
-     *
139
-     * @throws InvalidKeyInArrayException
140
-     * @return string|null
141
-     */
142
-    public function getStartTimeField()
143
-    {
144
-        $startTimeField = null;
145
-        $enableColumns = $this->get('enablecolumns');
146
-        if (is_array($enableColumns) && !empty($enableColumns['starttime'])) {
147
-            $startTimeField = $enableColumns['starttime'];
148
-        }
149
-        return $startTimeField;
150
-    }
151
-
152
-    /**
153
-     * Return the "endtime" field.
154
-     *
155
-     * @throws InvalidKeyInArrayException
156
-     * @return string|null
157
-     */
158
-    public function getEndTimeField()
159
-    {
160
-        $endTimeField = null;
161
-        $enableColumns = $this->get('enablecolumns');
162
-        if (is_array($enableColumns) && !empty($enableColumns['endtime'])) {
163
-            $endTimeField = $enableColumns['endtime'];
164
-        }
165
-        return $endTimeField;
166
-    }
167
-
168
-    /**
169
-     * Tells whether the table is hidden.
170
-     *
171
-     * @return bool
172
-     */
173
-    public function isHidden()
174
-    {
175
-        return isset($this->tca['hideTable']) ? $this->tca['hideTable'] : false;
176
-    }
177
-
178
-    /**
179
-     * Tells whether the table is not hidden.
180
-     *
181
-     * @return bool
182
-     */
183
-    public function isNotHidden()
184
-    {
185
-        return !$this->isHidden();
186
-    }
187
-
188
-    /**
189
-     * Get the "deleted" field for the table.
190
-     *
191
-     * @return string|null
192
-     */
193
-    public function getDeletedField()
194
-    {
195
-        return $this->get('delete');
196
-    }
197
-
198
-    /**
199
-     * Get the modification time stamp field.
200
-     *
201
-     * @return string|null
202
-     */
203
-    public function getTimeModificationField()
204
-    {
205
-        return $this->get('tstamp');
206
-    }
207
-
208
-    /**
209
-     * Get the creation time stamp field.
210
-     *
211
-     * @return string|null
212
-     */
213
-    public function getTimeCreationField()
214
-    {
215
-        return $this->get('crdate');
216
-    }
217
-
218
-    /**
219
-     * Get the language field for the table.
220
-     *
221
-     * @return string|null
222
-     */
223
-    public function getLanguageField()
224
-    {
225
-        return $this->get('languageField');
226
-    }
227
-
228
-    /**
229
-     * Get the field which points to the parent.
230
-     *
231
-     * @return string|null
232
-     */
233
-    public function getLanguageParentField()
234
-    {
235
-        return $this->get('transOrigPointerField');
236
-    }
237
-
238
-    /**
239
-     * Returns the default order in the form of a SQL segment.
240
-     *
241
-     * @return string|null
242
-     */
243
-    public function getDefaultOrderSql()
244
-    {
245
-        // "sortby" typically has "sorting" as value.
246
-        $order = $this->get('sortby') ? $this->get('sortby') . ' ASC' : $this->get('default_sortby');
247
-        return $order;
248
-    }
249
-
250
-    /**
251
-     * Returns the parsed default orderings.
252
-     * Returns array looks like array('title' => 'ASC');
253
-     *
254
-     * @return array
255
-     */
256
-    public function getDefaultOrderings()
257
-    {
258
-
259
-        // first clean up the sql segment
260
-        $defaultOrder = str_replace('ORDER BY', '', $this->getDefaultOrderSql());
261
-        $defaultOrderParts = GeneralUtility::trimExplode(',', $defaultOrder, true);
262
-
263
-        $orderings = [];
264
-        foreach ($defaultOrderParts as $defaultOrderPart) {
265
-            $parts = GeneralUtility::trimExplode(' ', $defaultOrderPart);
266
-            if (empty($parts[1])) {
267
-                $parts[1] = QueryInterface::ORDER_DESCENDING;
268
-            }
269
-            $orderings[$parts[0]] = $parts[1];
270
-        }
271
-
272
-        return $orderings;
273
-    }
274
-
275
-    /**
276
-     * Returns the searchable fields.
277
-     *
278
-     * @return string|null
279
-     */
280
-    public function getSearchFields()
281
-    {
282
-        return $this->get('searchFields');
283
-    }
284
-
285
-    /**
286
-     * Returns an array containing the field names.
287
-     *
288
-     * @return array
289
-     */
290
-    public function getFields()
291
-    {
292
-        return array_keys($this->columnTca);
293
-    }
294
-
295
-    /**
296
-     * Returns an array containing the fields and their configuration.
297
-     *
298
-     * @return array
299
-     */
300
-    public function getFieldsAndConfiguration()
301
-    {
302
-        return $this->columnTca;
303
-    }
304
-
305
-    /**
306
-     * Tell whether we have a field "sorting".
307
-     *
308
-     * @return bool
309
-     */
310
-    public function hasSortableField()
311
-    {
312
-        return $this->has('sortby');
313
-    }
314
-
315
-    /**
316
-     * Tell whether the field exists or not.
317
-     *
318
-     * @param string $fieldName
319
-     * @return bool
320
-     */
321
-    public function hasField($fieldName)
322
-    {
323
-        if ($this->isComposite($fieldName)) {
324
-            $parts = explode('.', $fieldName);
325
-            list ($strippedFieldPath, $possibleTableName) = $parts;
326
-            $hasField = isset($this->columnTca[$strippedFieldPath], $GLOBALS['TCA'][$possibleTableName]);
327
-
328
-            // Continue checking that the $strippedFieldName is of type "group"
329
-            if (isset($GLOBALS['TCA'][$this->tableName]['columns'][$strippedFieldPath]) && count($parts) > 2) {
330
-                $hasField = Tca::table($this->tableName)->field($strippedFieldPath)->isGroup(); // Group
331
-            } elseif (isset($this->columnTca[$strippedFieldPath]['config']['readOnly']) && (bool)$this->columnTca[$strippedFieldPath]['config']['readOnly']) {
332
-                $hasField = false; // handle case metadata.fe_groups where "fe_groups" is a tableName.
333
-            }
334
-        } else {
335
-            $hasField = isset($this->columnTca[$fieldName]) || in_array($fieldName, Tca::getSystemFields(), true);
336
-        }
337
-        return $hasField;
338
-    }
339
-
340
-    /**
341
-     * Tell whether the field name contains a path, e.g. metadata.title
342
-     *
343
-     * @param string $fieldName
344
-     * @return boolean
345
-     */
346
-    public function isComposite($fieldName)
347
-    {
348
-        return strpos($fieldName, '.') > 0;
349
-    }
350
-
351
-    /**
352
-     * Tells whether the $key exists.
353
-     *
354
-     * @param string $key
355
-     * @return string
356
-     */
357
-    public function has($key)
358
-    {
359
-        return isset($this->tca[$key]);
360
-    }
361
-
362
-    /**
363
-     * Tells whether the table name has "workspace" support.
364
-     *
365
-     * @return string
366
-     */
367
-    public function hasWorkspaceSupport()
368
-    {
369
-        return isset($this->tca['versioningWS']);
370
-    }
371
-
372
-    /**
373
-     * Tells whether the table name has "language" support.
374
-     *
375
-     * @return string
376
-     */
377
-    public function hasLanguageSupport()
378
-    {
379
-        return isset($this->tca['languageField']);
380
-    }
381
-
382
-    /**
383
-     * Return configuration value given a key.
384
-     *
385
-     * @param string $key
386
-     * @return string|null
387
-     */
388
-    public function get($key)
389
-    {
390
-        return $this->has($key) ? $this->tca[$key] : null;
391
-    }
392
-
393
-    /**
394
-     * @return array
395
-     */
396
-    public function getTca()
397
-    {
398
-        return $this->tca;
399
-    }
400
-
401
-    /**
402
-     * Tell whether the current BE User has access to this field.
403
-     *
404
-     * @return bool
405
-     */
406
-    public function hasAccess()
407
-    {
408
-        $hasAccess = true;
409
-        if ($this->isBackendMode()) {
410
-            $hasAccess = $this->getBackendUser()->check('tables_modify', $this->tableName);
411
-        }
412
-        return $hasAccess;
413
-    }
414
-
415
-    /**
416
-     * @param string $fieldName
417
-     * @throws \Exception
418
-     * @return FieldService
419
-     */
420
-    public function field($fieldName)
421
-    {
422
-
423
-        // In case field contains items.tx_table for field type "group"
424
-        $compositeField = '';
425
-        if (strpos($fieldName, '.') !== false) {
426
-            $compositeField = $fieldName;
427
-            $fieldParts = explode('.', $compositeField, 2);
428
-            $fieldName = $fieldParts[0];
429
-
430
-            // Special when field has been instantiated without the field name and path.
431
-            if (!empty($this->instances[$fieldName])) {
432
-                /** @var FieldService $field */
433
-                $field = $this->instances[$fieldName];
434
-                $field->setCompositeField($compositeField);
435
-            }
436
-        }
437
-
438
-        // True for system fields such as uid, pid that don't necessarily have a TCA.
439
-        if (empty($this->columnTca[$fieldName]) && in_array($fieldName, Tca::getSystemFields())) {
440
-            $this->columnTca[$fieldName] = [];
441
-        } elseif (empty($this->columnTca[$fieldName])) {
442
-            $message = sprintf(
443
-                'Does the field really exist? No TCA entry found for field "%s" for table "%s"',
444
-                $fieldName,
445
-                $this->tableName
446
-            );
447
-            throw new \Exception($message, 1385554481);
448
-        }
449
-
450
-
451
-        if (empty($this->instances[$fieldName])) {
452
-
453
-            $instance = GeneralUtility::makeInstance(
454
-                'Fab\Vidi\Tca\FieldService',
455
-                $fieldName,
456
-                $this->columnTca[$fieldName],
457
-                $this->tableName,
458
-                $compositeField
459
-            );
460
-
461
-            $this->instances[$fieldName] = $instance;
462
-        }
463
-        return $this->instances[$fieldName];
464
-    }
23
+	/**
24
+	 * @var array
25
+	 */
26
+	protected $tca;
27
+
28
+	/**
29
+	 * @var array
30
+	 */
31
+	protected $columnTca;
32
+
33
+	/**
34
+	 * @var string
35
+	 */
36
+	protected $tableName;
37
+
38
+	/**
39
+	 * @var array
40
+	 */
41
+	protected $instances;
42
+
43
+	/**
44
+	 * @throws InvalidKeyInArrayException
45
+	 * @param string $tableName
46
+	 * @return \Fab\Vidi\Tca\TableService
47
+	 */
48
+	public function __construct($tableName)
49
+	{
50
+		$this->tableName = $tableName;
51
+		if (empty($GLOBALS['TCA'][$this->tableName])) {
52
+			throw new InvalidKeyInArrayException(sprintf('No TCA existence for table "%s"', $this->tableName), 1356945106);
53
+		}
54
+		$this->tca = $GLOBALS['TCA'][$this->tableName]['ctrl'];
55
+		$this->columnTca = $GLOBALS['TCA'][$this->tableName]['columns'];
56
+	}
57
+
58
+	/**
59
+	 * Tell whether the table has a label field.
60
+	 *
61
+	 * @throws InvalidKeyInArrayException
62
+	 * @return string
63
+	 */
64
+	public function hasLabelField()
65
+	{
66
+		return $this->has('label');
67
+	}
68
+
69
+	/**
70
+	 * Get the label name of table name.
71
+	 *
72
+	 * @throws InvalidKeyInArrayException
73
+	 * @return string
74
+	 */
75
+	public function getLabelField()
76
+	{
77
+		$labelField = $this->get('label');
78
+		if (empty($labelField)) {
79
+			throw new InvalidKeyInArrayException(sprintf('No label configured for table "%s"', $this->tableName), 1385586726);
80
+		}
81
+		return $labelField;
82
+	}
83
+
84
+	/**
85
+	 * Returns the translated label of the table name.
86
+	 *
87
+	 * @return string
88
+	 */
89
+	public function getLabel()
90
+	{
91
+		$label = '';
92
+		try {
93
+			$label = LocalizationUtility::translate($this->getLabelField(), '');
94
+		} catch (\InvalidArgumentException $e) {
95
+		}
96
+		if (empty($label)) {
97
+			$label = $this->getLabelField();
98
+		}
99
+		return $label;
100
+	}
101
+
102
+	/**
103
+	 * Returns the title of the table.
104
+	 *
105
+	 * @return string
106
+	 */
107
+	public function getTitle()
108
+	{
109
+		$title = '';
110
+		try {
111
+			$title = LocalizationUtility::translate((string)$this->get('title'), '');
112
+		} catch (\InvalidArgumentException $e) {
113
+		}
114
+		if (empty($title)) {
115
+			$title = $this->get('title');
116
+		}
117
+		return $title;
118
+	}
119
+
120
+	/**
121
+	 * Return the "disabled" field.
122
+	 *
123
+	 * @throws InvalidKeyInArrayException
124
+	 * @return string|null
125
+	 */
126
+	public function getHiddenField()
127
+	{
128
+		$hiddenField = null;
129
+		$enableColumns = $this->get('enablecolumns');
130
+		if (is_array($enableColumns) && !empty($enableColumns['disabled'])) {
131
+			$hiddenField = $enableColumns['disabled'];
132
+		}
133
+		return $hiddenField;
134
+	}
135
+
136
+	/**
137
+	 * Return the "starttime" field.
138
+	 *
139
+	 * @throws InvalidKeyInArrayException
140
+	 * @return string|null
141
+	 */
142
+	public function getStartTimeField()
143
+	{
144
+		$startTimeField = null;
145
+		$enableColumns = $this->get('enablecolumns');
146
+		if (is_array($enableColumns) && !empty($enableColumns['starttime'])) {
147
+			$startTimeField = $enableColumns['starttime'];
148
+		}
149
+		return $startTimeField;
150
+	}
151
+
152
+	/**
153
+	 * Return the "endtime" field.
154
+	 *
155
+	 * @throws InvalidKeyInArrayException
156
+	 * @return string|null
157
+	 */
158
+	public function getEndTimeField()
159
+	{
160
+		$endTimeField = null;
161
+		$enableColumns = $this->get('enablecolumns');
162
+		if (is_array($enableColumns) && !empty($enableColumns['endtime'])) {
163
+			$endTimeField = $enableColumns['endtime'];
164
+		}
165
+		return $endTimeField;
166
+	}
167
+
168
+	/**
169
+	 * Tells whether the table is hidden.
170
+	 *
171
+	 * @return bool
172
+	 */
173
+	public function isHidden()
174
+	{
175
+		return isset($this->tca['hideTable']) ? $this->tca['hideTable'] : false;
176
+	}
177
+
178
+	/**
179
+	 * Tells whether the table is not hidden.
180
+	 *
181
+	 * @return bool
182
+	 */
183
+	public function isNotHidden()
184
+	{
185
+		return !$this->isHidden();
186
+	}
187
+
188
+	/**
189
+	 * Get the "deleted" field for the table.
190
+	 *
191
+	 * @return string|null
192
+	 */
193
+	public function getDeletedField()
194
+	{
195
+		return $this->get('delete');
196
+	}
197
+
198
+	/**
199
+	 * Get the modification time stamp field.
200
+	 *
201
+	 * @return string|null
202
+	 */
203
+	public function getTimeModificationField()
204
+	{
205
+		return $this->get('tstamp');
206
+	}
207
+
208
+	/**
209
+	 * Get the creation time stamp field.
210
+	 *
211
+	 * @return string|null
212
+	 */
213
+	public function getTimeCreationField()
214
+	{
215
+		return $this->get('crdate');
216
+	}
217
+
218
+	/**
219
+	 * Get the language field for the table.
220
+	 *
221
+	 * @return string|null
222
+	 */
223
+	public function getLanguageField()
224
+	{
225
+		return $this->get('languageField');
226
+	}
227
+
228
+	/**
229
+	 * Get the field which points to the parent.
230
+	 *
231
+	 * @return string|null
232
+	 */
233
+	public function getLanguageParentField()
234
+	{
235
+		return $this->get('transOrigPointerField');
236
+	}
237
+
238
+	/**
239
+	 * Returns the default order in the form of a SQL segment.
240
+	 *
241
+	 * @return string|null
242
+	 */
243
+	public function getDefaultOrderSql()
244
+	{
245
+		// "sortby" typically has "sorting" as value.
246
+		$order = $this->get('sortby') ? $this->get('sortby') . ' ASC' : $this->get('default_sortby');
247
+		return $order;
248
+	}
249
+
250
+	/**
251
+	 * Returns the parsed default orderings.
252
+	 * Returns array looks like array('title' => 'ASC');
253
+	 *
254
+	 * @return array
255
+	 */
256
+	public function getDefaultOrderings()
257
+	{
258
+
259
+		// first clean up the sql segment
260
+		$defaultOrder = str_replace('ORDER BY', '', $this->getDefaultOrderSql());
261
+		$defaultOrderParts = GeneralUtility::trimExplode(',', $defaultOrder, true);
262
+
263
+		$orderings = [];
264
+		foreach ($defaultOrderParts as $defaultOrderPart) {
265
+			$parts = GeneralUtility::trimExplode(' ', $defaultOrderPart);
266
+			if (empty($parts[1])) {
267
+				$parts[1] = QueryInterface::ORDER_DESCENDING;
268
+			}
269
+			$orderings[$parts[0]] = $parts[1];
270
+		}
271
+
272
+		return $orderings;
273
+	}
274
+
275
+	/**
276
+	 * Returns the searchable fields.
277
+	 *
278
+	 * @return string|null
279
+	 */
280
+	public function getSearchFields()
281
+	{
282
+		return $this->get('searchFields');
283
+	}
284
+
285
+	/**
286
+	 * Returns an array containing the field names.
287
+	 *
288
+	 * @return array
289
+	 */
290
+	public function getFields()
291
+	{
292
+		return array_keys($this->columnTca);
293
+	}
294
+
295
+	/**
296
+	 * Returns an array containing the fields and their configuration.
297
+	 *
298
+	 * @return array
299
+	 */
300
+	public function getFieldsAndConfiguration()
301
+	{
302
+		return $this->columnTca;
303
+	}
304
+
305
+	/**
306
+	 * Tell whether we have a field "sorting".
307
+	 *
308
+	 * @return bool
309
+	 */
310
+	public function hasSortableField()
311
+	{
312
+		return $this->has('sortby');
313
+	}
314
+
315
+	/**
316
+	 * Tell whether the field exists or not.
317
+	 *
318
+	 * @param string $fieldName
319
+	 * @return bool
320
+	 */
321
+	public function hasField($fieldName)
322
+	{
323
+		if ($this->isComposite($fieldName)) {
324
+			$parts = explode('.', $fieldName);
325
+			list ($strippedFieldPath, $possibleTableName) = $parts;
326
+			$hasField = isset($this->columnTca[$strippedFieldPath], $GLOBALS['TCA'][$possibleTableName]);
327
+
328
+			// Continue checking that the $strippedFieldName is of type "group"
329
+			if (isset($GLOBALS['TCA'][$this->tableName]['columns'][$strippedFieldPath]) && count($parts) > 2) {
330
+				$hasField = Tca::table($this->tableName)->field($strippedFieldPath)->isGroup(); // Group
331
+			} elseif (isset($this->columnTca[$strippedFieldPath]['config']['readOnly']) && (bool)$this->columnTca[$strippedFieldPath]['config']['readOnly']) {
332
+				$hasField = false; // handle case metadata.fe_groups where "fe_groups" is a tableName.
333
+			}
334
+		} else {
335
+			$hasField = isset($this->columnTca[$fieldName]) || in_array($fieldName, Tca::getSystemFields(), true);
336
+		}
337
+		return $hasField;
338
+	}
339
+
340
+	/**
341
+	 * Tell whether the field name contains a path, e.g. metadata.title
342
+	 *
343
+	 * @param string $fieldName
344
+	 * @return boolean
345
+	 */
346
+	public function isComposite($fieldName)
347
+	{
348
+		return strpos($fieldName, '.') > 0;
349
+	}
350
+
351
+	/**
352
+	 * Tells whether the $key exists.
353
+	 *
354
+	 * @param string $key
355
+	 * @return string
356
+	 */
357
+	public function has($key)
358
+	{
359
+		return isset($this->tca[$key]);
360
+	}
361
+
362
+	/**
363
+	 * Tells whether the table name has "workspace" support.
364
+	 *
365
+	 * @return string
366
+	 */
367
+	public function hasWorkspaceSupport()
368
+	{
369
+		return isset($this->tca['versioningWS']);
370
+	}
371
+
372
+	/**
373
+	 * Tells whether the table name has "language" support.
374
+	 *
375
+	 * @return string
376
+	 */
377
+	public function hasLanguageSupport()
378
+	{
379
+		return isset($this->tca['languageField']);
380
+	}
381
+
382
+	/**
383
+	 * Return configuration value given a key.
384
+	 *
385
+	 * @param string $key
386
+	 * @return string|null
387
+	 */
388
+	public function get($key)
389
+	{
390
+		return $this->has($key) ? $this->tca[$key] : null;
391
+	}
392
+
393
+	/**
394
+	 * @return array
395
+	 */
396
+	public function getTca()
397
+	{
398
+		return $this->tca;
399
+	}
400
+
401
+	/**
402
+	 * Tell whether the current BE User has access to this field.
403
+	 *
404
+	 * @return bool
405
+	 */
406
+	public function hasAccess()
407
+	{
408
+		$hasAccess = true;
409
+		if ($this->isBackendMode()) {
410
+			$hasAccess = $this->getBackendUser()->check('tables_modify', $this->tableName);
411
+		}
412
+		return $hasAccess;
413
+	}
414
+
415
+	/**
416
+	 * @param string $fieldName
417
+	 * @throws \Exception
418
+	 * @return FieldService
419
+	 */
420
+	public function field($fieldName)
421
+	{
422
+
423
+		// In case field contains items.tx_table for field type "group"
424
+		$compositeField = '';
425
+		if (strpos($fieldName, '.') !== false) {
426
+			$compositeField = $fieldName;
427
+			$fieldParts = explode('.', $compositeField, 2);
428
+			$fieldName = $fieldParts[0];
429
+
430
+			// Special when field has been instantiated without the field name and path.
431
+			if (!empty($this->instances[$fieldName])) {
432
+				/** @var FieldService $field */
433
+				$field = $this->instances[$fieldName];
434
+				$field->setCompositeField($compositeField);
435
+			}
436
+		}
437
+
438
+		// True for system fields such as uid, pid that don't necessarily have a TCA.
439
+		if (empty($this->columnTca[$fieldName]) && in_array($fieldName, Tca::getSystemFields())) {
440
+			$this->columnTca[$fieldName] = [];
441
+		} elseif (empty($this->columnTca[$fieldName])) {
442
+			$message = sprintf(
443
+				'Does the field really exist? No TCA entry found for field "%s" for table "%s"',
444
+				$fieldName,
445
+				$this->tableName
446
+			);
447
+			throw new \Exception($message, 1385554481);
448
+		}
449
+
450
+
451
+		if (empty($this->instances[$fieldName])) {
452
+
453
+			$instance = GeneralUtility::makeInstance(
454
+				'Fab\Vidi\Tca\FieldService',
455
+				$fieldName,
456
+				$this->columnTca[$fieldName],
457
+				$this->tableName,
458
+				$compositeField
459
+			);
460
+
461
+			$this->instances[$fieldName] = $instance;
462
+		}
463
+		return $this->instances[$fieldName];
464
+	}
465 465
 
466 466
 }
Please login to merge, or discard this patch.
Classes/ViewHelpers/Grid/Column/ConfigurationViewHelper.php 2 patches
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -47,7 +47,7 @@
 block discarded – undo
47 47
             // -------------------
48 48
             // mData: internal name of DataTable plugin and can not contains a path, e.g. metadata.title
49 49
             // columnName: whole field name with path
50
-            $output .= sprintf('Vidi._columns.push({ "data": "%s", "sortable": %s, "visible": %s, "width": "%s", "class": "%s", "columnName": "%s" });' . PHP_EOL,
50
+            $output .= sprintf('Vidi._columns.push({ "data": "%s", "sortable": %s, "visible": %s, "width": "%s", "class": "%s", "columnName": "%s" });'.PHP_EOL,
51 51
                 $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath), // Suitable field name for the DataTable plugin.
52 52
                 Tca::grid()->isSortable($fieldNameAndPath) ? 'true' : 'false',
53 53
                 Tca::grid()->isVisible($fieldNameAndPath) ? 'true' : 'false',
Please login to merge, or discard this patch.
Indentation   +55 added lines, -55 removed lines patch added patch discarded remove patch
@@ -19,67 +19,67 @@
 block discarded – undo
19 19
 class ConfigurationViewHelper extends AbstractViewHelper
20 20
 {
21 21
 
22
-    /**
23
-     * Render the columns of the grid.
24
-     *
25
-     * @throws NotExistingFieldException
26
-     * @return string
27
-     */
28
-    public function render()
29
-    {
30
-        $output = '';
22
+	/**
23
+	 * Render the columns of the grid.
24
+	 *
25
+	 * @throws NotExistingFieldException
26
+	 * @return string
27
+	 */
28
+	public function render()
29
+	{
30
+		$output = '';
31 31
 
32
-        foreach (Tca::grid()->getFields() as $fieldNameAndPath => $configuration) {
32
+		foreach (Tca::grid()->getFields() as $fieldNameAndPath => $configuration) {
33 33
 
34
-            // Early failure if field does not exist.
35
-            if (!$this->isAllowed($fieldNameAndPath)) {
36
-                $message = sprintf('Property "%s" does not exist!', $fieldNameAndPath);
37
-                throw new NotExistingFieldException($message, 1375369594);
38
-            }
34
+			// Early failure if field does not exist.
35
+			if (!$this->isAllowed($fieldNameAndPath)) {
36
+				$message = sprintf('Property "%s" does not exist!', $fieldNameAndPath);
37
+				throw new NotExistingFieldException($message, 1375369594);
38
+			}
39 39
 
40
-            // mData vs columnName
41
-            // -------------------
42
-            // mData: internal name of DataTable plugin and can not contains a path, e.g. metadata.title
43
-            // columnName: whole field name with path
44
-            $output .= sprintf('Vidi._columns.push({ "data": "%s", "sortable": %s, "visible": %s, "width": "%s", "class": "%s", "columnName": "%s" });' . PHP_EOL,
45
-                $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath), // Suitable field name for the DataTable plugin.
46
-                Tca::grid()->isSortable($fieldNameAndPath) ? 'true' : 'false',
47
-                Tca::grid()->isVisible($fieldNameAndPath) ? 'true' : 'false',
48
-                Tca::grid()->getWidth($fieldNameAndPath),
49
-                Tca::grid()->getClass($fieldNameAndPath),
50
-                $fieldNameAndPath
51
-            );
52
-        }
40
+			// mData vs columnName
41
+			// -------------------
42
+			// mData: internal name of DataTable plugin and can not contains a path, e.g. metadata.title
43
+			// columnName: whole field name with path
44
+			$output .= sprintf('Vidi._columns.push({ "data": "%s", "sortable": %s, "visible": %s, "width": "%s", "class": "%s", "columnName": "%s" });' . PHP_EOL,
45
+				$this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath), // Suitable field name for the DataTable plugin.
46
+				Tca::grid()->isSortable($fieldNameAndPath) ? 'true' : 'false',
47
+				Tca::grid()->isVisible($fieldNameAndPath) ? 'true' : 'false',
48
+				Tca::grid()->getWidth($fieldNameAndPath),
49
+				Tca::grid()->getClass($fieldNameAndPath),
50
+				$fieldNameAndPath
51
+			);
52
+		}
53 53
 
54
-        return $output;
55
-    }
54
+		return $output;
55
+	}
56 56
 
57
-    /**
58
-     * Tell whether the field looks ok to be displayed within the Grid.
59
-     *
60
-     * @param string $fieldNameAndPath
61
-     * @return boolean
62
-     */
63
-    protected function isAllowed($fieldNameAndPath)
64
-    {
65
-        $dataType = $this->getFieldPathResolver()->getDataType($fieldNameAndPath);
66
-        $fieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath);
57
+	/**
58
+	 * Tell whether the field looks ok to be displayed within the Grid.
59
+	 *
60
+	 * @param string $fieldNameAndPath
61
+	 * @return boolean
62
+	 */
63
+	protected function isAllowed($fieldNameAndPath)
64
+	{
65
+		$dataType = $this->getFieldPathResolver()->getDataType($fieldNameAndPath);
66
+		$fieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath);
67 67
 
68
-        $isAllowed = false;
69
-        if (Tca::grid()->hasRenderers($fieldNameAndPath)) {
70
-            $isAllowed = true;
71
-        } elseif (Tca::table()->field($fieldNameAndPath)->isSystem() || Tca::table($dataType)->hasField($fieldName)) {
72
-            $isAllowed = true;
73
-        }
68
+		$isAllowed = false;
69
+		if (Tca::grid()->hasRenderers($fieldNameAndPath)) {
70
+			$isAllowed = true;
71
+		} elseif (Tca::table()->field($fieldNameAndPath)->isSystem() || Tca::table($dataType)->hasField($fieldName)) {
72
+			$isAllowed = true;
73
+		}
74 74
 
75
-        return $isAllowed;
76
-    }
75
+		return $isAllowed;
76
+	}
77 77
 
78
-    /**
79
-     * @return FieldPathResolver|object
80
-     */
81
-    protected function getFieldPathResolver()
82
-    {
83
-        return GeneralUtility::makeInstance(FieldPathResolver::class);
84
-    }
78
+	/**
79
+	 * @return FieldPathResolver|object
80
+	 */
81
+	protected function getFieldPathResolver()
82
+	{
83
+		return GeneralUtility::makeInstance(FieldPathResolver::class);
84
+	}
85 85
 }
Please login to merge, or discard this patch.
Classes/ViewHelpers/Content/AbstractContentViewHelper.php 2 patches
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -57,7 +57,7 @@
 block discarded – undo
57 57
     {
58 58
         $serializedMatches = serialize($matches);
59 59
         $serializedOrderings = serialize($orderings);
60
-        return md5($dataType . $serializedMatches . $serializedOrderings . $limit . $offset);
60
+        return md5($dataType.$serializedMatches.$serializedOrderings.$limit.$offset);
61 61
     }
62 62
 
63 63
     /**
Please login to merge, or discard this patch.
Indentation   +209 added lines, -209 removed lines patch added patch discarded remove patch
@@ -27,214 +27,214 @@
 block discarded – undo
27 27
 abstract class AbstractContentViewHelper extends AbstractViewHelper
28 28
 {
29 29
 
30
-    /**
31
-     * @return void
32
-     * @throws Exception
33
-     */
34
-    public function initializeArguments()
35
-    {
36
-        $this->registerArgument('type', 'string', 'Corresponds to the type of data to be fetched. It will basically be a table name e.g. fe_users.', false, '');
37
-        $this->registerArgument('matches', 'array', 'Key / value array to be used as filter. The key corresponds to a field name.', false, array());
38
-        $this->registerArgument('selection', 'int', 'A possible selection defined in the BE and stored in the database.', false, 0);
39
-        $this->registerArgument('ignoreEnableFields', 'bool', 'Whether to ignore enable fields or not (AKA hidden, deleted, starttime, ...).', false, false);
40
-        $this->registerArgument('aliases', 'array', 'Attribute "matches" does not support certain character such as "." in field name. Use this to create aliases.', false, array());
41
-    }
42
-
43
-    /**
44
-     * Generate a signature to be used for storing the result set.
45
-     *
46
-     * @param string $dataType
47
-     * @param array $matches
48
-     * @param array $orderings
49
-     * @param $limit
50
-     * @param $offset
51
-     * @return string
52
-     */
53
-    protected function getQuerySignature($dataType, array $matches, array $orderings, $limit, $offset)
54
-    {
55
-        $serializedMatches = serialize($matches);
56
-        $serializedOrderings = serialize($orderings);
57
-        return md5($dataType . $serializedMatches . $serializedOrderings . $limit . $offset);
58
-    }
59
-
60
-    /**
61
-     * Returns a matcher object.
62
-     *
63
-     * @param string $dataType
64
-     * @param array $matches
65
-     * @return Matcher
66
-     * @throws NotExistingClassException
67
-     * @throws \InvalidArgumentException
68
-     */
69
-    protected function getMatcher($dataType, $matches = array())
70
-    {
71
-
72
-        /** @var $matcher Matcher */
73
-        $matcher = GeneralUtility::makeInstance(Matcher::class, [], $dataType);
74
-
75
-        // @todo implement advanced selection parsing {or: {usergroup.title: {like: foo}}, {tstamp: {greaterThan: 1234}}}
76
-        foreach ($matches as $fieldNameAndPath => $value) {
77
-
78
-            // CSV values should be considered as "in" operator in Query, otherwise "equals".
79
-            $explodedValues = GeneralUtility::trimExplode(',', $value, true);
80
-
81
-            // The matching value contains a "1,2" as example
82
-            if (count($explodedValues) > 1) {
83
-
84
-                $resolvedDataType = $this->getFieldPathResolver()->getDataType($fieldNameAndPath, $dataType);
85
-                $resolvedFieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath, $dataType);
86
-
87
-                // "equals" if in presence of a relation.
88
-                // "in" if not a relation.
89
-                if (Tca::table($resolvedDataType)->field($resolvedFieldName)->hasRelation()) {
90
-                    foreach ($explodedValues as $explodedValue) {
91
-                        $matcher->equals($fieldNameAndPath, $explodedValue);
92
-                    }
93
-                } else {
94
-                    $matcher->in($fieldNameAndPath, $explodedValues);
95
-                }
96
-            } else {
97
-                $matcher->equals($fieldNameAndPath, $explodedValues[0]);
98
-            }
99
-        }
100
-
101
-        // Trigger signal for post processing Matcher Object.
102
-        $this->emitPostProcessMatcherObjectSignal($matcher->getDataType(), $matcher);
103
-
104
-        return $matcher;
105
-    }
106
-
107
-    /**
108
-     * Replace possible aliases.
109
-     *
110
-     * @param array $values
111
-     * @return array
112
-     */
113
-    protected function replacesAliases(array $values)
114
-    {
115
-
116
-        $aliases = $this->arguments['aliases'];
117
-
118
-        foreach ($aliases as $aliasName => $aliasValue) {
119
-            if (isset($values[$aliasName])) {
120
-                $values[$aliasValue] = $values[$aliasName];
121
-                unset($values[$aliasName]); // remove the alias.
122
-            }
123
-        }
124
-
125
-        return $values;
126
-    }
127
-
128
-    /**
129
-     * Returns an order object.
130
-     *
131
-     * @param string $dataType
132
-     * @param array $order
133
-     * @return Order
134
-     */
135
-    public function getOrder($dataType, array $order = array())
136
-    {
137
-        // Default orderings in case order is empty.
138
-        if (empty($order)) {
139
-            $order = Tca::table($dataType)->getDefaultOrderings();
140
-        }
141
-
142
-        $order = GeneralUtility::makeInstance(Order::class, $order);
143
-
144
-        // Trigger signal for post processing Order Object.
145
-        $this->emitPostProcessOrderObjectSignal($dataType, $order);
146
-
147
-        return $order;
148
-    }
149
-
150
-    /**
151
-     * @return ResultSetStorage
152
-     */
153
-    public function getResultSetStorage()
154
-    {
155
-        return GeneralUtility::makeInstance(ResultSetStorage::class);
156
-    }
157
-
158
-    /**
159
-     * Signal that is called for post-processing a "order" object.
160
-     *
161
-     * @param string $dataType
162
-     * @param Order $order
163
-     */
164
-    protected function emitPostProcessOrderObjectSignal($dataType, Order $order)
165
-    {
166
-        $this->getSignalSlotDispatcher()->dispatch('Fab\Vidi\ViewHelper\Content\AbstractContentViewHelper', 'postProcessOrderObject', array($order, $dataType));
167
-    }
168
-
169
-    /**
170
-     * Signal that is called for post-processing a "matcher" object.
171
-     *
172
-     * @param string $dataType
173
-     * @param Matcher $matcher
174
-     */
175
-    protected function emitPostProcessMatcherObjectSignal($dataType, Matcher $matcher)
176
-    {
177
-        $this->getSignalSlotDispatcher()->dispatch('Fab\Vidi\ViewHelper\Content\AbstractContentViewHelper', 'postProcessMatcherObject', array($matcher, $dataType));
178
-    }
179
-
180
-    /**
181
-     * Signal that is called for post-processing a "limit".
182
-     *
183
-     * @param string $dataType
184
-     * @param int $limit
185
-     */
186
-    protected function emitPostProcessLimitSignal($dataType, $limit)
187
-    {
188
-        $this->getSignalSlotDispatcher()->dispatch('Fab\Vidi\ViewHelper\Content\AbstractContentViewHelper', 'postProcessLimit', array($limit, $dataType));
189
-    }
190
-
191
-    /**
192
-     * Signal that is called for post-processing a "offset".
193
-     *
194
-     * @param string $dataType
195
-     * @param int $offset
196
-     */
197
-    protected function emitPostProcessOffsetSignal($dataType, $offset)
198
-    {
199
-        $this->getSignalSlotDispatcher()->dispatch('Fab\Vidi\ViewHelper\Content\AbstractContentViewHelper', 'postProcessLimit', array($offset, $dataType));
200
-    }
201
-
202
-    /**
203
-     * Get the SignalSlot dispatcher
204
-     *
205
-     * @return Dispatcher
206
-     */
207
-    protected function getSignalSlotDispatcher()
208
-    {
209
-        return $this->getObjectManager()->get(Dispatcher::class);
210
-    }
211
-
212
-    /**
213
-     * @return ObjectManager
214
-     */
215
-    protected function getObjectManager()
216
-    {
217
-        return GeneralUtility::makeInstance(ObjectManager::class);
218
-    }
219
-
220
-    /**
221
-     * @param $ignoreEnableFields
222
-     * @return QuerySettingsInterface
223
-     */
224
-    protected function getDefaultQuerySettings($ignoreEnableFields)
225
-    {
226
-        /** @var QuerySettings $defaultQuerySettings */
227
-        $defaultQuerySettings = GeneralUtility::makeInstance(QuerySettings::class);
228
-        $defaultQuerySettings->setIgnoreEnableFields($ignoreEnableFields);
229
-        return $defaultQuerySettings;
230
-    }
231
-
232
-    /**
233
-     * @return FieldPathResolver
234
-     */
235
-    protected function getFieldPathResolver()
236
-    {
237
-        return GeneralUtility::makeInstance(FieldPathResolver::class);
238
-    }
30
+	/**
31
+	 * @return void
32
+	 * @throws Exception
33
+	 */
34
+	public function initializeArguments()
35
+	{
36
+		$this->registerArgument('type', 'string', 'Corresponds to the type of data to be fetched. It will basically be a table name e.g. fe_users.', false, '');
37
+		$this->registerArgument('matches', 'array', 'Key / value array to be used as filter. The key corresponds to a field name.', false, array());
38
+		$this->registerArgument('selection', 'int', 'A possible selection defined in the BE and stored in the database.', false, 0);
39
+		$this->registerArgument('ignoreEnableFields', 'bool', 'Whether to ignore enable fields or not (AKA hidden, deleted, starttime, ...).', false, false);
40
+		$this->registerArgument('aliases', 'array', 'Attribute "matches" does not support certain character such as "." in field name. Use this to create aliases.', false, array());
41
+	}
42
+
43
+	/**
44
+	 * Generate a signature to be used for storing the result set.
45
+	 *
46
+	 * @param string $dataType
47
+	 * @param array $matches
48
+	 * @param array $orderings
49
+	 * @param $limit
50
+	 * @param $offset
51
+	 * @return string
52
+	 */
53
+	protected function getQuerySignature($dataType, array $matches, array $orderings, $limit, $offset)
54
+	{
55
+		$serializedMatches = serialize($matches);
56
+		$serializedOrderings = serialize($orderings);
57
+		return md5($dataType . $serializedMatches . $serializedOrderings . $limit . $offset);
58
+	}
59
+
60
+	/**
61
+	 * Returns a matcher object.
62
+	 *
63
+	 * @param string $dataType
64
+	 * @param array $matches
65
+	 * @return Matcher
66
+	 * @throws NotExistingClassException
67
+	 * @throws \InvalidArgumentException
68
+	 */
69
+	protected function getMatcher($dataType, $matches = array())
70
+	{
71
+
72
+		/** @var $matcher Matcher */
73
+		$matcher = GeneralUtility::makeInstance(Matcher::class, [], $dataType);
74
+
75
+		// @todo implement advanced selection parsing {or: {usergroup.title: {like: foo}}, {tstamp: {greaterThan: 1234}}}
76
+		foreach ($matches as $fieldNameAndPath => $value) {
77
+
78
+			// CSV values should be considered as "in" operator in Query, otherwise "equals".
79
+			$explodedValues = GeneralUtility::trimExplode(',', $value, true);
80
+
81
+			// The matching value contains a "1,2" as example
82
+			if (count($explodedValues) > 1) {
83
+
84
+				$resolvedDataType = $this->getFieldPathResolver()->getDataType($fieldNameAndPath, $dataType);
85
+				$resolvedFieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath, $dataType);
86
+
87
+				// "equals" if in presence of a relation.
88
+				// "in" if not a relation.
89
+				if (Tca::table($resolvedDataType)->field($resolvedFieldName)->hasRelation()) {
90
+					foreach ($explodedValues as $explodedValue) {
91
+						$matcher->equals($fieldNameAndPath, $explodedValue);
92
+					}
93
+				} else {
94
+					$matcher->in($fieldNameAndPath, $explodedValues);
95
+				}
96
+			} else {
97
+				$matcher->equals($fieldNameAndPath, $explodedValues[0]);
98
+			}
99
+		}
100
+
101
+		// Trigger signal for post processing Matcher Object.
102
+		$this->emitPostProcessMatcherObjectSignal($matcher->getDataType(), $matcher);
103
+
104
+		return $matcher;
105
+	}
106
+
107
+	/**
108
+	 * Replace possible aliases.
109
+	 *
110
+	 * @param array $values
111
+	 * @return array
112
+	 */
113
+	protected function replacesAliases(array $values)
114
+	{
115
+
116
+		$aliases = $this->arguments['aliases'];
117
+
118
+		foreach ($aliases as $aliasName => $aliasValue) {
119
+			if (isset($values[$aliasName])) {
120
+				$values[$aliasValue] = $values[$aliasName];
121
+				unset($values[$aliasName]); // remove the alias.
122
+			}
123
+		}
124
+
125
+		return $values;
126
+	}
127
+
128
+	/**
129
+	 * Returns an order object.
130
+	 *
131
+	 * @param string $dataType
132
+	 * @param array $order
133
+	 * @return Order
134
+	 */
135
+	public function getOrder($dataType, array $order = array())
136
+	{
137
+		// Default orderings in case order is empty.
138
+		if (empty($order)) {
139
+			$order = Tca::table($dataType)->getDefaultOrderings();
140
+		}
141
+
142
+		$order = GeneralUtility::makeInstance(Order::class, $order);
143
+
144
+		// Trigger signal for post processing Order Object.
145
+		$this->emitPostProcessOrderObjectSignal($dataType, $order);
146
+
147
+		return $order;
148
+	}
149
+
150
+	/**
151
+	 * @return ResultSetStorage
152
+	 */
153
+	public function getResultSetStorage()
154
+	{
155
+		return GeneralUtility::makeInstance(ResultSetStorage::class);
156
+	}
157
+
158
+	/**
159
+	 * Signal that is called for post-processing a "order" object.
160
+	 *
161
+	 * @param string $dataType
162
+	 * @param Order $order
163
+	 */
164
+	protected function emitPostProcessOrderObjectSignal($dataType, Order $order)
165
+	{
166
+		$this->getSignalSlotDispatcher()->dispatch('Fab\Vidi\ViewHelper\Content\AbstractContentViewHelper', 'postProcessOrderObject', array($order, $dataType));
167
+	}
168
+
169
+	/**
170
+	 * Signal that is called for post-processing a "matcher" object.
171
+	 *
172
+	 * @param string $dataType
173
+	 * @param Matcher $matcher
174
+	 */
175
+	protected function emitPostProcessMatcherObjectSignal($dataType, Matcher $matcher)
176
+	{
177
+		$this->getSignalSlotDispatcher()->dispatch('Fab\Vidi\ViewHelper\Content\AbstractContentViewHelper', 'postProcessMatcherObject', array($matcher, $dataType));
178
+	}
179
+
180
+	/**
181
+	 * Signal that is called for post-processing a "limit".
182
+	 *
183
+	 * @param string $dataType
184
+	 * @param int $limit
185
+	 */
186
+	protected function emitPostProcessLimitSignal($dataType, $limit)
187
+	{
188
+		$this->getSignalSlotDispatcher()->dispatch('Fab\Vidi\ViewHelper\Content\AbstractContentViewHelper', 'postProcessLimit', array($limit, $dataType));
189
+	}
190
+
191
+	/**
192
+	 * Signal that is called for post-processing a "offset".
193
+	 *
194
+	 * @param string $dataType
195
+	 * @param int $offset
196
+	 */
197
+	protected function emitPostProcessOffsetSignal($dataType, $offset)
198
+	{
199
+		$this->getSignalSlotDispatcher()->dispatch('Fab\Vidi\ViewHelper\Content\AbstractContentViewHelper', 'postProcessLimit', array($offset, $dataType));
200
+	}
201
+
202
+	/**
203
+	 * Get the SignalSlot dispatcher
204
+	 *
205
+	 * @return Dispatcher
206
+	 */
207
+	protected function getSignalSlotDispatcher()
208
+	{
209
+		return $this->getObjectManager()->get(Dispatcher::class);
210
+	}
211
+
212
+	/**
213
+	 * @return ObjectManager
214
+	 */
215
+	protected function getObjectManager()
216
+	{
217
+		return GeneralUtility::makeInstance(ObjectManager::class);
218
+	}
219
+
220
+	/**
221
+	 * @param $ignoreEnableFields
222
+	 * @return QuerySettingsInterface
223
+	 */
224
+	protected function getDefaultQuerySettings($ignoreEnableFields)
225
+	{
226
+		/** @var QuerySettings $defaultQuerySettings */
227
+		$defaultQuerySettings = GeneralUtility::makeInstance(QuerySettings::class);
228
+		$defaultQuerySettings->setIgnoreEnableFields($ignoreEnableFields);
229
+		return $defaultQuerySettings;
230
+	}
231
+
232
+	/**
233
+	 * @return FieldPathResolver
234
+	 */
235
+	protected function getFieldPathResolver()
236
+	{
237
+		return GeneralUtility::makeInstance(FieldPathResolver::class);
238
+	}
239 239
 
240 240
 }
Please login to merge, or discard this patch.