PluginProbe
User Access Manager / 2.2.23
User Access Manager v2.2.23
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 +182 -134 2.3.182.2.23 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
@@ -74,127 +159,61 @@
74 159
75 160 return $postUrls[$url];
76 161 }
77 162
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 163 /**
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.
164 + * Returns the file object by the given type and url.
165 + * @param string $objectType The type of the requested file.
166 + * @param string $objectUrl The file url.
167 + * @return null|FileObject
101 168 */
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
169 + private function getFileSettingsByType(string $objectType, string $objectUrl): ?FileObject
127 170 {
128 - $uploadDirs = $this->wordpress->getUploadDir();
129 - $requestedUrl = $this->normalizeAttachmentUrl($uploadDirs, $objectUrl);
130 - $postId = $this->getPostIdByUrl($requestedUrl);
171 + $fileObject = null;
131 172
132 - if ($postId < 1) {
133 - return null;
134 - }
173 + if ($objectType === ObjectHandler::ATTACHMENT_OBJECT_TYPE) {
174 + $uploadDirs = $this->wordpress->getUploadDir();
175 + $uploadDir = str_replace(ABSPATH, '/', $uploadDirs['basedir']);
176 + $regex = '/.*' . str_replace('/', '\/', $uploadDir) . '\//i';
177 + $cleanObjectUrl = preg_replace($regex, '', $objectUrl);
178 + $uploadUrl = str_replace('/files', $uploadDir, $uploadDirs['baseurl']);
179 + $objectUrl = rtrim($uploadUrl, '/') . '/' . ltrim($cleanObjectUrl, '/');
135 180
136 - $post = $this->objectHandler->getPost($postId);
181 + $post = $this->objectHandler->getPost($this->getPostIdByUrl($objectUrl));
182 + $postType = $post->post_type ?? '';
137 183
138 - if (($post->post_type ?? '') !== ObjectHandler::ATTACHMENT_OBJECT_TYPE) {
139 - return null;
140 - }
184 + if ($postType === ObjectHandler::ATTACHMENT_OBJECT_TYPE) {
185 + $multiPath = str_replace('/files', $uploadDir, $uploadDirs['baseurl']);
141 186
142 - $attachedFile = $this->wordpress->getAttachedFile($post->ID);
187 + $fileObject = $this->fileObjectFactory->createFileObject(
188 + $post->ID,
189 + $objectType,
190 + $uploadDirs['basedir'] . str_replace($multiPath, '', $objectUrl),
191 + $this->wordpress->attachmentIsImage($post->ID)
192 + );
193 + }
194 + } else {
195 + $extraParameter = $this->getRequestParameter('uamextra');
143 196
144 - if ($attachedFile === false
145 - || $this->isInsideUploadDirectory($attachedFile, $uploadDirs['basedir']) === false
146 - ) {
147 - return null;
197 + $fileObject = $this->wordpress->applyFilters(
198 + 'uam_get_file_settings_by_type',
199 + $fileObject,
200 + $objectType,
201 + $objectUrl,
202 + $extraParameter
203 + );
148 204 }
149 205
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 - );
206 + return $fileObject;
164 207 }
165 208
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 209 /**
210 + * Delivers the content of the requested file.
211 + * @param string $objectType The type of the requested file.
212 + * @param string $objectUrl The file url.
194 213 * @throws UserGroupTypeException
195 214 */
196 - public function getFile(string $objectType, string $objectUrl): void
215 + public function getFile(string $objectType, string $objectUrl)
197 216 {
198 217 $fileObject = $this->getFileSettingsByType($objectType, $objectUrl);
199 218
200 219 if ($fileObject === null) {
@@ -217,8 +236,13 @@
217 236
218 237 $this->fileHandler->getFile($file, $fileObject->isImage());
219 238 }
220 239
240 + /**
241 + * Returns the redirect url and the permalink of the post if exists.
242 + * @param null|string $permalink
243 + * @return null|string
244 + */
221 245 private function getRedirectUrlAndPermalink(?string &$permalink): ?string
222 246 {
223 247 $permalink = null;
224 248 $redirect = $this->mainConfig->getRedirect();
@@ -235,11 +259,8 @@
235 259 } elseif ($redirect === 'custom_url') {
236 260 $url = $this->mainConfig->getRedirectCustomUrl();
237 261 } elseif ($redirect === 'login') {
238 262 $url = $this->getLoginUrl();
239 - } elseif ($redirect === 'origin') {
240 - $referer = $this->wordpress->getReferer();
241 - $url = $referer !== false ? $referer : $this->wordpress->getHomeUrl('/');
242 263 } else {
243 264 $url = $this->wordpress->getHomeUrl('/');
244 265 }
245 266
@@ -246,14 +267,16 @@
246 267 return $url;
247 268 }
248 269
249 270 /**
271 + * Redirects the user to his destination.
272 + * @param bool $checkPosts
250 273 * @throws UserGroupTypeException
251 274 */
252 - public function redirectUser(bool $checkPosts = true): void
275 + public function redirectUser($checkPosts = true)
253 276 {
254 277 if ($checkPosts === true) {
255 - $posts = $this->wordpress->getWpQuery()->get_posts();
278 + $posts = (array)$this->wordpress->getWpQuery()->get_posts();
256 279
257 280 foreach ($posts as $post) {
258 281 if ($this->accessHandler->checkObjectAccess($post->post_type, $post->ID)) {
259 282 return;
@@ -264,17 +287,18 @@
264 287 $url = $this->getRedirectUrlAndPermalink($permalink);
265 288 $currentUrl = $this->util->getCurrentUrl();
266 289
267 290 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 291 $this->wordpress->wpRedirect($url);
273 292 $this->php->callExit();
274 293 }
275 294 }
276 295
296 + /**
297 + * Returns the post id by the post name.
298 + * @param string $name
299 + * @return int
300 + */
277 301 private function getPostIdByName(string $name): int
278 302 {
279 303 $postableTypes = implode('\',\'', $this->objectHandler->getPostTypes());
280 304
@@ -281,9 +305,9 @@
281 305 $query = $this->database->prepare(
282 306 "SELECT ID
283 307 FROM {$this->database->getPostsTable()}
284 308 WHERE post_name = %s
285 - AND post_type IN ('$postableTypes')",
309 + AND post_type IN ('{$postableTypes}')",
286 310 $name
287 311 );
288 312
289 313 return (int) $this->database->getVariable($query);
@@ -288,9 +312,15 @@
288 312
289 313 return (int) $this->database->getVariable($query);
290 314 }
291 315
292 - private function extractObjectTypeAndId(mixed $pageParams, ?string &$objectType, int|string|null &$objectId): void
316 + /**
317 + * Extracts the object type and id.
318 + * @param mixed $pageParams
319 + * @param null|string $objectType
320 + * @param null|int|string $objectId
321 + */
322 + private function extractObjectTypeAndId($pageParams, ?string &$objectType, ?string &$objectId)
293 323 {
294 324 $objectType = null;
295 325 $objectId = null;
296 326
@@ -320,11 +350,15 @@
320 350 }
321 351 }
322 352
323 353 /**
354 + * Redirects to a page or to content.
355 + * @param array|null $headers The headers which are given from wordpress.
356 + * @param mixed $pageParams The params of the current page.
357 + * @return array|null
324 358 * @throws UserGroupTypeException
325 359 */
326 - public function redirect(?array $headers, mixed $pageParams): ?array
360 + public function redirect(?array $headers, $pageParams): ?array
327 361 {
328 362 $fileUrl = $this->getRequestParameter('uamgetfile');
329 363 $fileType = $this->getRequestParameter('uamfiletype');
330 364
@@ -342,9 +376,15 @@
342 376
343 377 return $headers;
344 378 }
345 379
346 - public function getFileUrl(string $url, int|string|null $id): string
380 + /**
381 + * Returns the url for a locked file.
382 + * @param string $url The base url.
383 + * @param int|string $id The id of the file.
384 + * @return string
385 + */
386 + public function getFileUrl(string $url, $id): string
347 387 {
348 388 // Nginx always supports real urls so we need the new urls only
349 389 // if we don't use nginx and mod_rewrite is disabled
350 390 if ($this->mainConfig->lockFile() === true
@@ -352,9 +392,9 @@
352 392 && $this->wordpress->gotModRewrite() === false
353 393 ) {
354 394 $post = $this->objectHandler->getPost($id);
355 395
356 - if ($post !== false) {
396 + if ($post !== null) {
357 397 $type = explode('/', $post->post_mime_type);
358 398 $type = $type[1] ?? $type[0];
359 399
360 400 $lockedFileTypes = $this->mainConfig->getLockedFiles();
@@ -368,8 +408,14 @@
368 408
369 409 return $url;
370 410 }
371 411
412 + /**
413 + * Caches the urls for the post for a later lookup.
414 + * @param string $url The url of the post.
415 + * @param object $post The post object.
416 + * @return string
417 + */
372 418 public function cachePostLinks(string $url, object $post): string
373 419 {
374 420 $postUrls = (array) $this->cache->getFromRuntimeCache(self::POST_URL_CACHE_KEY);
375 421 $postUrls[$url] = $post->ID;
@@ -376,10 +422,12 @@
376 422 $this->cache->addToRuntimeCache(self::POST_URL_CACHE_KEY, $postUrls);
377 423 return $url;
378 424 }
379 425
380 - #[NoReturn]
381 - public function testXSendFile(): void
426 + /**
427 + * Tries to load the file via x send file
428 + */
429 + public function testXSendFile()
382 430 {
383 431 $this->fileHandler->deliverXSendFileTestFile();
384 432 }
385 433 }