PluginProbe
404 Solution / trunk
404 Solution vtrunk
4.3.5 4.3.4 4.3.3 4.3.2 4.3.1 4.3.0 4.2.0 4.1.19 4.1.18 4.1.17 4.1.16 4.1.15 4.1.13 4.1.12 4.1.11 4.1.10 4.1.9 4.1.8 4.1.7 4.1.6 4.1.5 4.1.4 4.1.3 trunk 2.30.0 All 109 releases
404-solution / includes / rest / RestApiRedirectMutationService.php

RestApiRedirectMutationService.php in 404 Solution trunk, at includes/rest/RestApiRedirectMutationService.php

152 lines 5.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if (!defined('ABSPATH')) {
4 exit;
5 }
6
7 /**
8 * Executes REST redirect mutations through repository value objects.
9 */
10 final class ABJ_404_Solution_RestApiRedirectMutationService {
11
12 /** @var ABJ_404_Solution_RedirectsRepositoryInterface */
13 private $redirectsRepo;
14
15 /** @var ABJ_404_Solution_RestApiResponsePresenter */
16 private $presenter;
17
18 /**
19 * @param ABJ_404_Solution_RedirectsRepositoryInterface $redirectsRepo
20 */
21 public function __construct($redirectsRepo, ABJ_404_Solution_RestApiResponsePresenter $presenter) {
22 $this->redirectsRepo = $redirectsRepo;
23 $this->presenter = $presenter;
24 }
25
26 /**
27 * @param array{from: string, to: string, code: int, regex: bool} $input
28 * @return \WP_REST_Response|\WP_Error
29 */
30 public function create(array $input) {
31 $status = $input['regex'] ? (string)ABJ404_STATUS_REGEX : (string)ABJ404_STATUS_MANUAL;
32 $resolved = $this->resolveDestinationType($input['to']);
33
34 $insertedId = $this->redirectsRepo->setupRedirect(
35 \ABJ_404_Solution_RedirectSpec::fromArray(array(
36 'fromURL' => $input['from'],
37 'status' => $status,
38 'type' => (string)$resolved['type'],
39 'finalDest' => $resolved['dest'],
40 'code' => (string)$input['code'],
41 'disabled' => 0,
42 'engine' => 'rest-api',
43 ))
44 );
45
46 if (!$insertedId) {
47 return $this->presenter->createFailed();
48 }
49
50 return $this->presenter->redirectCreated((int)$insertedId, $input['from'], $input['to'], $input['code'], $status);
51 }
52
53 /**
54 * @param array{id: int, from: string, to: string, code: int, regex: bool} $input
55 * @return \WP_REST_Response|\WP_Error
56 */
57 public function update(array $input) {
58 $statusType = $input['regex'] ? (string)ABJ404_STATUS_REGEX : (string)ABJ404_STATUS_MANUAL;
59 $resolved = $this->resolveDestinationType($input['to']);
60
61 $error = $this->redirectsRepo->updateRedirect(ABJ_404_Solution_RedirectUpdate::fromArray(array(
62 'id' => $input['id'],
63 'type' => (int)$resolved['type'],
64 'fromUrl' => (string)$input['from'],
65 'destination' => (string)$resolved['dest'],
66 'code' => (string)$input['code'],
67 'statusType' => (string)$statusType,
68 )));
69
70 if ($error !== '') {
71 return $this->presenter->updateFailed((string)$error);
72 }
73
74 return $this->presenter->redirectUpdated($input['id'], $input['from'], $input['to'], $input['code'], $statusType);
75 }
76
77 /**
78 * @param array{id: int} $input
79 * @return \WP_REST_Response|\WP_Error
80 */
81 public function trash(array $input) {
82 $error = $this->redirectsRepo->moveRedirectsToTrash($input['id'], 1);
83
84 if ($error !== '') {
85 return $this->presenter->trashFailed((string)$error);
86 }
87
88 return $this->presenter->redirectTrashed($input['id']);
89 }
90
91 /**
92 * @param array{id: int, to: string, code: int} $input
93 * @return \WP_REST_Response|\WP_Error
94 */
95 public function promoteCaptured(array $input) {
96 $rows = $this->redirectsRepo->getRedirectsByIDs(array($input['id']));
97 if (empty($rows)) {
98 return $this->presenter->capturedNotFound();
99 }
100 $row = $rows[0];
101 $from = is_array($row) && isset($row['url']) && is_string($row['url']) ? $row['url'] : '';
102
103 if ($from === '') {
104 return $this->presenter->capturedBadRecord();
105 }
106
107 $resolved = $this->resolveDestinationType($input['to']);
108 $error = $this->redirectsRepo->updateRedirect(ABJ_404_Solution_RedirectUpdate::fromArray(array(
109 'id' => $input['id'],
110 'type' => (int)$resolved['type'],
111 'fromUrl' => (string)$from,
112 'destination' => (string)$resolved['dest'],
113 'code' => (string)$input['code'],
114 'statusType' => (string)ABJ404_STATUS_MANUAL,
115 )));
116
117 if ($error !== '') {
118 return $this->presenter->updateFailed((string)$error);
119 }
120
121 return $this->presenter->capturedPromoted($input['id'], $from, $input['to'], $input['code']);
122 }
123
124 /**
125 * @param string $to
126 * @return array{type: int, dest: string}
127 */
128 private function resolveDestinationType($to): array {
129 if ($this->looksLikeExternalUrl($to)) {
130 return array('type' => (int)ABJ404_TYPE_EXTERNAL, 'dest' => $to);
131 }
132
133 $trimmed = trim($to, '/ ');
134 if ($trimmed === '') {
135 return array('type' => (int)ABJ404_TYPE_HOME, 'dest' => (string)ABJ404_TYPE_HOME);
136 }
137
138 if (function_exists('url_to_postid')) {
139 $postId = url_to_postid(home_url($to));
140 if ($postId > 0) {
141 return array('type' => (int)ABJ404_TYPE_POST, 'dest' => (string)$postId);
142 }
143 }
144
145 return array('type' => (int)ABJ404_TYPE_EXTERNAL, 'dest' => $to);
146 }
147
148 private function looksLikeExternalUrl(string $url): bool {
149 return strncasecmp($url, 'http://', 7) === 0 || strncasecmp($url, 'https://', 8) === 0;
150 }
151 }
152