Completed
Push — master ( 5c161a...b70884 )
by Fabien
52:39
created
Classes/ViewHelpers/LanguagesViewHelper.php 1 patch
Indentation   +20 added lines, -20 removed lines patch added patch discarded remove patch
@@ -17,27 +17,27 @@
 block discarded – undo
17 17
  */
18 18
 class LanguagesViewHelper extends AbstractViewHelper
19 19
 {
20
-    /**
21
-     * Returns an array of available languages.
22
-     *
23
-     * @return array
24
-     */
25
-    public function render()
26
-    {
27
-        $languages[0] = $this->getLanguageService()->getDefaultFlag();
20
+	/**
21
+	 * Returns an array of available languages.
22
+	 *
23
+	 * @return array
24
+	 */
25
+	public function render()
26
+	{
27
+		$languages[0] = $this->getLanguageService()->getDefaultFlag();
28 28
 
29
-        foreach ($this->getLanguageService()->getLanguages() as $language) {
30
-            $languages[$language['uid']] = $language['flag'];
31
-        }
29
+		foreach ($this->getLanguageService()->getLanguages() as $language) {
30
+			$languages[$language['uid']] = $language['flag'];
31
+		}
32 32
 
33
-        return $languages;
34
-    }
33
+		return $languages;
34
+	}
35 35
 
36
-    /**
37
-     * @return LanguageService|object
38
-     */
39
-    protected function getLanguageService()
40
-    {
41
-        return GeneralUtility::makeInstance(LanguageService::class);
42
-    }
36
+	/**
37
+	 * @return LanguageService|object
38
+	 */
39
+	protected function getLanguageService()
40
+	{
41
+		return GeneralUtility::makeInstance(LanguageService::class);
42
+	}
43 43
 }
Please login to merge, or discard this patch.
Classes/ViewHelpers/IsRelatedToViewHelper.php 1 patch
Indentation   +42 added lines, -42 removed lines patch added patch discarded remove patch
@@ -18,46 +18,46 @@
 block discarded – undo
18 18
  */
19 19
 class IsRelatedToViewHelper extends AbstractViewHelper
20 20
 {
21
-    /**
22
-     * @return void
23
-     */
24
-    public function initializeArguments()
25
-    {
26
-        $this->registerArgument('relatedContent', Content::class, 'The related content', true);
27
-    }
28
-
29
-    /**
30
-     * Tells whether a Content is related to another content.
31
-     * The $fieldName corresponds to the relational field name
32
-     * between the first content object and the second.
33
-     *
34
-     * @return boolean
35
-     */
36
-    public function render()
37
-    {
38
-        /** @var Content $relatedContent */
39
-        $relatedContent = $this->arguments['relatedContent'];
40
-
41
-        $isChecked = false;
42
-
43
-        // Only computes whether the object is checked if one row is beeing edited.
44
-        $numberOfObjects = $this->templateVariableContainer->get('numberOfObjects');
45
-        if ($numberOfObjects === 1) {
46
-            /** @var Content $content */
47
-            $content = $this->templateVariableContainer->get('content');
48
-            $fieldName = $this->templateVariableContainer->get('fieldName');
49
-
50
-            // Build an array of user group uids
51
-            $relatedContentsIdentifiers = [];
52
-
53
-            /** @var Content $contentObject */
54
-            foreach ($content[$fieldName] as $contentObject) {
55
-                $relatedContentsIdentifiers[] = $contentObject->getUid();
56
-            }
57
-
58
-            $isChecked = in_array($relatedContent->getUid(), $relatedContentsIdentifiers, true);
59
-        }
60
-
61
-        return $isChecked;
62
-    }
21
+	/**
22
+	 * @return void
23
+	 */
24
+	public function initializeArguments()
25
+	{
26
+		$this->registerArgument('relatedContent', Content::class, 'The related content', true);
27
+	}
28
+
29
+	/**
30
+	 * Tells whether a Content is related to another content.
31
+	 * The $fieldName corresponds to the relational field name
32
+	 * between the first content object and the second.
33
+	 *
34
+	 * @return boolean
35
+	 */
36
+	public function render()
37
+	{
38
+		/** @var Content $relatedContent */
39
+		$relatedContent = $this->arguments['relatedContent'];
40
+
41
+		$isChecked = false;
42
+
43
+		// Only computes whether the object is checked if one row is beeing edited.
44
+		$numberOfObjects = $this->templateVariableContainer->get('numberOfObjects');
45
+		if ($numberOfObjects === 1) {
46
+			/** @var Content $content */
47
+			$content = $this->templateVariableContainer->get('content');
48
+			$fieldName = $this->templateVariableContainer->get('fieldName');
49
+
50
+			// Build an array of user group uids
51
+			$relatedContentsIdentifiers = [];
52
+
53
+			/** @var Content $contentObject */
54
+			foreach ($content[$fieldName] as $contentObject) {
55
+				$relatedContentsIdentifiers[] = $contentObject->getUid();
56
+			}
57
+
58
+			$isChecked = in_array($relatedContent->getUid(), $relatedContentsIdentifiers, true);
59
+		}
60
+
61
+		return $isChecked;
62
+	}
63 63
 }
Please login to merge, or discard this patch.
Classes/ViewHelpers/Content/AbstractContentViewHelper.php 1 patch
Indentation   +197 added lines, -197 removed lines patch added patch discarded remove patch
@@ -27,201 +27,201 @@
 block discarded – undo
27 27
  */
28 28
 abstract class AbstractContentViewHelper extends AbstractViewHelper
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
-        /** @var $matcher Matcher */
72
-        $matcher = GeneralUtility::makeInstance(Matcher::class, [], $dataType);
73
-
74
-        // @todo implement advanced selection parsing {or: {usergroup.title: {like: foo}}, {tstamp: {greaterThan: 1234}}}
75
-        foreach ($matches as $fieldNameAndPath => $value) {
76
-            // CSV values should be considered as "in" operator in Query, otherwise "equals".
77
-            $explodedValues = GeneralUtility::trimExplode(',', $value, true);
78
-
79
-            // The matching value contains a "1,2" as example
80
-            if (count($explodedValues) > 1) {
81
-                $resolvedDataType = $this->getFieldPathResolver()->getDataType($fieldNameAndPath, $dataType);
82
-                $resolvedFieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath, $dataType);
83
-
84
-                // "equals" if in presence of a relation.
85
-                // "in" if not a relation.
86
-                if (Tca::table($resolvedDataType)->field($resolvedFieldName)->hasRelation()) {
87
-                    foreach ($explodedValues as $explodedValue) {
88
-                        $matcher->equals($fieldNameAndPath, $explodedValue);
89
-                    }
90
-                } else {
91
-                    $matcher->in($fieldNameAndPath, $explodedValues);
92
-                }
93
-            } else {
94
-                $matcher->equals($fieldNameAndPath, $explodedValues[0]);
95
-            }
96
-        }
97
-
98
-        // Trigger signal for post processing Matcher Object.
99
-        $this->emitPostProcessMatcherObjectSignal($matcher->getDataType(), $matcher);
100
-
101
-        return $matcher;
102
-    }
103
-
104
-    /**
105
-     * Replace possible aliases.
106
-     *
107
-     * @param array $values
108
-     * @return array
109
-     */
110
-    protected function replacesAliases(array $values)
111
-    {
112
-        $aliases = $this->arguments['aliases'];
113
-
114
-        foreach ($aliases as $aliasName => $aliasValue) {
115
-            if (isset($values[$aliasName])) {
116
-                $values[$aliasValue] = $values[$aliasName];
117
-                unset($values[$aliasName]); // remove the alias.
118
-            }
119
-        }
120
-
121
-        return $values;
122
-    }
123
-
124
-    /**
125
-     * Returns an order object.
126
-     *
127
-     * @param string $dataType
128
-     * @param array $order
129
-     * @return Order
130
-     */
131
-    public function getOrder($dataType, array $order = array())
132
-    {
133
-        // Default orderings in case order is empty.
134
-        if (empty($order)) {
135
-            $order = Tca::table($dataType)->getDefaultOrderings();
136
-        }
137
-
138
-        $order = GeneralUtility::makeInstance(Order::class, $order);
139
-
140
-        // Trigger signal for post processing Order Object.
141
-        $this->emitPostProcessOrderObjectSignal($dataType, $order);
142
-
143
-        return $order;
144
-    }
145
-
146
-    /**
147
-     * @return ResultSetStorage
148
-     */
149
-    public function getResultSetStorage()
150
-    {
151
-        return GeneralUtility::makeInstance(ResultSetStorage::class);
152
-    }
153
-
154
-    /**
155
-     * Signal that is called for post-processing a "order" object.
156
-     *
157
-     * @param string $dataType
158
-     * @param Order $order
159
-     */
160
-    protected function emitPostProcessOrderObjectSignal($dataType, Order $order)
161
-    {
162
-        $this->getSignalSlotDispatcher()->dispatch('Fab\Vidi\ViewHelper\Content\AbstractContentViewHelper', 'postProcessOrderObject', array($order, $dataType));
163
-    }
164
-
165
-    /**
166
-     * Signal that is called for post-processing a "matcher" object.
167
-     *
168
-     * @param string $dataType
169
-     * @param Matcher $matcher
170
-     */
171
-    protected function emitPostProcessMatcherObjectSignal($dataType, Matcher $matcher)
172
-    {
173
-        $this->getSignalSlotDispatcher()->dispatch('Fab\Vidi\ViewHelper\Content\AbstractContentViewHelper', 'postProcessMatcherObject', array($matcher, $dataType));
174
-    }
175
-
176
-    /**
177
-     * Signal that is called for post-processing a "limit".
178
-     *
179
-     * @param string $dataType
180
-     * @param int $limit
181
-     */
182
-    protected function emitPostProcessLimitSignal($dataType, $limit)
183
-    {
184
-        $this->getSignalSlotDispatcher()->dispatch('Fab\Vidi\ViewHelper\Content\AbstractContentViewHelper', 'postProcessLimit', array($limit, $dataType));
185
-    }
186
-
187
-    /**
188
-     * Signal that is called for post-processing a "offset".
189
-     *
190
-     * @param string $dataType
191
-     * @param int $offset
192
-     */
193
-    protected function emitPostProcessOffsetSignal($dataType, $offset)
194
-    {
195
-        $this->getSignalSlotDispatcher()->dispatch('Fab\Vidi\ViewHelper\Content\AbstractContentViewHelper', 'postProcessLimit', array($offset, $dataType));
196
-    }
197
-
198
-    /**
199
-     * Get the SignalSlot dispatcher
200
-     *
201
-     * @return Dispatcher
202
-     */
203
-    protected function getSignalSlotDispatcher()
204
-    {
205
-        return GeneralUtility::makeInstance(Dispatcher::class);
206
-    }
207
-
208
-    /**
209
-     * @param $ignoreEnableFields
210
-     * @return QuerySettingsInterface
211
-     */
212
-    protected function getDefaultQuerySettings($ignoreEnableFields)
213
-    {
214
-        /** @var Typo3QuerySettings $defaultQuerySettings */
215
-        $defaultQuerySettings = GeneralUtility::makeInstance(Typo3QuerySettings::class);
216
-        $defaultQuerySettings->setIgnoreEnableFields($ignoreEnableFields);
217
-        return $defaultQuerySettings;
218
-    }
219
-
220
-    /**
221
-     * @return FieldPathResolver
222
-     */
223
-    protected function getFieldPathResolver()
224
-    {
225
-        return GeneralUtility::makeInstance(FieldPathResolver::class);
226
-    }
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
+		/** @var $matcher Matcher */
72
+		$matcher = GeneralUtility::makeInstance(Matcher::class, [], $dataType);
73
+
74
+		// @todo implement advanced selection parsing {or: {usergroup.title: {like: foo}}, {tstamp: {greaterThan: 1234}}}
75
+		foreach ($matches as $fieldNameAndPath => $value) {
76
+			// CSV values should be considered as "in" operator in Query, otherwise "equals".
77
+			$explodedValues = GeneralUtility::trimExplode(',', $value, true);
78
+
79
+			// The matching value contains a "1,2" as example
80
+			if (count($explodedValues) > 1) {
81
+				$resolvedDataType = $this->getFieldPathResolver()->getDataType($fieldNameAndPath, $dataType);
82
+				$resolvedFieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath, $dataType);
83
+
84
+				// "equals" if in presence of a relation.
85
+				// "in" if not a relation.
86
+				if (Tca::table($resolvedDataType)->field($resolvedFieldName)->hasRelation()) {
87
+					foreach ($explodedValues as $explodedValue) {
88
+						$matcher->equals($fieldNameAndPath, $explodedValue);
89
+					}
90
+				} else {
91
+					$matcher->in($fieldNameAndPath, $explodedValues);
92
+				}
93
+			} else {
94
+				$matcher->equals($fieldNameAndPath, $explodedValues[0]);
95
+			}
96
+		}
97
+
98
+		// Trigger signal for post processing Matcher Object.
99
+		$this->emitPostProcessMatcherObjectSignal($matcher->getDataType(), $matcher);
100
+
101
+		return $matcher;
102
+	}
103
+
104
+	/**
105
+	 * Replace possible aliases.
106
+	 *
107
+	 * @param array $values
108
+	 * @return array
109
+	 */
110
+	protected function replacesAliases(array $values)
111
+	{
112
+		$aliases = $this->arguments['aliases'];
113
+
114
+		foreach ($aliases as $aliasName => $aliasValue) {
115
+			if (isset($values[$aliasName])) {
116
+				$values[$aliasValue] = $values[$aliasName];
117
+				unset($values[$aliasName]); // remove the alias.
118
+			}
119
+		}
120
+
121
+		return $values;
122
+	}
123
+
124
+	/**
125
+	 * Returns an order object.
126
+	 *
127
+	 * @param string $dataType
128
+	 * @param array $order
129
+	 * @return Order
130
+	 */
131
+	public function getOrder($dataType, array $order = array())
132
+	{
133
+		// Default orderings in case order is empty.
134
+		if (empty($order)) {
135
+			$order = Tca::table($dataType)->getDefaultOrderings();
136
+		}
137
+
138
+		$order = GeneralUtility::makeInstance(Order::class, $order);
139
+
140
+		// Trigger signal for post processing Order Object.
141
+		$this->emitPostProcessOrderObjectSignal($dataType, $order);
142
+
143
+		return $order;
144
+	}
145
+
146
+	/**
147
+	 * @return ResultSetStorage
148
+	 */
149
+	public function getResultSetStorage()
150
+	{
151
+		return GeneralUtility::makeInstance(ResultSetStorage::class);
152
+	}
153
+
154
+	/**
155
+	 * Signal that is called for post-processing a "order" object.
156
+	 *
157
+	 * @param string $dataType
158
+	 * @param Order $order
159
+	 */
160
+	protected function emitPostProcessOrderObjectSignal($dataType, Order $order)
161
+	{
162
+		$this->getSignalSlotDispatcher()->dispatch('Fab\Vidi\ViewHelper\Content\AbstractContentViewHelper', 'postProcessOrderObject', array($order, $dataType));
163
+	}
164
+
165
+	/**
166
+	 * Signal that is called for post-processing a "matcher" object.
167
+	 *
168
+	 * @param string $dataType
169
+	 * @param Matcher $matcher
170
+	 */
171
+	protected function emitPostProcessMatcherObjectSignal($dataType, Matcher $matcher)
172
+	{
173
+		$this->getSignalSlotDispatcher()->dispatch('Fab\Vidi\ViewHelper\Content\AbstractContentViewHelper', 'postProcessMatcherObject', array($matcher, $dataType));
174
+	}
175
+
176
+	/**
177
+	 * Signal that is called for post-processing a "limit".
178
+	 *
179
+	 * @param string $dataType
180
+	 * @param int $limit
181
+	 */
182
+	protected function emitPostProcessLimitSignal($dataType, $limit)
183
+	{
184
+		$this->getSignalSlotDispatcher()->dispatch('Fab\Vidi\ViewHelper\Content\AbstractContentViewHelper', 'postProcessLimit', array($limit, $dataType));
185
+	}
186
+
187
+	/**
188
+	 * Signal that is called for post-processing a "offset".
189
+	 *
190
+	 * @param string $dataType
191
+	 * @param int $offset
192
+	 */
193
+	protected function emitPostProcessOffsetSignal($dataType, $offset)
194
+	{
195
+		$this->getSignalSlotDispatcher()->dispatch('Fab\Vidi\ViewHelper\Content\AbstractContentViewHelper', 'postProcessLimit', array($offset, $dataType));
196
+	}
197
+
198
+	/**
199
+	 * Get the SignalSlot dispatcher
200
+	 *
201
+	 * @return Dispatcher
202
+	 */
203
+	protected function getSignalSlotDispatcher()
204
+	{
205
+		return GeneralUtility::makeInstance(Dispatcher::class);
206
+	}
207
+
208
+	/**
209
+	 * @param $ignoreEnableFields
210
+	 * @return QuerySettingsInterface
211
+	 */
212
+	protected function getDefaultQuerySettings($ignoreEnableFields)
213
+	{
214
+		/** @var Typo3QuerySettings $defaultQuerySettings */
215
+		$defaultQuerySettings = GeneralUtility::makeInstance(Typo3QuerySettings::class);
216
+		$defaultQuerySettings->setIgnoreEnableFields($ignoreEnableFields);
217
+		return $defaultQuerySettings;
218
+	}
219
+
220
+	/**
221
+	 * @return FieldPathResolver
222
+	 */
223
+	protected function getFieldPathResolver()
224
+	{
225
+		return GeneralUtility::makeInstance(FieldPathResolver::class);
226
+	}
227 227
 }
Please login to merge, or discard this patch.
Classes/ViewHelpers/Content/FindOneViewHelper.php 1 patch
Indentation   +153 added lines, -153 removed lines patch added patch discarded remove patch
@@ -22,157 +22,157 @@
 block discarded – undo
22 22
  */
23 23
 class FindOneViewHelper extends AbstractViewHelper
24 24
 {
25
-    /**
26
-     * @return void
27
-     */
28
-    public function initializeArguments()
29
-    {
30
-        parent::initializeArguments();
31
-
32
-        $this->registerArgument('type', 'string', 'The content type', true, '');
33
-        $this->registerArgument('matches', 'array', 'Key / value array to be used as filter. The key corresponds to a field name.', false, []);
34
-        $this->registerArgument('identifier', 'int', 'The identifier of the object to be fetched.', false, 0);
35
-        $this->registerArgument('argumentName', 'string', 'The parameter name where to retrieve the identifier', false, 'tx_vidifrontend_pi1|uid');
36
-        $this->registerArgument('as', 'string', 'The alias object', false, 'object');
37
-    }
38
-
39
-    /**
40
-     * @return string Rendered string
41
-     * @api
42
-     */
43
-    public function render()
44
-    {
45
-        return static::renderStatic(
46
-            $this->arguments,
47
-            $this->buildRenderChildrenClosure(),
48
-            $this->renderingContext
49
-        );
50
-    }
51
-
52
-    /**
53
-     * @param array $arguments
54
-     * @param \Closure $renderChildrenClosure
55
-     * @param RenderingContextInterface $renderingContext
56
-     *
57
-     * @return string
58
-     */
59
-    public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext)
60
-    {
61
-        // Fetch the object
62
-        $matches = self::computeMatches($arguments);
63
-        $matcher = self::getMatcher($arguments['type'], $matches);
64
-
65
-        $contentRepository = ContentRepositoryFactory::getInstance($arguments['type']);
66
-        $object = $contentRepository->findOneBy($matcher);
67
-
68
-        $output = '';
69
-        if ($object) {
70
-            // Render children with "as" variable.
71
-            $templateVariableContainer = $renderingContext->getTemplateVariableContainer();
72
-            $templateVariableContainer->add($arguments['as'], $object);
73
-            $output = $renderChildrenClosure();
74
-            $templateVariableContainer->remove($arguments['as']);
75
-        }
76
-
77
-        return $output;
78
-    }
79
-
80
-    /**
81
-     * @param array $arguments
82
-     * @return array
83
-     */
84
-    protected static function computeMatches(array $arguments)
85
-    {
86
-        $matches = [];
87
-
88
-        $argumentValue = self::getArgumentValue($arguments['argumentName']);
89
-        if ($argumentValue > 0) {
90
-            $matches['uid'] = $argumentValue;
91
-        }
92
-
93
-        if ($arguments['matches']) {
94
-            $matches = $arguments['matches'];
95
-        }
96
-
97
-        if ($arguments['identifier'] > 0) {
98
-            $matches['uid'] = $arguments['identifier'];
99
-        }
100
-
101
-        // We want a default value in any case.
102
-        if (!$matches) {
103
-            $matches['uid'] = 0;
104
-        }
105
-        return $matches;
106
-    }
107
-
108
-    /**
109
-     * Returns a matcher object.
110
-     *
111
-     * @param string $dataType
112
-     * @param array $matches
113
-     * @return Matcher
114
-     */
115
-    protected static function getMatcher($dataType, array $matches = [])
116
-    {
117
-        /** @var $matcher Matcher */
118
-        $matcher = GeneralUtility::makeInstance(Matcher::class, [], $dataType);
119
-
120
-        foreach ($matches as $fieldNameAndPath => $value) {
121
-            // CSV values should be considered as "in" operator in Query, otherwise "equals".
122
-            $explodedValues = GeneralUtility::trimExplode(',', $value, true);
123
-
124
-            // The matching value contains a "1,2" as example
125
-            if (count($explodedValues) > 1) {
126
-                $resolvedDataType = self::getFieldPathResolver()->getDataType($fieldNameAndPath, $dataType);
127
-                $resolvedFieldName = self::getFieldPathResolver()->stripFieldPath($fieldNameAndPath, $dataType);
128
-
129
-                // "equals" if in presence of a relation.
130
-                // "in" if not a relation.
131
-                if (Tca::table($resolvedDataType)->field($resolvedFieldName)->hasRelation()) {
132
-                    foreach ($explodedValues as $explodedValue) {
133
-                        $matcher->equals($fieldNameAndPath, $explodedValue);
134
-                    }
135
-                } else {
136
-                    $matcher->in($fieldNameAndPath, $explodedValues);
137
-                }
138
-            } else {
139
-                $matcher->equals($fieldNameAndPath, $explodedValues[0]);
140
-            }
141
-        }
142
-
143
-        return $matcher;
144
-    }
145
-
146
-    /**
147
-     * @return FieldPathResolver
148
-     */
149
-    protected static function getFieldPathResolver()
150
-    {
151
-        return GeneralUtility::makeInstance(FieldPathResolver::class);
152
-    }
153
-
154
-    /**
155
-     * @param string $argumentName
156
-     * @return int
157
-     */
158
-    protected static function getArgumentValue($argumentName)
159
-    {
160
-        $value = ''; // default value
161
-
162
-        // Merge parameters
163
-        $parameters = GeneralUtility::_GET();
164
-        $post = GeneralUtility::_POST();
165
-        ArrayUtility::mergeRecursiveWithOverrule($parameters, $post);
166
-
167
-        // Traverse argument parts and retrieve value.
168
-        $argumentParts = GeneralUtility::trimExplode('|', $argumentName);
169
-        foreach ($argumentParts as $argumentPart) {
170
-            if (isset($parameters[$argumentPart])) {
171
-                $value = $parameters[$argumentPart];
172
-                $parameters = $value;
173
-            }
174
-        }
175
-
176
-        return (int)$value;
177
-    }
25
+	/**
26
+	 * @return void
27
+	 */
28
+	public function initializeArguments()
29
+	{
30
+		parent::initializeArguments();
31
+
32
+		$this->registerArgument('type', 'string', 'The content type', true, '');
33
+		$this->registerArgument('matches', 'array', 'Key / value array to be used as filter. The key corresponds to a field name.', false, []);
34
+		$this->registerArgument('identifier', 'int', 'The identifier of the object to be fetched.', false, 0);
35
+		$this->registerArgument('argumentName', 'string', 'The parameter name where to retrieve the identifier', false, 'tx_vidifrontend_pi1|uid');
36
+		$this->registerArgument('as', 'string', 'The alias object', false, 'object');
37
+	}
38
+
39
+	/**
40
+	 * @return string Rendered string
41
+	 * @api
42
+	 */
43
+	public function render()
44
+	{
45
+		return static::renderStatic(
46
+			$this->arguments,
47
+			$this->buildRenderChildrenClosure(),
48
+			$this->renderingContext
49
+		);
50
+	}
51
+
52
+	/**
53
+	 * @param array $arguments
54
+	 * @param \Closure $renderChildrenClosure
55
+	 * @param RenderingContextInterface $renderingContext
56
+	 *
57
+	 * @return string
58
+	 */
59
+	public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext)
60
+	{
61
+		// Fetch the object
62
+		$matches = self::computeMatches($arguments);
63
+		$matcher = self::getMatcher($arguments['type'], $matches);
64
+
65
+		$contentRepository = ContentRepositoryFactory::getInstance($arguments['type']);
66
+		$object = $contentRepository->findOneBy($matcher);
67
+
68
+		$output = '';
69
+		if ($object) {
70
+			// Render children with "as" variable.
71
+			$templateVariableContainer = $renderingContext->getTemplateVariableContainer();
72
+			$templateVariableContainer->add($arguments['as'], $object);
73
+			$output = $renderChildrenClosure();
74
+			$templateVariableContainer->remove($arguments['as']);
75
+		}
76
+
77
+		return $output;
78
+	}
79
+
80
+	/**
81
+	 * @param array $arguments
82
+	 * @return array
83
+	 */
84
+	protected static function computeMatches(array $arguments)
85
+	{
86
+		$matches = [];
87
+
88
+		$argumentValue = self::getArgumentValue($arguments['argumentName']);
89
+		if ($argumentValue > 0) {
90
+			$matches['uid'] = $argumentValue;
91
+		}
92
+
93
+		if ($arguments['matches']) {
94
+			$matches = $arguments['matches'];
95
+		}
96
+
97
+		if ($arguments['identifier'] > 0) {
98
+			$matches['uid'] = $arguments['identifier'];
99
+		}
100
+
101
+		// We want a default value in any case.
102
+		if (!$matches) {
103
+			$matches['uid'] = 0;
104
+		}
105
+		return $matches;
106
+	}
107
+
108
+	/**
109
+	 * Returns a matcher object.
110
+	 *
111
+	 * @param string $dataType
112
+	 * @param array $matches
113
+	 * @return Matcher
114
+	 */
115
+	protected static function getMatcher($dataType, array $matches = [])
116
+	{
117
+		/** @var $matcher Matcher */
118
+		$matcher = GeneralUtility::makeInstance(Matcher::class, [], $dataType);
119
+
120
+		foreach ($matches as $fieldNameAndPath => $value) {
121
+			// CSV values should be considered as "in" operator in Query, otherwise "equals".
122
+			$explodedValues = GeneralUtility::trimExplode(',', $value, true);
123
+
124
+			// The matching value contains a "1,2" as example
125
+			if (count($explodedValues) > 1) {
126
+				$resolvedDataType = self::getFieldPathResolver()->getDataType($fieldNameAndPath, $dataType);
127
+				$resolvedFieldName = self::getFieldPathResolver()->stripFieldPath($fieldNameAndPath, $dataType);
128
+
129
+				// "equals" if in presence of a relation.
130
+				// "in" if not a relation.
131
+				if (Tca::table($resolvedDataType)->field($resolvedFieldName)->hasRelation()) {
132
+					foreach ($explodedValues as $explodedValue) {
133
+						$matcher->equals($fieldNameAndPath, $explodedValue);
134
+					}
135
+				} else {
136
+					$matcher->in($fieldNameAndPath, $explodedValues);
137
+				}
138
+			} else {
139
+				$matcher->equals($fieldNameAndPath, $explodedValues[0]);
140
+			}
141
+		}
142
+
143
+		return $matcher;
144
+	}
145
+
146
+	/**
147
+	 * @return FieldPathResolver
148
+	 */
149
+	protected static function getFieldPathResolver()
150
+	{
151
+		return GeneralUtility::makeInstance(FieldPathResolver::class);
152
+	}
153
+
154
+	/**
155
+	 * @param string $argumentName
156
+	 * @return int
157
+	 */
158
+	protected static function getArgumentValue($argumentName)
159
+	{
160
+		$value = ''; // default value
161
+
162
+		// Merge parameters
163
+		$parameters = GeneralUtility::_GET();
164
+		$post = GeneralUtility::_POST();
165
+		ArrayUtility::mergeRecursiveWithOverrule($parameters, $post);
166
+
167
+		// Traverse argument parts and retrieve value.
168
+		$argumentParts = GeneralUtility::trimExplode('|', $argumentName);
169
+		foreach ($argumentParts as $argumentPart) {
170
+			if (isset($parameters[$argumentPart])) {
171
+				$value = $parameters[$argumentPart];
172
+				$parameters = $value;
173
+			}
174
+		}
175
+
176
+		return (int)$value;
177
+	}
178 178
 }
Please login to merge, or discard this patch.
Classes/ViewHelpers/Content/CountViewHelper.php 1 patch
Indentation   +20 added lines, -20 removed lines patch added patch discarded remove patch
@@ -16,27 +16,27 @@
 block discarded – undo
16 16
  */
17 17
 class CountViewHelper extends AbstractContentViewHelper
18 18
 {
19
-    /**
20
-     * Count a result set.
21
-     *
22
-     * @return int
23
-     */
24
-    public function render()
25
-    {
26
-        if (!empty($this->arguments['dataType'])) {
27
-            print 'Sorry to be so rude! There is something to change in the View Helper "v:find". Please replace attribute "dataType" by "type". This is a shorter syntax...';
28
-            exit();
29
-        }
30
-        $dataType = $this->arguments['type'];
31
-        $matches = $this->replacesAliases($this->arguments['matches']);
32
-        $ignoreEnableFields = $this->arguments['ignoreEnableFields'];
19
+	/**
20
+	 * Count a result set.
21
+	 *
22
+	 * @return int
23
+	 */
24
+	public function render()
25
+	{
26
+		if (!empty($this->arguments['dataType'])) {
27
+			print 'Sorry to be so rude! There is something to change in the View Helper "v:find". Please replace attribute "dataType" by "type". This is a shorter syntax...';
28
+			exit();
29
+		}
30
+		$dataType = $this->arguments['type'];
31
+		$matches = $this->replacesAliases($this->arguments['matches']);
32
+		$ignoreEnableFields = $this->arguments['ignoreEnableFields'];
33 33
 
34
-        $matcher = $this->getMatcher($dataType, $matches);
34
+		$matcher = $this->getMatcher($dataType, $matches);
35 35
 
36
-        $contentRepository = ContentRepositoryFactory::getInstance($dataType);
37
-        $contentRepository->setDefaultQuerySettings($this->getDefaultQuerySettings($ignoreEnableFields));
36
+		$contentRepository = ContentRepositoryFactory::getInstance($dataType);
37
+		$contentRepository->setDefaultQuerySettings($this->getDefaultQuerySettings($ignoreEnableFields));
38 38
 
39
-        $numberOfObjects = ContentRepositoryFactory::getInstance($dataType)->countBy($matcher);
40
-        return $numberOfObjects;
41
-    }
39
+		$numberOfObjects = ContentRepositoryFactory::getInstance($dataType)->countBy($matcher);
40
+		return $numberOfObjects;
41
+	}
42 42
 }
Please login to merge, or discard this patch.
Classes/ViewHelpers/Content/FindViewHelper.php 1 patch
Indentation   +53 added lines, -53 removed lines patch added patch discarded remove patch
@@ -19,68 +19,68 @@
 block discarded – undo
19 19
  */
20 20
 class FindViewHelper extends AbstractContentViewHelper
21 21
 {
22
-    /**
23
-     * @return void
24
-     * @throws Exception
25
-     */
26
-    public function initializeArguments()
27
-    {
28
-        parent::initializeArguments();
22
+	/**
23
+	 * @return void
24
+	 * @throws Exception
25
+	 */
26
+	public function initializeArguments()
27
+	{
28
+		parent::initializeArguments();
29 29
 
30
-        $this->registerArgument('orderings', 'array', 'Key / value array to be used for ordering. The key corresponds to a field name. The value can be "DESC" or "ASC".', false, array());
31
-        $this->registerArgument('limit', 'int', 'Limit the number of records being fetched.', false, 0);
32
-        $this->registerArgument('offset', 'int', 'Where to start the list of records.', false, 0);
33
-    }
30
+		$this->registerArgument('orderings', 'array', 'Key / value array to be used for ordering. The key corresponds to a field name. The value can be "DESC" or "ASC".', false, array());
31
+		$this->registerArgument('limit', 'int', 'Limit the number of records being fetched.', false, 0);
32
+		$this->registerArgument('offset', 'int', 'Where to start the list of records.', false, 0);
33
+	}
34 34
 
35
-    /**
36
-     * Fetch and returns a list of content objects.
37
-     *
38
-     * @return array
39
-     * @throws \BadMethodCallException
40
-     */
41
-    public function render()
42
-    {
43
-        $selectionIdentifier = (int)$this->arguments['selection'];
35
+	/**
36
+	 * Fetch and returns a list of content objects.
37
+	 *
38
+	 * @return array
39
+	 * @throws \BadMethodCallException
40
+	 */
41
+	public function render()
42
+	{
43
+		$selectionIdentifier = (int)$this->arguments['selection'];
44 44
 
45
-        if ($selectionIdentifier > 0) {
46
-            /** @var SelectionRepository $selectionRepository */
47
-            $selectionRepository = GeneralUtility::makeInstance(SelectionRepository::class);
45
+		if ($selectionIdentifier > 0) {
46
+			/** @var SelectionRepository $selectionRepository */
47
+			$selectionRepository = GeneralUtility::makeInstance(SelectionRepository::class);
48 48
 
49
-            /** @var Selection $selection */
50
-            $selection = $selectionRepository->findByUid($selectionIdentifier);
51
-            $matches = json_decode($selection->getQuery(), true);
52
-            $dataType = $selection->getDataType();
53
-        } else {
54
-            $dataType = $this->arguments['type'];
55
-            if (!empty($this->arguments['dataType'])) {
56
-                print 'Sorry to be so rude! There is something to change in the View Helper "v:find". Please replace attribute "dataType" by "type". This is a shorter syntax...';
57
-                exit();
58
-            }
59
-            $matches = $this->replacesAliases($this->arguments['matches']);
60
-        }
49
+			/** @var Selection $selection */
50
+			$selection = $selectionRepository->findByUid($selectionIdentifier);
51
+			$matches = json_decode($selection->getQuery(), true);
52
+			$dataType = $selection->getDataType();
53
+		} else {
54
+			$dataType = $this->arguments['type'];
55
+			if (!empty($this->arguments['dataType'])) {
56
+				print 'Sorry to be so rude! There is something to change in the View Helper "v:find". Please replace attribute "dataType" by "type". This is a shorter syntax...';
57
+				exit();
58
+			}
59
+			$matches = $this->replacesAliases($this->arguments['matches']);
60
+		}
61 61
 
62
-        $orderings = $this->replacesAliases($this->arguments['orderings']);
63
-        $limit = $this->arguments['limit'];
64
-        $offset = $this->arguments['offset'];
65
-        $ignoreEnableFields = $this->arguments['ignoreEnableFields'];
62
+		$orderings = $this->replacesAliases($this->arguments['orderings']);
63
+		$limit = $this->arguments['limit'];
64
+		$offset = $this->arguments['offset'];
65
+		$ignoreEnableFields = $this->arguments['ignoreEnableFields'];
66 66
 
67
-        $querySignature = $this->getQuerySignature($dataType, $matches, $orderings, $limit, $offset);
67
+		$querySignature = $this->getQuerySignature($dataType, $matches, $orderings, $limit, $offset);
68 68
 
69
-        $resultSet = $this->getResultSetStorage()->get($querySignature);
70
-        if (!$resultSet) {
71
-            $matcher = $this->getMatcher($dataType, $matches);
72
-            $orderings = $this->getOrder($dataType, $orderings);
69
+		$resultSet = $this->getResultSetStorage()->get($querySignature);
70
+		if (!$resultSet) {
71
+			$matcher = $this->getMatcher($dataType, $matches);
72
+			$orderings = $this->getOrder($dataType, $orderings);
73 73
 
74
-            $this->emitPostProcessLimitSignal($dataType, $limit);
75
-            $this->emitPostProcessOffsetSignal($dataType, $offset);
74
+			$this->emitPostProcessLimitSignal($dataType, $limit);
75
+			$this->emitPostProcessOffsetSignal($dataType, $offset);
76 76
 
77
-            $contentRepository = ContentRepositoryFactory::getInstance($dataType);
78
-            $contentRepository->setDefaultQuerySettings($this->getDefaultQuerySettings($ignoreEnableFields));
77
+			$contentRepository = ContentRepositoryFactory::getInstance($dataType);
78
+			$contentRepository->setDefaultQuerySettings($this->getDefaultQuerySettings($ignoreEnableFields));
79 79
 
80
-            $resultSet = $contentRepository->findBy($matcher, $orderings, $limit, $offset);
81
-            $this->getResultSetStorage()->set($querySignature, $resultSet); // store the result set for performance sake.
82
-        }
80
+			$resultSet = $contentRepository->findBy($matcher, $orderings, $limit, $offset);
81
+			$this->getResultSetStorage()->set($querySignature, $resultSet); // store the result set for performance sake.
82
+		}
83 83
 
84
-        return $resultSet;
85
-    }
84
+		return $resultSet;
85
+	}
86 86
 }
Please login to merge, or discard this patch.
Classes/ViewHelpers/Be/AdditionalAssetsViewHelper.php 1 patch
Indentation   +35 added lines, -35 removed lines patch added patch discarded remove patch
@@ -20,42 +20,42 @@
 block discarded – undo
20 20
  */
21 21
 class AdditionalAssetsViewHelper extends AbstractBackendViewHelper
22 22
 {
23
-    /**
24
-     * Load the assets (JavaScript, CSS) for this Vidi module.
25
-     *
26
-     * @return void
27
-     * @api
28
-     */
29
-    public function render()
30
-    {
31
-        $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
32
-        /** @var ModuleLoader $moduleLoader */
33
-        $moduleLoader = GeneralUtility::makeInstance(ModuleLoader::class);
23
+	/**
24
+	 * Load the assets (JavaScript, CSS) for this Vidi module.
25
+	 *
26
+	 * @return void
27
+	 * @api
28
+	 */
29
+	public function render()
30
+	{
31
+		$pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
32
+		/** @var ModuleLoader $moduleLoader */
33
+		$moduleLoader = GeneralUtility::makeInstance(ModuleLoader::class);
34 34
 
35
-        foreach ($moduleLoader->getAdditionalStyleSheetFiles() as $addCssFile) {
36
-            $fileNameAndPath = $this->resolvePath($addCssFile);
37
-            $pageRenderer->addCssFile($fileNameAndPath);
38
-        }
35
+		foreach ($moduleLoader->getAdditionalStyleSheetFiles() as $addCssFile) {
36
+			$fileNameAndPath = $this->resolvePath($addCssFile);
37
+			$pageRenderer->addCssFile($fileNameAndPath);
38
+		}
39 39
 
40
-        foreach ($moduleLoader->getAdditionalJavaScriptFiles() as $addJsFile) {
41
-            $fileNameAndPath = $this->resolvePath($addJsFile);
42
-            $pageRenderer->addJsFile($fileNameAndPath);
43
-        }
44
-    }
40
+		foreach ($moduleLoader->getAdditionalJavaScriptFiles() as $addJsFile) {
41
+			$fileNameAndPath = $this->resolvePath($addJsFile);
42
+			$pageRenderer->addJsFile($fileNameAndPath);
43
+		}
44
+	}
45 45
 
46
-    /**
47
-     * Resolve a resource path.
48
-     *
49
-     * @param string $uri
50
-     * @return string
51
-     */
52
-    protected function resolvePath($uri)
53
-    {
54
-        $uri = GeneralUtility::getFileAbsFileName($uri);
55
-        $uri = substr($uri, strlen(Environment::getPublicPath() . '/'));
56
-        if (ApplicationType::fromRequest($GLOBALS['TYPO3_REQUEST'])->isBackend() && $uri !== false) {
57
-            $uri = '../' . $uri;
58
-        }
59
-        return $uri;
60
-    }
46
+	/**
47
+	 * Resolve a resource path.
48
+	 *
49
+	 * @param string $uri
50
+	 * @return string
51
+	 */
52
+	protected function resolvePath($uri)
53
+	{
54
+		$uri = GeneralUtility::getFileAbsFileName($uri);
55
+		$uri = substr($uri, strlen(Environment::getPublicPath() . '/'));
56
+		if (ApplicationType::fromRequest($GLOBALS['TYPO3_REQUEST'])->isBackend() && $uri !== false) {
57
+			$uri = '../' . $uri;
58
+		}
59
+		return $uri;
60
+	}
61 61
 }
Please login to merge, or discard this patch.
Classes/ViewHelpers/Be/RequireJsViewHelper.php 1 patch
Indentation   +15 added lines, -15 removed lines patch added patch discarded remove patch
@@ -19,21 +19,21 @@
 block discarded – undo
19 19
  */
20 20
 class RequireJsViewHelper extends AbstractBackendViewHelper
21 21
 {
22
-    /**
23
-     * Load RequireJS code.
24
-     *
25
-     * @return void
26
-     */
27
-    public function render()
28
-    {
29
-        $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
22
+	/**
23
+	 * Load RequireJS code.
24
+	 *
25
+	 * @return void
26
+	 */
27
+	public function render()
28
+	{
29
+		$pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
30 30
 
31
-        $content = $this->renderChildren();
32
-        $pageRenderer->addJsInlineCode('vidi-inline', $content);
31
+		$content = $this->renderChildren();
32
+		$pageRenderer->addJsInlineCode('vidi-inline', $content);
33 33
 
34
-        $publicResourcesPath = PathUtility::getPublicResourceWebPath('EXT:vidi/Resources/Public/');
35
-        $configuration['paths']['Fab/Vidi'] = $publicResourcesPath . 'JavaScript';
36
-        $pageRenderer->addRequireJsConfiguration($configuration);
37
-        $pageRenderer->loadRequireJsModule('Fab/Vidi/Vidi/Main');
38
-    }
34
+		$publicResourcesPath = PathUtility::getPublicResourceWebPath('EXT:vidi/Resources/Public/');
35
+		$configuration['paths']['Fab/Vidi'] = $publicResourcesPath . 'JavaScript';
36
+		$pageRenderer->addRequireJsConfiguration($configuration);
37
+		$pageRenderer->loadRequireJsModule('Fab/Vidi/Vidi/Main');
38
+	}
39 39
 }
Please login to merge, or discard this patch.
Classes/ViewHelpers/Selection/VisibilityOptionsViewHelper.php 1 patch
Indentation   +23 added lines, -23 removed lines patch added patch discarded remove patch
@@ -18,30 +18,30 @@
 block discarded – undo
18 18
  */
19 19
 class VisibilityOptionsViewHelper extends AbstractViewHelper
20 20
 {
21
-    /**
22
-     * Returns the options for the visibility field of a Selection.
23
-     *
24
-     * @return array
25
-     */
26
-    public function render()
27
-    {
28
-        $options[Selection::VISIBILITY_PRIVATE] = LocalizationUtility::translate('LLL:EXT:vidi/Resources/Private/Language/tx_vidi_selection.xlf:visibility.private', 'vidi');
29
-        $options[Selection::VISIBILITY_EVERYONE] = LocalizationUtility::translate('LLL:EXT:vidi/Resources/Private/Language/tx_vidi_selection.xlf:visibility.everyone', 'vidi');
21
+	/**
22
+	 * Returns the options for the visibility field of a Selection.
23
+	 *
24
+	 * @return array
25
+	 */
26
+	public function render()
27
+	{
28
+		$options[Selection::VISIBILITY_PRIVATE] = LocalizationUtility::translate('LLL:EXT:vidi/Resources/Private/Language/tx_vidi_selection.xlf:visibility.private', 'vidi');
29
+		$options[Selection::VISIBILITY_EVERYONE] = LocalizationUtility::translate('LLL:EXT:vidi/Resources/Private/Language/tx_vidi_selection.xlf:visibility.everyone', 'vidi');
30 30
 
31
-        if ($this->getBackendUser()->isAdmin()) {
32
-            $options[Selection::VISIBILITY_ADMIN_ONLY] = LocalizationUtility::translate('LLL:EXT:vidi/Resources/Private/Language/tx_vidi_selection.xlf:visibility.admin_only', 'vidi');
33
-        }
34
-        return $options;
35
-    }
31
+		if ($this->getBackendUser()->isAdmin()) {
32
+			$options[Selection::VISIBILITY_ADMIN_ONLY] = LocalizationUtility::translate('LLL:EXT:vidi/Resources/Private/Language/tx_vidi_selection.xlf:visibility.admin_only', 'vidi');
33
+		}
34
+		return $options;
35
+	}
36 36
 
37 37
 
38
-    /**
39
-     * Returns an instance of the current Backend User.
40
-     *
41
-     * @return BackendUserAuthentication
42
-     */
43
-    protected function getBackendUser()
44
-    {
45
-        return $GLOBALS['BE_USER'];
46
-    }
38
+	/**
39
+	 * Returns an instance of the current Backend User.
40
+	 *
41
+	 * @return BackendUserAuthentication
42
+	 */
43
+	protected function getBackendUser()
44
+	{
45
+		return $GLOBALS['BE_USER'];
46
+	}
47 47
 }
Please login to merge, or discard this patch.