PluginProbe
Search Atlas SEO – OTTO AI SEO Automation for WordPress / 2.5.23
Search Atlas SEO – OTTO AI SEO Automation for WordPress v2.5.23
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 / includes / class-metasync-setup-wizard.php

class-metasync-setup-wizard.php in Search Atlas SEO – OTTO AI SEO Automation for WordPress 2.5.23, at includes/class-metasync-setup-wizard.php

549 lines 15.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * The setup wizard functionality of the plugin
5 *
6 * @link https://searchatlas.com
7 * @since 1.0.0
8 *
9 * @package Metasync
10 * @subpackage Metasync/includes
11 */
12
13 /**
14 * The setup wizard class.
15 *
16 * This class handles the setup wizard functionality for first-time plugin setup.
17 * Guides users through connecting the platform, importing from other SEO plugins,
18 * and configuring basic SEO settings.
19 *
20 * @since 1.0.0
21 * @package Metasync
22 * @subpackage Metasync/includes
23 * @author Engineering Team <support@searchatlas.com>
24 */
25 class Metasync_Setup_Wizard
26 {
27 /**
28 * The ID of this plugin.
29 *
30 * @since 1.0.0
31 * @access private
32 * @var string $plugin_name The ID of this plugin.
33 */
34 private $plugin_name;
35
36 /**
37 * The version of this plugin.
38 *
39 * @since 1.0.0
40 * @access private
41 * @var string $version The current version of this plugin.
42 */
43 private $version;
44
45 /**
46 * Total number of wizard steps
47 *
48 * @since 1.0.0
49 * @access private
50 * @var int
51 */
52 private $total_steps = 6;
53
54 /**
55 * Initialize the class and set its properties.
56 *
57 * @since 1.0.0
58 * @param string $plugin_name The name of this plugin.
59 * @param string $version The version of this plugin.
60 */
61 public function __construct($plugin_name, $version)
62 {
63 $this->plugin_name = $plugin_name;
64 $this->version = $version;
65 }
66
67 /**
68 * Check if wizard should auto-launch
69 *
70 * @since 1.0.0
71 * @return boolean
72 */
73 public function should_auto_launch_wizard()
74 {
75 // Check if wizard has been completed
76 $wizard_completed = get_option('metasync_wizard_completed', false);
77
78 if ($wizard_completed && !empty($wizard_completed['completed'])) {
79 return false;
80 }
81
82 // Check if first activation flag is set
83 return get_option('metasync_show_wizard', false);
84 }
85
86 /**
87 * Render the setup wizard page
88 *
89 * @since 1.0.0
90 */
91 public function render_wizard_page()
92 {
93 // Check user has access
94 if (!Metasync::current_user_has_plugin_access()) {
95 wp_die(__('You do not have sufficient permissions to access this page.'));
96 }
97
98 // Get current wizard state
99 $user_id = get_current_user_id();
100 $wizard_state = get_transient("metasync_wizard_state_{$user_id}");
101
102 if (!$wizard_state) {
103 // Initialize wizard state
104 $wizard_state = array(
105 'current_step' => 1,
106 'completed_steps' => array(),
107 'started_at' => time(),
108 'user_id' => $user_id
109 );
110 set_transient("metasync_wizard_state_{$user_id}", $wizard_state, DAY_IN_SECONDS);
111 }
112
113 // Load wizard template
114 require_once plugin_dir_path(dirname(__FILE__)) . 'views/metasync-setup-wizard.php';
115 }
116
117 /**
118 * Get all wizard steps configuration
119 *
120 * @since 1.0.0
121 * @return array
122 */
123 private function get_wizard_steps()
124 {
125 return array(
126 1 => array(
127 'id' => 'welcome',
128 'title' => 'Welcome',
129 'description' => 'Welcome to MetaSync'
130 ),
131 2 => array(
132 'id' => 'connection',
133 'title' => 'Connect',
134 'description' => 'Connect to platform'
135 ),
136 3 => array(
137 'id' => 'import',
138 'title' => 'Import',
139 'description' => 'Import from other plugins'
140 ),
141 4 => array(
142 'id' => 'seo_settings',
143 'title' => 'SEO Settings',
144 'description' => 'Configure indexation'
145 ),
146 5 => array(
147 'id' => 'schema',
148 'title' => 'Schema',
149 'description' => 'Schema preferences'
150 ),
151 6 => array(
152 'id' => 'complete',
153 'title' => 'Complete',
154 'description' => 'Setup complete'
155 )
156 );
157 }
158
159 /**
160 * Render Step 1: Welcome Screen
161 *
162 * @since 1.0.0
163 */
164 public function render_step_welcome()
165 {
166 $plugin_name = Metasync::get_effective_plugin_name();
167 ?>
168 <div class="wizard-step wizard-step-welcome active" data-step="1">
169 <div class="wizard-step-header">
170 <h2>🎉 Welcome to <?php echo esc_html($plugin_name); ?>!</h2>
171 <p>Let's get your site optimized for search engines in just a few minutes.</p>
172 </div>
173
174 <div class="wizard-step-content">
175 <div class="wizard-benefits">
176 <div class="wizard-benefit-card">
177 <span class="benefit-icon">🚀</span>
178 <h3>Automated SEO</h3>
179 <p>Automatically optimize your content for search engines</p>
180 </div>
181 <div class="wizard-benefit-card">
182 <span class="benefit-icon">📊</span>
183 <h3>Performance Tracking</h3>
184 <p>Monitor your site's search performance in real-time</p>
185 </div>
186 <div class="wizard-benefit-card">
187 <span class="benefit-icon">🔗</span>
188 <h3>Seamless Integration</h3>
189 <p>Connect with <?php echo esc_html($plugin_name); ?> for advanced features</p>
190 </div>
191 </div>
192
193 <div class="wizard-time-estimate">
194 <span>⏱️ Estimated time: 3-5 minutes</span>
195 </div>
196 </div>
197 </div>
198 <?php
199 }
200
201 /**
202 * Render Step 2: Connection
203 *
204 * @since 1.0.0
205 */
206 public function render_step_connection()
207 {
208 $plugin_name = Metasync::get_effective_plugin_name();
209 $general_settings = Metasync::get_option('general');
210 $is_connected = !empty($general_settings['searchatlas_api_key']);
211 ?>
212 <div class="wizard-step wizard-step-connection" data-step="2">
213 <div class="wizard-step-header">
214 <h2>🔗 Connect to <?php echo esc_html($plugin_name); ?></h2>
215 <p>Link your WordPress site to your <?php echo esc_html($plugin_name); ?> account for advanced features.</p>
216 </div>
217
218 <div class="wizard-step-content">
219 <?php if (!$is_connected): ?>
220 <div class="wizard-connection-box">
221 <p><strong>Why connect?</strong></p>
222 <ul>
223 <li>Access OTTO AI-powered SEO assistant</li>
224 <li>Get real-time search ranking data</li>
225 <li>Receive automated optimization suggestions</li>
226 </ul>
227
228 <button id="wizard-connect-btn" class="wizard-primary-btn">
229 Connect with <?php echo esc_html($plugin_name); ?>
230 </button>
231 </div>
232 <?php else: ?>
233 <div class="wizard-connection-success">
234 <span class="success-icon"></span>
235 <h3>Successfully Connected!</h3>
236 <p>Your site is linked to <?php echo esc_html($plugin_name); ?>.</p>
237 </div>
238 <?php endif; ?>
239 </div>
240 </div>
241 <?php
242 }
243
244 /**
245 * Render Step 3: Plugin Import
246 *
247 * @since 1.0.0
248 */
249 public function render_step_import()
250 {
251 $installed_plugins = $this->detect_seo_plugins();
252 ?>
253 <div class="wizard-step wizard-step-import" data-step="3">
254 <div class="wizard-step-header">
255 <h2>📥 Import from Other SEO Plugins</h2>
256 <p>We detected other SEO plugins. Import your existing settings to save time.</p>
257 </div>
258
259 <div class="wizard-step-content">
260 <?php if (!empty($installed_plugins)): ?>
261 <div class="wizard-import-grid">
262 <?php foreach ($installed_plugins as $plugin): ?>
263 <div class="wizard-import-card">
264 <div class="import-card-header">
265 <h3><?php echo esc_html($plugin['name']); ?></h3>
266 <span class="import-badge">Detected</span>
267 </div>
268
269 <div class="import-card-options">
270 <label>
271 <input type="checkbox" class="import-option"
272 data-plugin="<?php echo esc_attr($plugin['slug']); ?>"
273 data-type="robots">
274 Robots.txt
275 </label>
276 <label>
277 <input type="checkbox" class="import-option"
278 data-plugin="<?php echo esc_attr($plugin['slug']); ?>"
279 data-type="sitemap">
280 Sitemap Settings
281 </label>
282 <label>
283 <input type="checkbox" class="import-option"
284 data-plugin="<?php echo esc_attr($plugin['slug']); ?>"
285 data-type="redirections">
286 Redirections
287 </label>
288 <label>
289 <input type="checkbox" class="import-option"
290 data-plugin="<?php echo esc_attr($plugin['slug']); ?>"
291 data-type="indexation">
292 Indexation/Robots Meta
293 </label>
294 <label>
295 <input type="checkbox" class="import-option"
296 data-plugin="<?php echo esc_attr($plugin['slug']); ?>"
297 data-type="schema">
298 Schema Markup
299 </label>
300 </div>
301
302 <div class="import-card-footer">
303 <button class="wizard-import-btn"
304 data-plugin="<?php echo esc_attr($plugin['slug']); ?>">
305 Import Selected
306 </button>
307 <div class="import-progress" style="display:none;">
308 <div class="import-progress-bar"></div>
309 <span class="import-progress-text">Importing...</span>
310 </div>
311 </div>
312 </div>
313 <?php endforeach; ?>
314 </div>
315 <?php else: ?>
316 <div class="wizard-no-imports">
317 <p>No compatible SEO plugins detected. You can skip this step.</p>
318 </div>
319 <?php endif; ?>
320 </div>
321 </div>
322 <?php
323 }
324
325
326 /**
327 * Render Step 4: SEO Settings (Indexation Controls)
328 *
329 * @since 1.0.0
330 */
331 public function render_step_seo_settings()
332 {
333 $seo_controls = Metasync::get_option('seo_controls') ?: array();
334 ?>
335 <div class="wizard-step wizard-step-seo" data-step="4">
336 <div class="wizard-step-header">
337 <h2>🚀 Basic SEO Settings</h2>
338 <p>Choose which archive types should be indexed by search engines.</p>
339 </div>
340
341 <div class="wizard-step-content">
342 <div class="wizard-seo-grid">
343 <div class="wizard-seo-card">
344 <h3>�
345 Archive Types</h3>
346 <p>Control which WordPress archives are visible to search engines.</p>
347
348 <div class="wizard-toggle-group">
349 <label class="wizard-toggle-label">
350 <input type="checkbox" name="seo_date_archives"
351 <?php checked(!isset($seo_controls['index_date_archives']) || $seo_controls['index_date_archives'] !== 'true'); ?>>
352 <span>Index Date Archives</span>
353 </label>
354
355 <label class="wizard-toggle-label">
356 <input type="checkbox" name="seo_author_archives"
357 <?php checked(!isset($seo_controls['index_author_archives']) || $seo_controls['index_author_archives'] !== 'true'); ?>>
358 <span>Index Author Archives</span>
359 </label>
360
361 <label class="wizard-toggle-label">
362 <input type="checkbox" name="seo_category_archives"
363 <?php checked(!isset($seo_controls['index_category_archives']) || $seo_controls['index_category_archives'] !== 'true'); ?>>
364 <span>Index Category Archives</span>
365 </label>
366
367 <label class="wizard-toggle-label">
368 <input type="checkbox" name="seo_tag_archives"
369 <?php checked(!isset($seo_controls['index_tag_archives']) || $seo_controls['index_tag_archives'] !== 'true'); ?>>
370 <span>Index Tag Archives</span>
371 </label>
372 </div>
373 </div>
374
375 <div class="wizard-recommendation-box">
376 <h4>💡 Recommended Settings</h4>
377 <p>For most sites, we recommend:</p>
378 <ul>
379 <li> Index Category and Tag archives (helps with SEO)</li>
380 <li> Noindex Date archives (usually duplicate content)</li>
381 <li> Noindex Author archives (unless multi-author blog)</li>
382 </ul>
383 <button class="wizard-apply-recommended">Apply Recommended</button>
384 </div>
385 </div>
386 </div>
387 </div>
388 <?php
389 }
390
391 /**
392 * Render Step 5: Schema Preferences
393 *
394 * @since 1.0.0
395 */
396 public function render_step_schema()
397 {
398 $general_settings = Metasync::get_option('general');
399 $schema_enabled = !empty($general_settings['enable_schema_markup']);
400 ?>
401 <div class="wizard-step wizard-step-schema" data-step="5">
402 <div class="wizard-step-header">
403 <h2>📋 Schema Markup Preferences</h2>
404 <p>Configure structured data to help search engines understand your content.</p>
405 </div>
406
407 <div class="wizard-step-content">
408 <div class="wizard-schema-enable">
409 <label class="wizard-toggle-label-large">
410 <input type="checkbox" id="schema-enabled" name="schema_enabled"
411 <?php checked($schema_enabled); ?>>
412 <span>Enable Automatic Schema Markup</span>
413 </label>
414 <p class="wizard-field-help">
415 Schema markup helps search engines display rich snippets in search results.
416 </p>
417 </div>
418
419 <div class="wizard-schema-settings" style="display: <?php echo $schema_enabled ? 'block' : 'none'; ?>;">
420 <h3>Default Schema Types</h3>
421
422 <div class="wizard-schema-types">
423 <label class="wizard-schema-type-card">
424 <input type="radio" name="default_schema_type" value="article"
425 <?php checked(($general_settings['default_schema_type'] ?? 'article') === 'article'); ?>>
426 <div class="schema-type-content">
427 <span class="schema-type-icon">📰</span>
428 <h4>Article</h4>
429 <p>Best for blog posts and news articles</p>
430 </div>
431 </label>
432
433 <label class="wizard-schema-type-card">
434 <input type="radio" name="default_schema_type" value="webpage"
435 <?php checked(($general_settings['default_schema_type'] ?? '') === 'webpage'); ?>>
436 <div class="schema-type-content">
437 <span class="schema-type-icon">📄</span>
438 <h4>WebPage</h4>
439 <p>Best for general website pages</p>
440 </div>
441 </label>
442
443 <label class="wizard-schema-type-card">
444 <input type="radio" name="default_schema_type" value="product"
445 <?php checked(($general_settings['default_schema_type'] ?? '') === 'product'); ?>>
446 <div class="schema-type-content">
447 <span class="schema-type-icon">🛍</span>
448 <h4>Product</h4>
449 <p>Best for e-commerce sites</p>
450 </div>
451 </label>
452 </div>
453 </div>
454 </div>
455 </div>
456 <?php
457 }
458
459 /**
460 * Render Step 7: Completion Screen
461 *
462 * @since 1.0.0
463 */
464 public function render_step_complete()
465 {
466 $menu_slug = 'searchatlas';
467 $data = Metasync::get_option('general');
468 if (!empty($data['white_label_plugin_menu_slug'])) {
469 $menu_slug = $data['white_label_plugin_menu_slug'];
470 }
471 ?>
472 <div class="wizard-step wizard-step-complete" data-step="6">
473 <div class="wizard-step-header">
474 <div class="wizard-complete-icon">🎉</div>
475 <h2>Setup Complete!</h2>
476 <p>Your site is now optimized for search engines.</p>
477 </div>
478
479 <div class="wizard-step-content">
480 <div class="wizard-complete-summary">
481 <h3>What's Next?</h3>
482
483 <div class="wizard-next-steps">
484 <div class="wizard-next-step-card">
485 <span class="next-step-number">1</span>
486 <div class="next-step-content">
487 <h4>Explore the Dashboard</h4>
488 <p>View your SEO performance metrics and insights</p>
489 <a href="?page=<?php echo esc_attr($menu_slug); ?>-dashboard"
490 class="wizard-next-step-link">View Dashboard →</a>
491 </div>
492 </div>
493
494 <div class="wizard-next-step-card">
495 <span class="next-step-number">2</span>
496 <div class="next-step-content">
497 <h4>Optimize Your Content</h4>
498 <p>Start optimizing individual posts and pages</p>
499 <a href="<?php echo esc_url(admin_url('edit.php')); ?>"
500 class="wizard-next-step-link">View Posts →</a>
501 </div>
502 </div>
503
504 <div class="wizard-next-step-card">
505 <span class="next-step-number">3</span>
506 <div class="next-step-content">
507 <h4>Fine-Tune Settings</h4>
508 <p>Adjust advanced SEO settings for your specific needs</p>
509 <a href="?page=<?php echo esc_attr($menu_slug); ?>"
510 class="wizard-next-step-link">View Settings →</a>
511 </div>
512 </div>
513 </div>
514 </div>
515
516 <div class="wizard-complete-actions">
517 <button class="wizard-primary-btn wizard-complete-btn">
518 Get Started with <?php echo esc_html(Metasync::get_effective_plugin_name()); ?>
519 </button>
520 </div>
521 </div>
522 </div>
523 <?php
524 }
525
526 /**
527 * Detect installed SEO plugins
528 *
529 * @since 1.0.0
530 * @return array
531 */
532 private function detect_seo_plugins()
533 {
534 $detected = array();
535
536 if (defined('WPSEO_VERSION')) {
537 $detected[] = array('name' => 'Yoast SEO', 'slug' => 'yoast');
538 }
539 if (defined('RANK_MATH_VERSION')) {
540 $detected[] = array('name' => 'Rank Math', 'slug' => 'rankmath');
541 }
542 if (defined('AIOSEO_VERSION')) {
543 $detected[] = array('name' => 'All in One SEO', 'slug' => 'aioseo');
544 }
545
546 return $detected;
547 }
548 }
549