PluginProbe
User Access Manager / 2.2.13
User Access Manager v2.2.13
2.3.20 2.3.19 2.3.18 2.3.17 2.3.16 2.3.15 2.3.14 2.3.13 trunk 0.6 0.6.1 0.6.2 0.7 0.7 Beta 0.7.0.1 0.8 0.8.0.1 0.8.0.2 0.9 0.9.1 0.9.1.1 0.9.1.2 0.9.1.3 0.9.1.4 1.0 All 136 releases
← All changes | src/Controller/Frontend/RedirectController.php +183 -142 2.3.182.2.13 View file →
@@ -1,21 +1,32 @@
1 1 <?php
2 +/**
3 + * FrontendRedirectController.php
4 + *
5 + * The FrontendRedirectController class file.
6 + *
7 + * PHP versions 5
8 + *
9 + * @author Alexander Schneider <alexanderschneider85@gmail.com>
10 + * @copyright 2008-2017 Alexander Schneider
11 + * @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2
12 + * @version SVN: $id$
13 + * @link http://wordpress.org/extend/plugins/user-access-manager/
14 + */
2 15
3 16 declare(strict_types=1);
4 17
5 18 namespace UserAccessManager\Controller\Frontend;
6 19
7 -use JetBrains\PhpStorm\NoReturn;
8 20 use UserAccessManager\Access\AccessHandler;
9 21 use UserAccessManager\Cache\Cache;
10 22 use UserAccessManager\Config\MainConfig;
11 23 use UserAccessManager\Config\WordpressConfig;
12 24 use UserAccessManager\Controller\Controller;
13 -use UserAccessManager\Controller\Frontend\Authentication\LoginControllerTrait;
14 25 use UserAccessManager\Database\Database;
15 26 use UserAccessManager\File\FileHandler;
16 -use UserAccessManager\File\Delivery\FileObject;
17 -use UserAccessManager\File\Delivery\FileObjectFactory;
27 +use UserAccessManager\File\FileObject;
28 +use UserAccessManager\File\FileObjectFactory;
18 29 use UserAccessManager\Object\ObjectHandler;
19 30 use UserAccessManager\UserGroup\UserGroupTypeException;
20 31 use UserAccessManager\Util\Util;
21 32 use UserAccessManager\Wrapper\Php;
@@ -20,36 +31,110 @@
20 31 use UserAccessManager\Util\Util;
21 32 use UserAccessManager\Wrapper\Php;
22 33 use UserAccessManager\Wrapper\Wordpress;
23 34
35 +/**
36 + * Class FrontendRedirectController
37 + *
38 + * @package UserAccessManager\Controller
39 + */
24 40 class RedirectController extends Controller
25 41 {
26 42 use LoginControllerTrait;
27 43
28 - public const POST_URL_CACHE_KEY = 'PostUrls';
29 - public const REDIRECT_TO_PARAMETER = 'redirect_to';
44 + const POST_URL_CACHE_KEY = 'PostUrls';
30 45
46 + /**
47 + * @var MainConfig
48 + */
49 + private $mainConfig;
50 +
51 + /**
52 + * @var Database
53 + */
54 + private $database;
55 +
56 + /**
57 + * @var Cache
58 + */
59 + private $cache;
60 +
61 + /**
62 + * @var Util
63 + */
64 + private $util;
65 +
66 + /**
67 + * @var ObjectHandler
68 + */
69 + private $objectHandler;
70 +
71 + /**
72 + * @var AccessHandler
73 + */
74 + private $accessHandler;
75 +
76 + /**
77 + * @var FileHandler
78 + */
79 + private $fileHandler;
80 +
81 + /**
82 + * @var FileObjectFactory
83 + */
84 + private $fileObjectFactory;
85 +
86 + /**
87 + * RedirectController constructor.
88 + * @param Php $php
89 + * @param Wordpress $wordpress
90 + * @param WordpressConfig $wordpressConfig
91 + * @param MainConfig $mainConfig
92 + * @param Database $database
93 + * @param Util $util
94 + * @param Cache $cache
95 + * @param ObjectHandler $objectHandler
96 + * @param AccessHandler $accessHandler
97 + * @param FileHandler $fileHandler
98 + * @param FileObjectFactory $fileObjectFactory
99 + */
31 100 public function __construct(
32 101 Php $php,
33 102 Wordpress $wordpress,
34 103 WordpressConfig $wordpressConfig,
35 - private MainConfig $mainConfig,
36 - private Database $database,
37 - private Util $util,
38 - private Cache $cache,
39 - private ObjectHandler $objectHandler,
40 - private AccessHandler $accessHandler,
41 - private FileHandler $fileHandler,
42 - private FileObjectFactory $fileObjectFactory
104 + MainConfig $mainConfig,
105 + Database $database,
106 + Util $util,
107 + Cache $cache,
108 + ObjectHandler $objectHandler,
109 + AccessHandler $accessHandler,
110 + FileHandler $fileHandler,
111 + FileObjectFactory $fileObjectFactory
43 112 ) {
44 113 parent::__construct($php, $wordpress, $wordpressConfig);
114 + $this->mainConfig = $mainConfig;
115 + $this->database = $database;
116 + $this->util = $util;
117 + $this->cache = $cache;
118 + $this->objectHandler = $objectHandler;
119 + $this->accessHandler = $accessHandler;
120 + $this->fileHandler = $fileHandler;
121 + $this->fileObjectFactory = $fileObjectFactory;
45 122 }
46 123
124 + /**
125 + * @return Wordpress
126 + */
47 127 protected function getWordpress(): Wordpress
48 128 {
49 129 return $this->wordpress;
50 130 }
51 131
132 + /**
133 + * Returns the post by the given url.
134 + * @param string $url The url of the post(attachment).
135 + * @return int
136 + */
52 137 public function getPostIdByUrl(string $url): int
53 138 {
54 139 $postUrls = (array)$this->cache->getFromRuntimeCache(self::POST_URL_CACHE_KEY);
55 140
@@ -61,140 +146,67 @@
61 146 $newUrlPieces = preg_split('/-[0-9]+x[0-9]+(_[a-z])?/', $url);
62 147 $newUrl = (count($newUrlPieces) === 2) ? $newUrlPieces[0] . $newUrlPieces[1] : $newUrlPieces[0];
63 148 $newUrl = preg_replace('/-pdf\.jpg$/', '.pdf', $newUrl);
64 149
65 - $postId = $this->wordpress->attachmentUrlToPostId($newUrl);
66 -
67 - if ($postId === 0) {
68 - $newUrl = preg_replace('/(\\.[^.\\s]{3,4})$/', '-scaled$1', $newUrl);
69 - $postId = $this->wordpress->attachmentUrlToPostId($newUrl);
70 - }
71 -
72 - $postUrls[$url] = $postId;
150 + $postUrls[$url] = $this->wordpress->attachmentUrlToPostId($newUrl);
73 151 $this->cache->addToRuntimeCache(self::POST_URL_CACHE_KEY, $postUrls);
74 152
75 153 return $postUrls[$url];
76 154 }
77 155
78 - private function normalizeAttachmentUrl(array $uploadDirs, string $objectUrl): string
79 - {
80 - $uploadDir = str_replace(ABSPATH, '/', $uploadDirs['basedir']);
81 - $regex = '/.*' . str_replace('/', '\/', $uploadDir) . '\//i';
82 - $cleanObjectUrl = preg_replace($regex, '', $objectUrl);
83 - $uploadUrl = str_replace('/files', $uploadDir, $uploadDirs['baseurl']);
84 -
85 - return rtrim($uploadUrl, '/') . '/' . ltrim($cleanObjectUrl, '/');
86 - }
87 -
88 - private function isRegisteredSize(int $attachmentId, string $fileName): bool
89 - {
90 - $metaData = $this->wordpress->getAttachmentMetadata($attachmentId);
91 - $sizes = is_array($metaData) === true ? (array) ($metaData['sizes'] ?? []) : [];
92 -
93 - return in_array($fileName, array_column($sizes, 'file'), true);
94 - }
95 -
96 156 /**
97 - * Returns the file the request asks for and tells through $isImage whether it can be shown as image.
98 - * A requested generated size is only used if it is registered at the attachment and stored inside the
99 - * upload directory, so no arbitrary and no missing file becomes reachable. Generated sizes are always
100 - * images, also for documents like PDFs, where they are the preview images shown in the media library.
157 + * Returns the file object by the given type and url.
158 + * @param string $objectType The type of the requested file.
159 + * @param string $objectUrl The file url.
160 + * @return null|FileObject
101 161 */
102 - private function getAttachmentFile(
103 - int $attachmentId,
104 - string $attachedFile,
105 - string $requestedUrl,
106 - string $uploadBaseDir,
107 - ?bool &$isImage
108 - ): string {
109 - $requestedFileName = basename((string) parse_url($requestedUrl, PHP_URL_PATH));
110 - $sizeFile = dirname($attachedFile) . DIRECTORY_SEPARATOR . $requestedFileName;
111 -
112 - if ($requestedFileName !== basename($attachedFile)
113 - && $this->isRegisteredSize($attachmentId, $requestedFileName) === true
114 - && $this->isInsideUploadDirectory($sizeFile, $uploadBaseDir) === true
115 - ) {
116 - $isImage = true;
117 -
118 - return $sizeFile;
119 - }
120 -
121 - $isImage = $this->wordpress->attachmentIsImage($attachmentId);
122 -
123 - return $attachedFile;
124 - }
125 -
126 - private function getAttachmentFileObject(string $objectUrl): ?FileObject
162 + private function getFileSettingsByType(string $objectType, string $objectUrl): ?FileObject
127 163 {
128 - $uploadDirs = $this->wordpress->getUploadDir();
129 - $requestedUrl = $this->normalizeAttachmentUrl($uploadDirs, $objectUrl);
130 - $postId = $this->getPostIdByUrl($requestedUrl);
164 + $fileObject = null;
131 165
132 - if ($postId < 1) {
133 - return null;
134 - }
166 + if ($objectType === ObjectHandler::ATTACHMENT_OBJECT_TYPE) {
167 + $uploadDirs = $this->wordpress->getUploadDir();
168 + $uploadDir = str_replace(ABSPATH, '/', $uploadDirs['basedir']);
169 + $regex = '/.*' . str_replace('/', '\/', $uploadDir) . '\//i';
170 + $cleanObjectUrl = preg_replace($regex, '', $objectUrl);
171 + $uploadUrl = str_replace('/files', $uploadDir, $uploadDirs['baseurl']);
172 + $objectUrl = rtrim($uploadUrl, '/') . '/' . ltrim($cleanObjectUrl, '/');
135 173
136 - $post = $this->objectHandler->getPost($postId);
174 + $post = $this->objectHandler->getPost($this->getPostIdByUrl($objectUrl));
175 + $postType = $post->post_type ?? '';
137 176
138 - if (($post->post_type ?? '') !== ObjectHandler::ATTACHMENT_OBJECT_TYPE) {
139 - return null;
140 - }
177 + if ($postType === ObjectHandler::ATTACHMENT_OBJECT_TYPE) {
178 + $multiPath = str_replace('/files', $uploadDir, $uploadDirs['baseurl']);
141 179
142 - $attachedFile = $this->wordpress->getAttachedFile($post->ID);
180 + $fileObject = $this->fileObjectFactory->createFileObject(
181 + $post->ID,
182 + $objectType,
183 + $uploadDirs['basedir'] . str_replace($multiPath, '', $objectUrl),
184 + $this->wordpress->attachmentIsImage($post->ID)
185 + );
186 + }
187 + } else {
188 + $extraParameter = $this->getRequestParameter('uamextra');
143 189
144 - if ($attachedFile === false
145 - || $this->isInsideUploadDirectory($attachedFile, $uploadDirs['basedir']) === false
146 - ) {
147 - return null;
190 + $fileObject = $this->wordpress->applyFilters(
191 + 'uam_get_file_settings_by_type',
192 + $fileObject,
193 + $objectType,
194 + $objectUrl,
195 + $extraParameter
196 + );
148 197 }
149 198
150 - $file = $this->getAttachmentFile(
151 - $post->ID,
152 - $attachedFile,
153 - $requestedUrl,
154 - $uploadDirs['basedir'],
155 - $isImage
156 - );
157 -
158 - return $this->fileObjectFactory->createFileObject(
159 - $post->ID,
160 - ObjectHandler::ATTACHMENT_OBJECT_TYPE,
161 - $file,
162 - $isImage
163 - );
199 + return $fileObject;
164 200 }
165 201
166 - private function isInsideUploadDirectory(string $file, string $uploadBaseDir): bool
167 - {
168 - $realFile = $this->php->realpath($file);
169 - $realUploadBaseDir = $this->php->realpath($uploadBaseDir);
170 -
171 - return $realFile !== false
172 - && $realUploadBaseDir !== false
173 - && str_starts_with($realFile, $realUploadBaseDir . DIRECTORY_SEPARATOR);
174 - }
175 -
176 - private function getFileSettingsByType(string $objectType, string $objectUrl): ?FileObject
177 - {
178 - if ($objectType === ObjectHandler::ATTACHMENT_OBJECT_TYPE) {
179 - return $this->getAttachmentFileObject($objectUrl);
180 - }
181 -
182 - $extraParameter = $this->getRequestParameter('uamextra');
183 -
184 - return $this->wordpress->applyFilters(
185 - 'uam_get_file_settings_by_type',
186 - null,
187 - $objectType,
188 - $objectUrl,
189 - $extraParameter
190 - );
191 - }
192 -
193 202 /**
203 + * Delivers the content of the requested file.
204 + * @param string $objectType The type of the requested file.
205 + * @param string $objectUrl The file url.
194 206 * @throws UserGroupTypeException
195 207 */
196 - public function getFile(string $objectType, string $objectUrl): void
208 + public function getFile(string $objectType, string $objectUrl)
197 209 {
198 210 $fileObject = $this->getFileSettingsByType($objectType, $objectUrl);
199 211
200 212 if ($fileObject === null) {
@@ -217,8 +229,13 @@
217 229
218 230 $this->fileHandler->getFile($file, $fileObject->isImage());
219 231 }
220 232
233 + /**
234 + * Returns the redirect url and the permalink of the post if exists.
235 + * @param null|string $permalink
236 + * @return null|string
237 + */
221 238 private function getRedirectUrlAndPermalink(?string &$permalink): ?string
222 239 {
223 240 $permalink = null;
224 241 $redirect = $this->mainConfig->getRedirect();
@@ -235,11 +252,8 @@
235 252 } elseif ($redirect === 'custom_url') {
236 253 $url = $this->mainConfig->getRedirectCustomUrl();
237 254 } elseif ($redirect === 'login') {
238 255 $url = $this->getLoginUrl();
239 - } elseif ($redirect === 'origin') {
240 - $referer = $this->wordpress->getReferer();
241 - $url = $referer !== false ? $referer : $this->wordpress->getHomeUrl('/');
242 256 } else {
243 257 $url = $this->wordpress->getHomeUrl('/');
244 258 }
245 259
@@ -246,14 +260,16 @@
246 260 return $url;
247 261 }
248 262
249 263 /**
264 + * Redirects the user to his destination.
265 + * @param bool $checkPosts
250 266 * @throws UserGroupTypeException
251 267 */
252 - public function redirectUser(bool $checkPosts = true): void
268 + public function redirectUser($checkPosts = true)
253 269 {
254 270 if ($checkPosts === true) {
255 - $posts = $this->wordpress->getWpQuery()->get_posts();
271 + $posts = (array)$this->wordpress->getWpQuery()->get_posts();
256 272
257 273 foreach ($posts as $post) {
258 274 if ($this->accessHandler->checkObjectAccess($post->post_type, $post->ID)) {
259 275 return;
@@ -264,17 +280,18 @@
264 280 $url = $this->getRedirectUrlAndPermalink($permalink);
265 281 $currentUrl = $this->util->getCurrentUrl();
266 282
267 283 if ($url !== null && $url !== $currentUrl && $permalink !== $currentUrl) {
268 - if ($this->mainConfig->appendRedirectToParameter() === true) {
269 - $url = $this->wordpress->addQueryArg([self::REDIRECT_TO_PARAMETER => $currentUrl], $url);
270 - }
271 -
272 284 $this->wordpress->wpRedirect($url);
273 285 $this->php->callExit();
274 286 }
275 287 }
276 288
289 + /**
290 + * Returns the post id by the post name.
291 + * @param string $name
292 + * @return int
293 + */
277 294 private function getPostIdByName(string $name): int
278 295 {
279 296 $postableTypes = implode('\',\'', $this->objectHandler->getPostTypes());
280 297
@@ -281,9 +298,9 @@
281 298 $query = $this->database->prepare(
282 299 "SELECT ID
283 300 FROM {$this->database->getPostsTable()}
284 301 WHERE post_name = %s
285 - AND post_type IN ('$postableTypes')",
302 + AND post_type IN ('{$postableTypes}')",
286 303 $name
287 304 );
288 305
289 306 return (int) $this->database->getVariable($query);
@@ -288,9 +305,15 @@
288 305
289 306 return (int) $this->database->getVariable($query);
290 307 }
291 308
292 - private function extractObjectTypeAndId(mixed $pageParams, ?string &$objectType, int|string|null &$objectId): void
309 + /**
310 + * Extracts the object type and id.
311 + * @param object $pageParams
312 + * @param null|string $objectType
313 + * @param null|int|string $objectId
314 + */
315 + private function extractObjectTypeAndId(object $pageParams, ?string &$objectType, ?string &$objectId)
293 316 {
294 317 $objectType = null;
295 318 $objectId = null;
296 319
@@ -320,11 +343,15 @@
320 343 }
321 344 }
322 345
323 346 /**
347 + * Redirects to a page or to content.
348 + * @param array $headers The headers which are given from wordpress.
349 + * @param object $pageParams The params of the current page.
350 + * @return array
324 351 * @throws UserGroupTypeException
325 352 */
326 - public function redirect(?array $headers, mixed $pageParams): ?array
353 + public function redirect(array $headers, object $pageParams): array
327 354 {
328 355 $fileUrl = $this->getRequestParameter('uamgetfile');
329 356 $fileType = $this->getRequestParameter('uamfiletype');
330 357
@@ -342,9 +369,15 @@
342 369
343 370 return $headers;
344 371 }
345 372
346 - public function getFileUrl(string $url, int|string|null $id): string
373 + /**
374 + * Returns the url for a locked file.
375 + * @param string $url The base url.
376 + * @param int|string $id The id of the file.
377 + * @return string
378 + */
379 + public function getFileUrl(string $url, $id): string
347 380 {
348 381 // Nginx always supports real urls so we need the new urls only
349 382 // if we don't use nginx and mod_rewrite is disabled
350 383 if ($this->mainConfig->lockFile() === true
@@ -352,9 +385,9 @@
352 385 && $this->wordpress->gotModRewrite() === false
353 386 ) {
354 387 $post = $this->objectHandler->getPost($id);
355 388
356 - if ($post !== false) {
389 + if ($post !== null) {
357 390 $type = explode('/', $post->post_mime_type);
358 391 $type = $type[1] ?? $type[0];
359 392
360 393 $lockedFileTypes = $this->mainConfig->getLockedFiles();
@@ -368,8 +401,14 @@
368 401
369 402 return $url;
370 403 }
371 404
405 + /**
406 + * Caches the urls for the post for a later lookup.
407 + * @param string $url The url of the post.
408 + * @param object $post The post object.
409 + * @return string
410 + */
372 411 public function cachePostLinks(string $url, object $post): string
373 412 {
374 413 $postUrls = (array) $this->cache->getFromRuntimeCache(self::POST_URL_CACHE_KEY);
375 414 $postUrls[$url] = $post->ID;
@@ -376,10 +415,12 @@
376 415 $this->cache->addToRuntimeCache(self::POST_URL_CACHE_KEY, $postUrls);
377 416 return $url;
378 417 }
379 418
380 - #[NoReturn]
381 - public function testXSendFile(): void
419 + /**
420 + * Tries to load the file via x send file
421 + */
422 + public function testXSendFile()
382 423 {
383 424 $this->fileHandler->deliverXSendFileTestFile();
384 425 }
385 426 }