Completed
Pull Request — master (#10)
by Aske
03:21
created

appendDefaultDimensionPresetUriSegments()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 7
rs 9.4285
cc 2
eloc 5
nc 2
nop 2
1
<?php
2
namespace MOC\NotFound\ViewHelpers;
3
4
use TYPO3\Flow\Annotations as Flow;
5
use TYPO3\Flow\Configuration\ConfigurationManager;
6
use TYPO3\Flow\Core\Bootstrap;
7
use TYPO3\Flow\Http\Request;
8
use TYPO3\Flow\Http\RequestHandler;
9
use TYPO3\Flow\Http\Response;
10
use TYPO3\Flow\Http\Uri;
11
use TYPO3\Flow\Mvc\ActionRequest;
12
use TYPO3\Flow\Mvc\Routing\Router;
13
use TYPO3\Fluid\Core\ViewHelper\AbstractViewHelper;
14
use TYPO3\Neos\Domain\Service\ContentDimensionPresetSourceInterface;
15
16
/**
17
 * Loads the content of a given URL
18
 */
19
class RequestViewHelper extends AbstractViewHelper {
20
21
	/**
22
	 * @Flow\Inject
23
	 * @var \TYPO3\Flow\Mvc\Dispatcher
24
	 */
25
	protected $dispatcher;
26
27
	/**
28
	 * @Flow\Inject(lazy = false)
29
	 * @var Bootstrap
30
	 */
31
	protected $bootstrap;
32
33
	/**
34
	 * @Flow\Inject(lazy = false)
35
	 * @var Router
36
	 */
37
	protected $router;
38
39
	/**
40
	 * @Flow\Inject(lazy=false)
41
	 * @var \TYPO3\Flow\Security\Context
42
	 */
43
	protected $securityContext;
44
45
	/**
46
	 * @Flow\Inject
47
	 * @var ConfigurationManager
48
	 */
49
	protected $configurationManager;
50
51
	/**
52
	 * @Flow\InjectConfiguration("routing.supportEmptySegmentForDimensions", package="TYPO3.Neos")
53
	 * @var boolean
54
	 */
55
	protected $supportEmptySegmentForDimensions;
56
57
	/**
58
	 * @Flow\Inject
59
	 * @var ContentDimensionPresetSourceInterface
60
	 */
61
	protected $contentDimensionPresetSource;
62
63
	/**
64
	 * Initialize this engine
65
	 *
66
	 * @return void
67
	 */
68
	public function initializeObject() {
69
		$this->router->setRoutesConfiguration($this->configurationManager->getConfiguration(ConfigurationManager::CONFIGURATION_TYPE_ROUTES));
70
	}
71
72
	/**
73
	 * @param string $path
74
	 * @return string
75
	 * @throws \Exception
76
	 */
77
	public function render($path = NULL) {
78
		$this->appendFirstUriPartIfValidDimension($path);
79
		/** @var RequestHandler $activeRequestHandler */
80
		$activeRequestHandler = $this->bootstrap->getActiveRequestHandler();
81
		$parentHttpRequest = $activeRequestHandler->getHttpRequest();
82
		$uri = rtrim($parentHttpRequest->getBaseUri(), '/') . '/' . $path;
83
		$httpRequest = Request::create(new Uri($uri));
84
		$matchingRoute = $this->router->route($httpRequest);
85
		if (!$matchingRoute) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $matchingRoute of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
86
			$exception = new \Exception(sprintf('Uri with path "%s" could not be found.', $uri), 1426446160);
87
			$exceptionHandler = set_exception_handler(null)[0];
88
			$exceptionHandler->handleException($exception);
89
			exit();
0 ignored issues
show
Coding Style Compatibility introduced by
The method render() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
90
		}
91
		$request = new ActionRequest($parentHttpRequest);
92
		foreach ($matchingRoute as $argumentName => $argumentValue) {
93
			$request->setArgument($argumentName, $argumentValue);
94
		}
95
		$response = new Response($activeRequestHandler->getHttpResponse());
96
97
		$this->securityContext->withoutAuthorizationChecks(function() use ($request, $response) {
98
			$this->dispatcher->dispatch($request, $response);
99
		});
100
101
		return $response->getContent();
102
	}
103
104
	/**
105
	 * @param string $path
106
	 * @return void
107
	 */
108
	protected function appendFirstUriPartIfValidDimension(&$path) {
109
		$requestPath = ltrim($this->controllerContext->getRequest()->getHttpRequest()->getUri()->getPath(), '/');
110
		$matches = [];
111
		preg_match(\TYPO3\Neos\Routing\FrontendNodeRoutePartHandler::DIMENSION_REQUEST_PATH_MATCHER, $requestPath, $matches);
112
		if (!isset($matches['firstUriPart']) && !isset($matches['dimensionPresetUriSegments'])) {
113
			return;
114
		}
115
116
		$dimensionPresets = $this->contentDimensionPresetSource->getAllPresets();
117
		if (count($dimensionPresets) === 0) {
118
			return;
119
		}
120
121
		$firstUriPartExploded = explode('_', $matches['firstUriPart'] ?: $matches['dimensionPresetUriSegments']);
122
		if ($this->supportEmptySegmentForDimensions) {
123
			foreach ($firstUriPartExploded as $uriSegment) {
124
				$uriSegmentIsValid = false;
125 View Code Duplication
				foreach ($dimensionPresets as $dimensionName => $dimensionPreset) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
126
					$preset = $this->contentDimensionPresetSource->findPresetByUriSegment($dimensionName, $uriSegment);
127
					if ($preset !== null) {
128
						$uriSegmentIsValid = true;
129
						break;
130
					}
131
				}
132
				if (!$uriSegmentIsValid) {
133
					return;
134
				}
135
			}
136
		} else {
137
			if (count($firstUriPartExploded) !== count($dimensionPresets)) {
138
				$this->appendDefaultDimensionPresetUriSegments($dimensionPresets, $path);
139
				return;
140
			}
141 View Code Duplication
			foreach ($dimensionPresets as $dimensionName => $dimensionPreset) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
142
				$uriSegment = array_shift($firstUriPartExploded);
143
				$preset = $this->contentDimensionPresetSource->findPresetByUriSegment($dimensionName, $uriSegment);
144
				if ($preset === null) {
145
					return;
146
				}
147
			}
148
		}
149
150
		$path = $matches['firstUriPart'] . '/' . $path;
151
	}
152
153
	/**
154
	 * @param array $dimensionPresets
155
	 * @param string $path
156
	 * @return void
157
	 */
158
	protected function appendDefaultDimensionPresetUriSegments($dimensionPresets, &$path) {
159
		$defaultDimensionPresetUriSegments = [];
160
		foreach ($dimensionPresets as $dimensionName => $dimensionPreset) {
161
			$defaultDimensionPresetUriSegments[] = $dimensionPreset['presets'][$dimensionPreset['defaultPreset']]['uriSegment'];
162
		}
163
		$path = implode('_', $defaultDimensionPresetUriSegments) . '/' . $path;
164
	}
165
}
166