PluginProbe
Search Atlas SEO – OTTO AI SEO Automation for WordPress / trunk
Search Atlas SEO – OTTO AI SEO Automation for WordPress vtrunk
2.6.26 2.6.25 2.6.24 2.6.23 2.6.22 2.6.21 2.6.20 2.6.19 2.6.18 2.6.17 2.6.16 2.6.15 2.6.14 2.6.13 2.6.12 2.6.11 2.6.10 2.6.9 2.6.8 2.6.7 2.6.6 2.6.5 2.6.4 2.6.3 2.5.23 All 138 releases
metasync / views / metasync-add-redirection.php

metasync-add-redirection.php in Search Atlas SEO – OTTO AI SEO Automation for WordPress trunk, at views/metasync-add-redirection.php

722 lines 33.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // If this file is called directly, abort.
3 if (!defined('ABSPATH')) {
4 exit;
5 }
6
7
8 /**
9 * Instant Indexing Settings page contents.
10 *
11 * @package Google Instant Indexing
12 */
13 ?>
14
15 <style>
16 /* Form styling for redirection form */
17 #add-redirection-form .form-table th {
18 vertical-align: middle !important;
19 text-align: center !important;
20 padding: 20px 30px 20px 0 !important;
21 width: 200px !important;
22 font-weight: 600 !important;
23 color: var(--dashboard-text-primary) !important;
24 background: rgba(59, 130, 246, 0.05) !important;
25 border-right: 2px solid var(--dashboard-border) !important;
26 margin-right: 20px !important;
27 }
28
29 #add-redirection-form .form-table td {
30 vertical-align: middle !important;
31 padding: 15px !important;
32 }
33
34 #add-redirection-form .form-table input[type="text"],
35 #add-redirection-form .form-table input[type="url"] {
36 padding: 10px 12px !important;
37 height: 40px !important;
38 border: 1px solid var(--dashboard-border) !important;
39 border-radius: 6px !important;
40 background: var(--dashboard-card-bg) !important;
41 color: var(--dashboard-text-primary) !important;
42 font-size: 14px !important;
43 }
44
45 #add-redirection-form .form-table select {
46 padding: 10px 12px !important;
47 height: 40px !important;
48 border: 1px solid var(--dashboard-border) !important;
49 border-radius: 6px !important;
50 background: var(--dashboard-card-bg) !important;
51 color: var(--dashboard-text-primary) !important;
52 font-size: 14px !important;
53 min-width: 150px !important;
54 }
55
56 #add-redirection-form .form-table ul {
57 margin: 0 !important;
58 padding: 0 !important;
59 list-style: none !important;
60 }
61
62 #add-redirection-form .form-table ul li {
63 margin-bottom: 8px !important;
64 display: flex !important;
65 align-items: center !important;
66 gap: 12px !important;
67 }
68
69 #add-redirection-form .form-table ul li label {
70 display: flex !important;
71 align-items: center !important;
72 gap: 12px !important;
73 font-weight: 500 !important;
74 color: var(--dashboard-text-primary) !important;
75 cursor: pointer !important;
76 margin: 0 !important;
77 padding: 12px 16px !important;
78 background: rgba(255, 255, 255, 0.02) !important;
79 border-radius: 6px !important;
80 border: 1px solid transparent !important;
81 transition: all 0.2s ease !important;
82 }
83
84 #add-redirection-form .form-table ul li label:hover {
85 background: rgba(59, 130, 246, 0.1) !important;
86 border-color: var(--dashboard-accent) !important;
87 transform: translateY(-1px) !important;
88 }
89
90 #add-redirection-form .form-table ul li input[type="radio"] {
91 margin: 0 !important;
92 width: 16px !important;
93 height: 16px !important;
94 }
95
96 #add-redirection-form .form-table .description {
97 margin-top: 8px !important;
98 color: var(--dashboard-text-secondary) !important;
99 font-size: 13px !important;
100 font-style: italic !important;
101 }
102
103 #add-redirection-form .form-table .regular-text {
104 width: 100% !important;
105 max-width: 400px !important;
106 }
107
108 #add-redirection-form .form-table .button {
109 padding: 10px 20px !important;
110 height: 40px !important;
111 border-radius: 6px !important;
112 font-weight: 500 !important;
113 text-decoration: none !important;
114 display: inline-flex !important;
115 align-items: center !important;
116 justify-content: center !important;
117 }
118
119 #add-redirection-form .form-table .button-primary {
120 background: var(--dashboard-accent) !important;
121 border-color: var(--dashboard-accent) !important;
122 color: white !important;
123 }
124
125 #add-redirection-form .form-table .button-secondary {
126 background: var(--dashboard-card-bg) !important;
127 border: 1px solid var(--dashboard-border) !important;
128 color: var(--dashboard-text-primary) !important;
129 }
130
131 #add-redirection-form .form-table .button:hover {
132 opacity: 0.9 !important;
133 transform: translateY(-1px) !important;
134 transition: all 0.2s ease !important;
135 }
136
137 /* Source URLs list styling */
138 #source_urls {
139 margin: 0 !important;
140 padding: 0 !important;
141 list-style: none !important;
142 }
143
144 #source_urls li {
145 display: flex !important;
146 align-items: center !important;
147 gap: 12px !important;
148 margin-bottom: 12px !important;
149 padding: 12px !important;
150 background: var(--dashboard-card-hover) !important;
151 border: 1px solid var(--dashboard-border) !important;
152 border-radius: 6px !important;
153 }
154
155 #source_urls li input[type="text"] {
156 flex: 1 !important;
157 margin: 0 !important;
158 }
159
160 #source_urls li select {
161 min-width: 140px !important;
162 margin: 0 !important;
163 }
164
165 #source_urls li .source_url_delete {
166 background: var(--dashboard-error) !important;
167 color: white !important;
168 border: none !important;
169 padding: 8px 12px !important;
170 border-radius: 4px !important;
171 cursor: pointer !important;
172 font-size: 12px !important;
173 height: 32px !important;
174 }
175
176 #source_urls li .source_url_delete:hover {
177 background: #dc2626 !important;
178 transform: translateY(-1px) !important;
179 }
180
181 #addNewSourceUrl {
182 margin-top: 12px !important;
183 background: var(--dashboard-success) !important;
184 color: white !important;
185 border: none !important;
186 }
187
188 #addNewSourceUrl:hover {
189 background: #059669 !important;
190 }
191
192 /* Form table row spacing */
193 #add-redirection-form .form-table tr {
194 border-bottom: 1px solid var(--dashboard-border) !important;
195 margin-bottom: 20px !important;
196 }
197
198 #add-redirection-form .form-table tr:hover th {
199 background: rgba(59, 130, 246, 0.08) !important;
200 }
201
202 /* Add spacing between rows */
203 #add-redirection-form .form-table tbody tr {
204 margin-bottom: 25px !important;
205 padding-bottom: 15px !important;
206 }
207
208 #add-redirection-form .form-table tbody tr:not(:last-child) {
209 margin-bottom: 30px !important;
210 padding-bottom: 20px !important;
211 }
212
213 /* Responsive adjustments */
214 @media (max-width: 768px) {
215 #add-redirection-form .form-table th,
216 #add-redirection-form .form-table td {
217 display: block !important;
218 width: 100% !important;
219 padding: 15px !important;
220 }
221
222 #add-redirection-form .form-table th {
223 margin-bottom: 12px !important;
224 font-weight: 600 !important;
225 background: rgba(59, 130, 246, 0.1) !important;
226 border-right: none !important;
227 border-bottom: 2px solid var(--dashboard-border) !important;
228 padding: 20px !important;
229 text-align: center !important;
230 }
231
232 #add-redirection-form .form-table td {
233 padding: 15px !important;
234 }
235
236 #source_urls li {
237 flex-direction: column !important;
238 align-items: stretch !important;
239 gap: 8px !important;
240 }
241
242 #source_urls li input[type="text"],
243 #source_urls li select {
244 width: 100% !important;
245 }
246 }
247
248 /* Description text styling */
249 .description,
250 p.description {
251 color: var(--dashboard-text-secondary, #9ca3af) !important;
252 font-size: 13px !important;
253 line-height: 1.5 !important;
254 }
255 </style>
256
257 <div id="add-redirection-form">
258 <h1><?php echo (isset($_GET['action']) && $_GET['action'] == 'edit') ? 'Edit Redirection' : 'Add Redirection'; ?></h1>
259
260 <!-- Redirection Tips Section -->
261 <div class="redirection-tips-container" style="margin-bottom: 20px;">
262 <button type="button" id="toggle-redirection-tips" class="button button-secondary" style="margin-bottom: 10px;">
263 <span class="dashicons dashicons-info"></span> Show Redirection Tips & Examples
264 </button>
265
266 <div id="redirection-tips-content" style="display: none; background: var(--dashboard-card-bg); border: 1px solid var(--dashboard-border); border-radius: 8px; padding: 20px; margin-top: 10px;">
267 <h3 style="margin-top: 0; color: var(--dashboard-text-primary);">Redirection Pattern Guide</h3>
268
269 <!-- Pattern Type Examples -->
270 <div class="tips-section">
271 <h4 style="color: var(--dashboard-accent); margin-bottom: 10px;">Pattern Types Explained</h4>
272
273 <!-- Exact Match -->
274 <details class="tip-item" style="margin-bottom: 15px; padding: 10px; background: rgba(59, 130, 246, 0.1); border-left: 3px solid var(--dashboard-accent); border-radius: 4px;">
275 <summary style="cursor: pointer; font-weight: 600; color: var(--dashboard-text-primary); padding: 5px;">
276 <span class="dashicons dashicons-yes-alt" style="color: var(--dashboard-accent);"></span> 1. Exact Match
277 </summary>
278 <div style="margin-top: 10px; padding-left: 20px; color: var(--dashboard-text-secondary);">
279 <p><strong>Use when:</strong> You want to redirect one specific URL only.</p>
280 <div style="background: var(--dashboard-card-hover); padding: 10px; border-radius: 4px; margin: 10px 0;">
281 <strong>Example:</strong><br>
282 <code>From: /old-page</code><br>
283 <code>To: /new-page</code><br>
284 <code>Pattern: Exact Match</code>
285 </div>
286 <p><strong>Matches:</strong> �
287 <code>yoursite.com/old-page</code></p>
288 <p><strong>Doesn't match:</strong> ❌ <code>yoursite.com/old-page/</code> or <code>yoursite.com/old-page-2</code></p>
289 </div>
290 </details>
291
292 <!-- Starts With -->
293 <details class="tip-item" style="margin-bottom: 15px; padding: 10px; background: rgba(16, 185, 129, 0.1); border-left: 3px solid var(--dashboard-success); border-radius: 4px;">
294 <summary style="cursor: pointer; font-weight: 600; color: var(--dashboard-text-primary); padding: 5px;">
295 <span class="dashicons dashicons-arrow-right-alt" style="color: var(--dashboard-success);"></span> 2. Starts With
296 </summary>
297 <div style="margin-top: 10px; padding-left: 20px; color: var(--dashboard-text-secondary);">
298 <p><strong>Use when:</strong> You want to redirect all URLs that start with a specific path.</p>
299 <div style="background: var(--dashboard-card-hover); padding: 10px; border-radius: 4px; margin: 10px 0;">
300 <strong>Example - Category to Articles Migration:</strong><br>
301 <code>From: /category/blog/</code><br>
302 <code>To: /articles/article/</code><br>
303 <code>Pattern: Starts With</code>
304 </div>
305 <p><strong>Matches:</strong><br>
306
307 <code>yoursite.com/category/blog/my-post</code> → <code>yoursite.com/articles/article/</code><br>
308
309 <code>yoursite.com/category/blog/2024/january</code> → <code>yoursite.com/articles/article/</code><br>
310
311 <code>yoursite.com/category/blog</code> → <code>yoursite.com/articles/article/</code></p>
312 <p><strong>Doesn't match:</strong> ❌ <code>yoursite.com/old-category/blog/post</code></p>
313 <p><strong>Note:</strong> This pattern does NOT preserve the path after the matched part. All matching URLs redirect to the same destination. For path preservation, use Wildcard (*) pattern instead.</p>
314 </div>
315 </details>
316
317 <!-- Ends With -->
318 <details class="tip-item" style="margin-bottom: 15px; padding: 10px; background: rgba(139, 92, 246, 0.1); border-left: 3px solid #8b5cf6; border-radius: 4px;">
319 <summary style="cursor: pointer; font-weight: 600; color: var(--dashboard-text-primary); padding: 5px;">
320 <span class="dashicons dashicons-arrow-left-alt" style="color: #8b5cf6;"></span> 3. Ends With
321 </summary>
322 <div style="margin-top: 10px; padding-left: 20px; color: var(--dashboard-text-secondary);">
323 <p><strong>Use when:</strong> You want to redirect URLs that end with specific text or file extensions.</p>
324 <div style="background: var(--dashboard-card-hover); padding: 10px; border-radius: 4px; margin: 10px 0;">
325 <strong>Example - PDF Redirect:</strong><br>
326 <code>From: .pdf</code><br>
327 <code>To: /downloads/</code><br>
328 <code>Pattern: Ends With</code>
329 </div>
330 <p><strong>Matches:</strong><br>
331
332 <code>yoursite.com/document.pdf</code><br>
333
334 <code>yoursite.com/files/report-2024.pdf</code></p>
335 </div>
336 </details>
337
338 <!-- Wildcard -->
339 <details class="tip-item" style="margin-bottom: 15px; padding: 10px; background: rgba(34, 197, 94, 0.1); border-left: 3px solid #22c55e; border-radius: 4px;">
340 <summary style="cursor: pointer; font-weight: 600; color: var(--dashboard-text-primary); padding: 5px;">
341 <span class="dashicons dashicons-star-filled" style="color: #22c55e;"></span> 4. Wildcard (*) - Path Preservation
342 </summary>
343 <div style="margin-top: 10px; padding-left: 20px; color: var(--dashboard-text-secondary);">
344 <p><strong>Use when:</strong> You want to redirect URLs and preserve the remaining path structure. Perfect for section migrations!</p>
345
346 <div style="background: var(--dashboard-card-hover); padding: 10px; border-radius: 4px; margin: 10px 0;">
347 <strong>Example 1 - Blog to Articles (Preserve Full Path):</strong><br>
348 <code>From: /blog/*</code><br>
349 <code>To: /articles/*</code><br>
350 <code>Pattern: Wildcard (*)</code>
351 </div>
352 <p><strong>Result:</strong><br>
353
354 <code>/blog/my-post</code> → <code>/articles/my-post</code><br>
355
356 <code>/blog/2024/tech/ai</code> → <code>/articles/2024/tech/ai</code><br>
357
358 <code>/blog/category/news/post-123</code> → <code>/articles/category/news/post-123</code></p>
359
360 <div style="background: var(--dashboard-card-hover); padding: 10px; border-radius: 4px; margin: 10px 0;">
361 <strong>Example 2 - Year Archive Restructure:</strong><br>
362 <code>From: /2024/*</code><br>
363 <code>To: /archive/2024/*</code>
364 </div>
365 <p><strong>Result:</strong><br>
366
367 <code>/2024/january/post</code> → <code>/archive/2024/january/post</code><br>
368
369 <code>/2024/sales-report</code> → <code>/archive/2024/sales-report</code></p>
370
371 <div style="background: var(--dashboard-card-hover); padding: 10px; border-radius: 4px; margin: 10px 0;">
372 <strong>Example 3 - Prefix Addition:</strong><br>
373 <code>From: /post/*</code><br>
374 <code>To: /blog/post/*</code>
375 </div>
376 <p><strong>Result:</strong><br>
377
378 <code>/post/hello-world</code> → <code>/blog/post/hello-world</code></p>
379
380 <div style="background: rgba(34, 197, 94, 0.2); padding: 10px; border-radius: 4px; margin: 10px 0; border: 1px solid #22c55e;">
381 <strong>How it works:</strong><br>
382 The <code>*</code> wildcard captures everything after the matched part and replaces the <code>*</code> in the destination URL.<br>
383 <strong>Much simpler than regex for common use cases!</strong>
384 </div>
385 </div>
386 </details>
387
388 <!-- Regex Pattern -->
389 <details class="tip-item" style="margin-bottom: 15px; padding: 10px; background: rgba(239, 68, 68, 0.1); border-left: 3px solid var(--dashboard-error); border-radius: 4px;">
390 <summary style="cursor: pointer; font-weight: 600; color: var(--dashboard-text-primary); padding: 5px;">
391 <span class="dashicons dashicons-admin-tools" style="color: var(--dashboard-error);"></span> 5. Regex Pattern (Advanced)
392 </summary>
393 <div style="margin-top: 10px; padding-left: 20px; color: var(--dashboard-text-secondary);">
394 <p><strong>Use when:</strong> You need complex pattern matching with path preservation.</p>
395
396 <div style="background: var(--dashboard-card-hover); padding: 10px; border-radius: 4px; margin: 10px 0;">
397 <strong>Example 1 - Category to Articles Migration (Preserve Path):</strong><br>
398 <code>From: category-blog</code> (label only)<br>
399 <code>Regex Pattern: /^\/category\/blog\/(.*)$/</code><br>
400 <code>To: /articles/article/$1</code><br>
401 <code>Pattern: Regex Pattern</code>
402 </div>
403 <p><strong>Result:</strong><br>
404
405 <code>/category/blog/my-post</code> → <code>/articles/article/my-post</code><br>
406
407 <code>/category/blog/2024/tech</code> → <code>/articles/article/2024/tech</code><br>
408
409 <code>/category/blog/news/item-123</code> → <code>/articles/article/news/item-123</code></p>
410
411 <div style="background: var(--dashboard-card-hover); padding: 10px; border-radius: 4px; margin: 10px 0;">
412 <strong>Example 2 - Product ID Redirect:</strong><br>
413 <code>From: product-id</code> (label only)<br>
414 <code>Regex Pattern: /^\/product-(\d+)$/</code><br>
415 <code>To: /products/view?id=$1</code>
416 </div>
417 <p><strong>Result:</strong><br>
418
419 <code>/product-123</code> → <code>/products/view?id=123</code><br>
420
421 <code>/product-456</code> → <code>/products/view?id=456</code></p>
422
423 <div style="background: rgba(239, 68, 68, 0.2); padding: 10px; border-radius: 4px; margin: 10px 0; border: 1px solid var(--dashboard-error);">
424 <strong>Regex Syntax:</strong><br>
425 <code>/^ $/</code> = Pattern delimiters (required)<br>
426 <code>^</code> = Start of URL path<br>
427 <code>$</code> = End of URL path<br>
428 <code>(.*)</code> = Capture everything (use $1 in destination)<br>
429 <code>(\d+)</code> = Capture numbers only<br>
430 <code>\/</code> = Escape forward slash<br>
431 <code>\.</code> = Escape dot for literal match
432 </div>
433 </div>
434 </details>
435 </div>
436
437 <!-- HTTP Status Codes -->
438 <div class="tips-section" style="margin-top: 20px;">
439 <h4 style="color: var(--dashboard-accent); margin-bottom: 10px;">HTTP Status Codes Guide</h4>
440
441 <details class="tip-item" style="margin-bottom: 10px; padding: 10px; background: rgba(255, 255, 255, 0.05); border-radius: 4px;">
442 <summary style="cursor: pointer; font-weight: 600; color: var(--dashboard-text-primary);">
443 <strong style="color: var(--dashboard-success);">301</strong> - Permanent Redirect (SEO Friendly)
444 </summary>
445 <div style="padding: 10px; color: var(--dashboard-text-secondary);">
446 <p><strong>Use for:</strong> Permanent URL changes, site restructuring</p>
447 <p><strong>Benefits:</strong> Search engines transfer page rank to new URL</p>
448 <p><strong>Example:</strong> Old domain to new domain, permanent page moves</p>
449 </div>
450 </details>
451
452 <details class="tip-item" style="margin-bottom: 10px; padding: 10px; background: rgba(255, 255, 255, 0.05); border-radius: 4px;">
453 <summary style="cursor: pointer; font-weight: 600; color: var(--dashboard-text-primary);">
454 <strong style="color: var(--dashboard-warning);">302</strong> - Temporary Redirect
455 </summary>
456 <div style="padding: 10px; color: var(--dashboard-text-secondary);">
457 <p><strong>Use for:</strong> Temporary changes, A/B testing, seasonal campaigns</p>
458 <p><strong>Note:</strong> Search engines don't transfer page rank</p>
459 </div>
460 </details>
461
462 <details class="tip-item" style="margin-bottom: 10px; padding: 10px; background: rgba(255, 255, 255, 0.05); border-radius: 4px;">
463 <summary style="cursor: pointer; font-weight: 600; color: var(--dashboard-text-primary);">
464 <strong style="color: var(--dashboard-error);">410</strong> - Content Deleted (No Destination)
465 </summary>
466 <div style="padding: 10px; color: var(--dashboard-text-secondary);">
467 <p><strong>Use for:</strong> Permanently removed content that won't return</p>
468 <p><strong>Note:</strong> No destination URL needed - page shows as permanently gone</p>
469 <p><strong>Better than 404 for SEO</strong></p>
470 </div>
471 </details>
472
473 <details class="tip-item" style="margin-bottom: 10px; padding: 10px; background: rgba(255, 255, 255, 0.05); border-radius: 4px;">
474 <summary style="cursor: pointer; font-weight: 600; color: var(--dashboard-text-primary);">
475 <strong>451</strong> - Unavailable for Legal Reasons
476 </summary>
477 <div style="padding: 10px; color: var(--dashboard-text-secondary);">
478 <p><strong>Use for:</strong> Content blocked due to legal requirements</p>
479 </div>
480 </details>
481 </div>
482
483 <!-- Common Use Cases -->
484 <div class="tips-section" style="margin-top: 20px;">
485 <h4 style="color: var(--dashboard-accent); margin-bottom: 10px;">Common Use Cases</h4>
486
487 <div style="background: rgba(34, 197, 94, 0.1); padding: 15px; border-radius: 4px; margin-bottom: 10px; border-left: 3px solid #22c55e;">
488 <strong>Blog to Articles Migration (WITH Path Preservation):</strong>
489 <p style="margin: 5px 0; color: var(--dashboard-text-secondary);">
490 <strong>Use Wildcard:</strong> <code>/blog/*</code> → <code>/articles/*</code><br>
491 This preserves the entire path structure automatically!
492 </p>
493 </div>
494
495 <div style="background: var(--dashboard-card-hover); padding: 15px; border-radius: 4px; margin-bottom: 10px;">
496 <strong>✓ Multiple Old URLs → One New URL:</strong>
497 <p style="margin: 5px 0; color: var(--dashboard-text-secondary);">Add multiple source URLs (click "Add Another") all pointing to same destination.</p>
498 </div>
499
500 <div style="background: var(--dashboard-card-hover); padding: 15px; border-radius: 4px; margin-bottom: 10px;">
501 <strong>✓ Entire Section Migration (Simple):</strong>
502 <p style="margin: 5px 0; color: var(--dashboard-text-secondary);">Use "Starts With" pattern for /old-section/ → /new-section/ (doesn't preserve sub-paths)</p>
503 </div>
504
505 <div style="background: var(--dashboard-card-hover); padding: 15px; border-radius: 4px; margin-bottom: 10px;">
506 <strong>✓ File Extension Redirect:</strong>
507 <p style="margin: 5px 0; color: var(--dashboard-text-secondary);">Use "Ends With" pattern for .pdf → /downloads/ to redirect all PDF files</p>
508 </div>
509 </div>
510
511 <!-- Best Practices -->
512 <div class="tips-section" style="margin-top: 20px; padding: 15px; background: rgba(59, 130, 246, 0.1); border-radius: 4px;">
513 <h4 style="color: var(--dashboard-accent); margin-top: 0;">Best Practices</h4>
514 <ul style="color: var(--dashboard-text-secondary); margin: 0; padding-left: 20px;">
515 <li>Test with 302 first, then change to 301 when confirmed working</li>
516 <li>Use Exact Match when possible (faster performance)</li>
517 <li>Use Regex only when path preservation is needed</li>
518 <li>Monitor hit counts to identify most-used redirects</li>
519 <li>Add descriptions to help identify redirect purpose later</li>
520 <li>Keep redirects active to maintain SEO value</li>
521 </ul>
522 </div>
523 </div>
524 </div>
525
526 <table class="form-table add-form-table">
527 <tr valign="top">
528 <th scope="row">
529 Source From:
530 </th>
531 <td>
532 <?php
533
534 $record = [];
535 $id = '';
536 $source_form = ['' => 'exact'];
537 $url_redirect_to = '';
538 $http_code = '301';
539 $status = 'active';
540 $uri = '';
541
542 $get_data = metasync_sanitize_input_array($_GET);
543
544 if (isset($get_data['action'])) {
545 if (isset($get_data['uri']) && ($get_data['action'] == 'redirect' && !empty($get_data['uri']))) {
546 // Decode the URI and sanitize it properly
547 $uri = urldecode($get_data['uri']);
548 $uri = sanitize_text_field($uri);
549
550 // Ensure URI starts with /
551 if (!str_starts_with($uri, '/')) {
552 $uri = '/' . $uri;
553 }
554 }
555
556 if (isset($get_data['id']) && $get_data['action'] == 'edit') {
557 // Get database instance
558 $db_instance = isset($this) && isset($this->db_redirection) ? $this->db_redirection : null;
559
560 if ($db_instance) {
561 $record = $db_instance->find(intval($get_data['id']));
562
563 if ($record) {
564 $id = isset($record->id) ? esc_attr($record->id) : '';
565 $source_form = isset($record->sources_from) && $record->sources_from ? unserialize($record->sources_from, ['allowed_classes' => false]) : []; // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_unserialize
566 $url_redirect_to = isset($record->url_redirect_to) ? esc_attr($record->url_redirect_to) : '';
567 $http_code = isset($record->http_code) ? esc_attr($record->http_code) : '';
568 $status = isset($record->status) ? esc_attr($record->status) : '';
569 }
570 }
571 }
572 }
573
574 $search_type = [
575 ['name' => 'Exact Match', 'value' => 'exact'],
576 ['name' => 'Starts With', 'value' => 'start'],
577 ['name' => 'Ends With', 'value' => 'end'],
578 ['name' => 'Wildcard (*)', 'value' => 'wildcard'],
579 ['name' => 'Regex Pattern', 'value' => 'regex'],
580 ];
581
582 ?>
583 <ul id="source_urls">
584
585 <?php
586
587 foreach ($source_form as $source_name => $source_type) {
588
589 ?>
590 <li>
591 <input type="text" class="regular-text" name="source_url[]" value="<?php echo $uri ? esc_attr($uri) : esc_attr($source_name) ?>">
592 <select name="search_type[]">
593 <?php
594 foreach ($search_type as $type) {
595 printf('<option value="%s" %s >%s</option>', esc_attr($type['value']), selected(esc_attr($type['value']), esc_attr($source_type)), esc_attr($type['name']));
596 }
597 ?>
598 </select>
599 <button type="button" class="source_url_delete">Remove</button>
600 </li>
601 <?php } ?>
602
603 </ul>
604
605 <?php
606 printf(' <input type="hidden" name="redirect_id" value="%s"/>', esc_attr($id));
607 printf(' <input class="button-secondary" type="button" id="addNewSourceUrl" value="Add Another">');
608 ?>
609
610 </td>
611 </tr>
612
613 <tr valign="top" id="destination" class="<?php if ($http_code == '410' || $http_code == '451') {
614 echo esc_attr('hide');
615 } ?>">
616 <th scope="row">
617 Destination URL:
618 </th>
619 <td>
620 <input type="text" class="regular-text" name="destination_url" id="destination_url" value="<?php echo esc_url($url_redirect_to) ?>">
621 </td>
622 </tr>
623
624 <tr valign="top">
625 <th scope="row">
626 Redirection Type:
627 </th>
628 <td>
629 <ul>
630 <li>
631 <label>
632 <input type="radio" name="redirect_type" class="redirect_type" value="301" <?php checked($http_code, '301'); ?>>
633 301 Permanent Move
634 </label>
635 </li>
636 <li>
637 <label>
638 <input type="radio" name="redirect_type" class="redirect_type" value="302" <?php checked($http_code, '302'); ?>>
639 302 Temporary Move
640 </label>
641 </li>
642 <li>
643 <label>
644 <input type="radio" name="redirect_type" class="redirect_type" value="307" <?php checked($http_code, '307'); ?>>
645 307 Temporary Redirect
646 </label>
647 </li>
648 <li>
649 <label>
650 <input type="radio" name="redirect_type" class="redirect_type" value="410" <?php checked($http_code, '410'); ?>>
651 410 Content Deleted
652 </label>
653 </li>
654 <li>
655 <label>
656 <input type="radio" name="redirect_type" class="redirect_type" value="451" <?php checked($http_code, '451'); ?>>
657 451 Content Unavailable for Legal Reasons
658 </label>
659 </li>
660 </ul>
661 </td>
662 </tr>
663
664 <tr valign="top" id="regex_pattern_row" style="display: none;">
665 <th scope="row">
666 Regex Pattern:
667 </th>
668 <td>
669 <input type="text" class="regular-text" name="regex_pattern" id="regex_pattern"
670 value="<?php echo isset($record->regex_pattern) ? esc_attr($record->regex_pattern) : ''; ?>"
671 placeholder="/^\/old-path\/.*$/">
672 <p class="description">
673 Enter a valid regex pattern. Example: <code>/^\/old-path\/.*$/</code> to match all URLs starting with /old-path/
674 </p>
675 </td>
676 </tr>
677
678 <tr valign="top">
679 <th scope="row">
680 Description:
681 </th>
682 <td>
683 <input type="text" class="regular-text" name="description" id="description"
684 value="<?php echo isset($record->description) ? esc_attr($record->description) : ''; ?>"
685 placeholder="Optional description for this redirection">
686 <p class="description">
687 Optional description to help identify this redirection rule.
688 </p>
689 </td>
690 </tr>
691
692 <tr valign="top">
693 <th scope="row">
694 Status:
695 </th>
696 <td>
697 <label class="pr">
698 <input type="radio" name="status" value="active" <?php checked($status, 'active'); ?>>
699 Active
700 </label>
701 <label class="pr">
702 <input type="radio" name="status" value="inactive" <?php checked($status, 'inactive'); ?>>
703 Inactive
704 </label>
705 </td>
706 </tr>
707
708 <tr valign="top">
709 <td colspan="2">
710 <input type="submit" name="submit" class="button button-primary" value="Save">
711 <input type="button" id="cancel-redirection" class="button button-secondary" value="Cancel" data-cancel-url="<?php echo esc_url(admin_url('admin.php?page=' . Metasync_Admin::$page_slug . '-redirections')); ?>">
712 </td>
713 </tr>
714 </table>
715
716 </div>
717
718 <?php
719 $get_data = metasync_sanitize_input_array($_GET);
720 if (isset($get_data['action']) && ($get_data['action'] == 'edit' || $get_data['action'] == 'redirect' || $get_data['action'] == 'add')) {
721 ?>
722 <?php } ?>