PluginProbe
Search Atlas SEO – OTTO AI SEO Automation for WordPress / 2.7.2
Search Atlas SEO – OTTO AI SEO Automation for WordPress v2.7.2
2.7.1 2.7.2 2.7.0 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 All 141 releases
metasync / custom-pages / class-metasync-custom-pages-admin.php

class-metasync-custom-pages-admin.php in Search Atlas SEO – OTTO AI SEO Automation for WordPress 2.7.2, at custom-pages/class-metasync-custom-pages-admin.php

423 lines 17.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Custom Pages Admin Interface
5 *
6 * Provides the admin interface for managing custom HTML pages
7 *
8 * @package Metasync
9 * @subpackage Metasync/custom-pages
10 * @since 1.0.0
11 */
12
13 class Metasync_Custom_Pages_Admin
14 {
15 /**
16 * Render the Custom Pages management interface
17 */
18 public static function render_admin_page()
19 {
20 // Check user capabilities
21 if (!Metasync::current_user_has_plugin_access()) {
22 wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'metasync'));
23 }
24
25 // Handle actions
26 self::handle_actions();
27
28 ?>
29 <!-- Custom HTML Pages Dashboard -->
30 <div class="metasync-custom-pages-dashboard">
31 <?php self::render_notice(); ?>
32
33 <div class="dashboard-card" style="text-align: center; margin-bottom: 20px;">
34 <a href="<?php echo esc_url(admin_url('post-new.php?post_type=page&metasync_html_page=1')); ?>"
35 class="button button-primary button-large" style="font-size: 14px; padding: 10px 24px;">
36 <span class="dashicons dashicons-plus-alt" style="font-size: 16px; vertical-align: middle;"></span>
37 Add New Custom HTML Page
38 </a>
39 </div>
40
41 <div class="metasync-info-cards-grid">
42 <div class="dashboard-card">
43 <h2 style="color: var(--dashboard-accent, #3b82f6); margin-top: 0; font-size: 16px;">📄 About Custom HTML Pages</h2>
44 <p style="color: var(--dashboard-text-secondary); font-size: 14px; line-height: 1.6;">
45 Create dedicated HTML pages that are served directly <strong>without any theme styling</strong>.
46 Perfect for:
47 </p>
48 <ul style="color: var(--dashboard-text-secondary); font-size: 14px; line-height: 1.8; margin-left: 20px;">
49 <li>Landing pages with custom designs</li>
50 <li>Marketing pages built with external tools</li>
51 <li>Standalone HTML pages with embedded CSS/JS</li>
52 <li>A/B testing pages with unique layouts</li>
53 <li><strong>Works with <?php echo esc_html(Metasync::get_whitelabel_otto_name()); ?> and all other MetaSync features!</strong></li>
54 </ul>
55 <p style="margin-top: 15px; padding: 10px; background: rgba(59, 130, 246, 0.1); border-left: 4px solid var(--dashboard-accent, #3b82f6); font-size: 13px; color: var(--dashboard-text-secondary);">
56 💡 <strong>Note:</strong> Pages created here won't interfere with your regular pages or page builders like Elementor, Divi, etc.
57 </p>
58 </div>
59
60 <div class="dashboard-card">
61 <h3 style="color: var(--dashboard-accent, #3b82f6); margin-top: 0; font-size: 16px;">🚀 How to Use</h3>
62 <ol style="color: var(--dashboard-text-secondary); font-size: 14px; line-height: 1.8; margin-left: 20px;">
63 <li>Click <strong>"Add New Custom HTML Page"</strong> above</li>
64 <li>Set your page title and URL slug</li>
65 <li>You'll see the <strong>"Custom HTML Settings"</strong> panel</li>
66 <li>Check <strong>"Enable Raw HTML Mode"</strong> (auto-enabled for new pages)</li>
67 <li>Upload your HTML file OR paste HTML code directly</li>
68 <li>Click <strong>"Publish"</strong> to make it live</li>
69 </ol>
70 <p style="margin-top: 15px; padding: 10px; background: rgba(255, 193, 7, 0.1); border-left: 4px solid #ffc107; font-size: 13px; color: var(--dashboard-text-secondary);">
71 💡 <strong>Tip:</strong> These pages work with <?php echo esc_html(Metasync::get_whitelabel_otto_name()); ?>, so your custom HTML will get AI-powered SEO enhancements!
72 </p>
73 </div>
74 </div>
75
76 <?php self::render_pages_table(); ?>
77 </div>
78
79 <style>
80 /* Custom HTML Pages Dashboard Styles */
81 .metasync-custom-pages-dashboard {
82 max-width: 1400px;
83 }
84
85 .metasync-info-cards-grid {
86 display: grid;
87 grid-template-columns: repeat(auto-fit, minmax(450px, 1fr));
88 gap: 20px;
89 margin-bottom: 30px;
90 }
91
92 /* Pages Table - Match plugin table styling */
93 .metasync-pages-table {
94 margin-top: 0;
95 }
96
97 .metasync-pages-table h2 {
98 margin: 0 0 20px 0;
99 padding: 0;
100 background: none;
101 border: none;
102 font-size: 18px;
103 font-weight: 600;
104 color: var(--dashboard-text-primary, #ffffff);
105 }
106
107 .metasync-pages-table table {
108 width: 100%;
109 border-collapse: collapse;
110 background: var(--dashboard-card-bg, #1a1f26);
111 border: 1px solid var(--dashboard-border, #374151);
112 border-radius: 8px;
113 overflow: hidden;
114 }
115
116 .metasync-pages-table th {
117 background: var(--dashboard-card-bg, #22272e);
118 padding: 12px 15px;
119 text-align: left;
120 font-weight: 600;
121 font-size: 13px;
122 color: var(--dashboard-text-secondary, #9ca3af);
123 border-bottom: 1px solid var(--dashboard-border, #374151);
124 text-transform: uppercase;
125 letter-spacing: 0.5px;
126 }
127
128 .metasync-pages-table td {
129 padding: 12px 15px;
130 border-bottom: 1px solid var(--dashboard-border, #374151);
131 vertical-align: middle;
132 font-size: 14px;
133 color: var(--dashboard-text-primary, #ffffff);
134 }
135
136 .metasync-pages-table tbody tr {
137 transition: background-color 0.2s ease;
138 }
139
140 .metasync-pages-table tbody tr:hover {
141 background: var(--dashboard-card-hover, #222831);
142 }
143
144 .metasync-pages-table tbody tr:last-child td {
145 border-bottom: none;
146 }
147
148 .metasync-pages-table td a {
149 color: var(--dashboard-accent, #3b82f6);
150 text-decoration: none;
151 font-weight: 500;
152 }
153
154 .metasync-pages-table td a:hover {
155 color: var(--dashboard-accent-hover, #60a5fa);
156 text-decoration: underline;
157 }
158
159 .metasync-page-status {
160 display: inline-flex;
161 align-items: center;
162 gap: 6px;
163 font-size: 13px;
164 font-weight: 500;
165 cursor: default;
166 }
167
168 .metasync-page-status::before {
169 content: '';
170 display: inline-block;
171 width: 8px;
172 height: 8px;
173 border-radius: 50%;
174 background: currentColor;
175 flex-shrink: 0;
176 }
177
178 .metasync-page-status.metasync-status-publish {
179 color: #1e7e34;
180 }
181
182 .metasync-page-status.metasync-status-draft {
183 color: #a06800;
184 }
185
186 .metasync-page-status.metasync-status-pending {
187 color: #0c5460;
188 }
189
190 .metasync-page-actions {
191 white-space: nowrap;
192 }
193
194 .metasync-page-actions .button {
195 margin-right: 5px;
196 font-size: 13px;
197 }
198
199 .metasync-page-url {
200 color: var(--dashboard-accent, #3b82f6);
201 font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, monospace;
202 font-size: 13px;
203 word-break: break-all;
204 }
205
206 .metasync-html-badge {
207 display: inline-block;
208 padding: 3px 8px;
209 background: var(--dashboard-accent, #3b82f6);
210 color: #fff;
211 border-radius: 4px;
212 font-size: 10px;
213 font-weight: 600;
214 margin-left: 8px;
215 vertical-align: middle;
216 text-transform: uppercase;
217 letter-spacing: 0.5px;
218 }
219
220 .metasync-api-badge {
221 background: linear-gradient(135deg, #38bdf8 0%, #0ea5e9 100%);
222 box-shadow: 0 2px 4px rgba(14, 165, 233, 0.3);
223 }
224
225 .metasync-empty-state {
226 text-align: center;
227 padding: 60px 20px;
228 background: var(--dashboard-card-bg, #1a1f26);
229 border: 2px dashed var(--dashboard-border, #374151);
230 border-radius: 8px;
231 margin: 0;
232 }
233
234 .metasync-empty-state h3 {
235 color: var(--dashboard-text-primary, #ffffff);
236 margin-bottom: 10px;
237 font-size: 20px;
238 }
239
240 .metasync-empty-state p {
241 color: var(--dashboard-text-secondary, #9ca3af);
242 margin-bottom: 20px;
243 font-size: 14px;
244 }
245
246 @media (max-width: 1024px) {
247 .metasync-info-cards-grid {
248 grid-template-columns: 1fr;
249 }
250 }
251
252 @media (max-width: 782px) {
253 .metasync-pages-table table {
254 font-size: 12px;
255 }
256
257 .metasync-pages-table th,
258 .metasync-pages-table td {
259 padding: 10px 8px;
260 }
261
262 .metasync-page-actions .button {
263 margin-bottom: 5px;
264 }
265 }
266 </style>
267 <?php
268 }
269
270 /**
271 * Render pages table
272 */
273 private static function render_pages_table()
274 {
275 $pages = Metasync_Custom_Pages::get_custom_pages();
276
277 ?>
278 <div class="metasync-pages-table">
279 <h2>Your Custom Pages</h2>
280
281 <?php if (empty($pages)): ?>
282 <div class="metasync-empty-state">
283 <h3>📄 No Custom HTML Pages Yet</h3>
284 <p>Create your first custom HTML page to get started!</p>
285 <a href="<?php echo esc_url(admin_url('post-new.php?post_type=page&metasync_html_page=1')); ?>"
286 class="button button-primary button-large">
287 <span class="dashicons dashicons-plus-alt"></span>
288 Create Your First Custom HTML Page
289 </a>
290 <p style="margin-top: 15px; color: #666; font-size: 13px;">
291 Pages created here will have the Custom HTML Settings panel for uploading/editing HTML.
292 </p>
293 </div>
294 <?php else: ?>
295 <table>
296 <thead>
297 <tr>
298 <th style="width: 40%;">Page Title</th>
299 <th style="width: 25%;">URL</th>
300 <th style="width: 15%;">Status</th>
301 <th style="width: 20%;">Actions</th>
302 </tr>
303 </thead>
304 <tbody>
305 <?php foreach ($pages as $page):
306 $html_enabled = get_post_meta($page->ID, Metasync_Custom_Pages::META_HTML_ENABLED, true);
307 $created_via_api = get_post_meta($page->ID, Metasync_Custom_Pages::META_CREATED_VIA_API, true);
308 $page_url = get_permalink($page->ID);
309 $edit_url = get_edit_post_link($page->ID);
310 ?>
311 <tr>
312 <td>
313 <strong>
314 <a href="<?php echo esc_url($edit_url); ?>">
315 <?php echo esc_html($page->post_title ?: '(No title)'); ?>
316 </a>
317 </strong>
318 <?php if ($created_via_api === '1'): ?>
319 <span class="metasync-html-badge metasync-api-badge" title="This page was created through the MetaSync REST API">API</span>
320 <?php endif; ?>
321 <?php if ($html_enabled === '1'): ?>
322 <span class="metasync-html-badge" title="This page uses Raw HTML mode: its content is edited as raw HTML instead of the block editor">RAW HTML</span>
323 <?php endif; ?>
324 </td>
325 <td>
326 <a href="<?php echo esc_url($page_url); ?>"
327 target="_blank"
328 class="metasync-page-url">
329 <?php echo esc_html(wp_make_link_relative($page_url)); ?>
330 <span class="dashicons dashicons-external" style="font-size: 14px;"></span>
331 </a>
332 </td>
333 <td>
334 <?php
335 $status_labels = array(
336 'publish' => 'Published',
337 'draft' => 'Draft',
338 'pending' => 'Pending Review',
339 'private' => 'Private',
340 );
341 $status_label = isset($status_labels[$page->post_status])
342 ? $status_labels[$page->post_status]
343 : ucfirst($page->post_status);
344 ?>
345 <span class="metasync-page-status metasync-status-<?php echo esc_attr($page->post_status); ?>">
346 <?php echo esc_html($status_label); ?>
347 </span>
348 </td>
349 <td class="metasync-page-actions">
350 <a href="<?php echo esc_url($edit_url); ?>" class="button button-small">
351 <span class="dashicons dashicons-edit"></span>
352 Edit
353 </a>
354 <?php if ($page->post_status === 'publish'): ?>
355 <a href="<?php echo esc_url($page_url); ?>"
356 target="_blank"
357 class="button button-small button-primary">
358 <span class="dashicons dashicons-external"></span>
359 View
360 </a>
361 <?php else: ?>
362 <a href="<?php echo esc_url(add_query_arg('preview', 'true', $page_url)); ?>"
363 target="_blank"
364 class="button button-small">
365 <span class="dashicons dashicons-visibility"></span>
366 Preview
367 </a>
368 <?php endif; ?>
369 </td>
370 </tr>
371 <?php endforeach; ?>
372 </tbody>
373 </table>
374 <?php endif; ?>
375 </div>
376 <?php
377 }
378
379 /**
380 * Handle admin actions
381 */
382 private static function handle_actions()
383 {
384 // Handle any custom actions here (bulk delete, etc.)
385 if (!isset($_GET['action'])) {
386 return;
387 }
388
389 // Verify nonce
390 if (!isset($_GET['_wpnonce']) || !wp_verify_nonce($_GET['_wpnonce'], 'metasync_custom_pages_action')) {
391 return;
392 }
393
394 $action = sanitize_text_field(wp_unslash($_GET['action']));
395
396 switch ($action) {
397 case 'delete':
398 if (isset($_GET['page_id'])) {
399 $page_id = intval($_GET['page_id']);
400 if (current_user_can('delete_post', $page_id)) {
401 wp_delete_post($page_id, true);
402 add_settings_error(
403 'metasync_custom_pages',
404 'page_deleted',
405 'Custom page deleted successfully.',
406 'success'
407 );
408 }
409 }
410 break;
411 }
412 }
413
414 /**
415 * Render admin notices
416 */
417 private static function render_notice()
418 {
419 settings_errors('metasync_custom_pages');
420 }
421 }
422
423