PluginProbe ʕ •ᴥ•ʔ
Rank Math SEO – AI SEO Tools to Dominate SEO Rankings / 1.0.257
Rank Math SEO – AI SEO Tools to Dominate SEO Rankings v1.0.257
1.0.271 1.0.271.1 1.0.270 1.0.269 trunk 1.0.216 1.0.217 1.0.218 1.0.219 1.0.220 1.0.221 1.0.222 1.0.223 1.0.224 1.0.225 1.0.226 1.0.227 1.0.227.1 1.0.228 1.0.229 1.0.230 1.0.231 1.0.232 1.0.233 1.0.234 1.0.234.1 1.0.235 1.0.236 1.0.237 1.0.238 1.0.239 1.0.240 1.0.241 1.0.242 1.0.243 1.0.244 1.0.245 1.0.246 1.0.247 1.0.248 1.0.249 1.0.250 1.0.251 1.0.251.1 1.0.252 1.0.252.1 1.0.253 1.0.254 1.0.255 1.0.256 1.0.257 1.0.258 1.0.259 1.0.259.1 1.0.260 1.0.261 1.0.262 1.0.263 1.0.264 1.0.264.1 1.0.265 1.0.266 1.0.266.1 1.0.267 1.0.268
seo-by-rank-math / includes / class-installer.php
seo-by-rank-math / includes Last commit date
3rdparty 7 months ago admin 7 months ago cli 5 years ago frontend 8 months ago helpers 7 months ago metaboxes 2 years ago module 7 months ago modules 7 months ago opengraph 9 months ago replace-variables 7 months ago rest 8 months ago settings 9 months ago traits 8 months ago updates 8 months ago class-auto-updater.php 5 years ago class-cmb2.php 2 years ago class-common.php 1 year ago class-compatibility.php 1 year ago class-data-encryption.php 1 year ago class-defaults.php 6 years ago class-frontend-seo-score.php 1 year ago class-helper.php 10 months ago class-installer.php 7 months ago class-json-manager.php 1 year ago class-kb.php 7 months ago class-metadata.php 1 year ago class-post.php 1 year ago class-rewrite.php 10 months ago class-settings.php 1 year ago class-term.php 1 year ago class-thumbnail-overlay.php 1 year ago class-tracking.php 7 months ago class-update-email.php 3 years ago class-updates.php 8 months ago class-user.php 8 months ago index.php 7 years ago interface-runner.php 7 years ago template-tags.php 1 year ago
class-installer.php
735 lines
1 <?php
2 /**
3 * Plugin activation and deactivation functionality.
4 *
5 * This class defines all code necessary to run during the plugin's activation.
6 *
7 * @since 0.9.0
8 * @package RankMath
9 * @subpackage RankMath\Core
10 * @author Rank Math <support@rankmath.com>
11 */
12
13 namespace RankMath;
14
15 use RankMath\Traits\Hooker;
16 use RankMath\Admin\Watcher;
17 use RankMath\Helper;
18 use RankMath\Helpers\DB as DB_Helper;
19 use RankMath\Admin\Admin_Helper;
20 use RankMath\Role_Manager\Capability_Manager;
21
22 defined( 'ABSPATH' ) || exit;
23
24 /**
25 * Installer class.
26 */
27 class Installer {
28
29 use Hooker;
30
31 /**
32 * Bind all events.
33 */
34 public function __construct() {
35 register_activation_hook( RANK_MATH_FILE, [ $this, 'activation' ] );
36 register_deactivation_hook( RANK_MATH_FILE, [ $this, 'deactivation' ] );
37
38 $this->action( 'wp', 'create_cron_jobs' );
39 $this->action( 'wp_initialize_site', 'initialize_site' );
40 $this->filter( 'wpmu_drop_tables', 'on_delete_blog' );
41 }
42
43 /**
44 * Do things when activating Rank Math.
45 *
46 * @param bool $network_wide Whether the plugin is being activated network-wide.
47 */
48 public function activation( $network_wide = false ) {
49 if ( ! is_multisite() || ! $network_wide ) {
50 $this->activate();
51 return;
52 }
53
54 $this->network_activate_deactivate( true );
55 }
56
57 /**
58 * Do things when deactivating Rank Math.
59 *
60 * @param bool $network_wide Whether the plugin is being activated network-wide.
61 */
62 public function deactivation( $network_wide = false ) {
63 if ( ! is_multisite() || ! $network_wide ) {
64 $this->deactivate();
65 return;
66 }
67
68 $this->network_activate_deactivate( false );
69 }
70
71 /**
72 * Fired when a new site is activated with a WPMU environment.
73 *
74 * @param WP_Site $site The new site's object.
75 */
76 public function initialize_site( $site ) {
77 switch_to_blog( $site->blog_id );
78 $this->activate();
79 restore_current_blog();
80 }
81
82 /**
83 * Uninstall tables when MU blog is deleted.
84 *
85 * @param array $tables List of tables that will be deleted by WP.
86 * @return array
87 */
88 public function on_delete_blog( $tables ) {
89 global $wpdb;
90
91 $tables[] = $wpdb->prefix . 'rank_math_404_logs';
92 $tables[] = $wpdb->prefix . 'rank_math_redirections';
93 $tables[] = $wpdb->prefix . 'rank_math_redirections_cache';
94 $tables[] = $wpdb->prefix . 'rank_math_internal_links';
95 $tables[] = $wpdb->prefix . 'rank_math_internal_meta';
96 $tables[] = $wpdb->prefix . 'rank_math_analytics_gsc';
97 $tables[] = $wpdb->prefix . 'rank_math_analytics_objects';
98 $tables[] = $wpdb->prefix . 'rank_math_analytics_inspections';
99
100 return $tables;
101 }
102
103 /**
104 * Run network-wide activation/deactivation of the plugin.
105 *
106 * @param bool $activate True for plugin activation, false for de-activation.
107 *
108 * @copyright Copyright (C) 2008-2019, Yoast BV
109 * The following code is a derivative work of the code from the Yoast(https://github.com/Yoast/wordpress-seo/), which is licensed under GPL v3.
110 */
111 private function network_activate_deactivate( $activate ) {
112 global $wpdb;
113
114 $blog_ids = DB_Helper::get_col( "SELECT blog_id FROM $wpdb->blogs WHERE archived = '0' AND spam = '0' AND deleted = '0'" );
115 if ( empty( $blog_ids ) ) {
116 return;
117 }
118
119 foreach ( $blog_ids as $blog_id ) {
120 $func = true === $activate ? 'activate' : 'deactivate';
121
122 switch_to_blog( $blog_id );
123 $this->$func();
124 restore_current_blog();
125 }
126 }
127
128 /**
129 * Plugin activation callback.
130 */
131 private function activate() {
132 // Init to use the common filters.
133 new \RankMath\Defaults();
134
135 $current_version = get_option( 'rank_math_version', null );
136 $current_db_version = get_option( 'rank_math_db_version', null );
137
138 $this->create_options();
139 $this->set_capabilities();
140 $this->create_cron_jobs();
141
142 if ( is_null( $current_version ) && is_null( $current_db_version ) ) {
143 set_transient( '_rank_math_activation_redirect', 1, 30 );
144 }
145
146 // Update to latest version.
147 update_option( 'rank_math_version', rank_math()->version );
148 update_option( 'rank_math_db_version', rank_math()->db_version );
149
150 // Clear rollback option if necessary.
151 if ( rank_math()->version !== get_option( 'rank_math_rollback_version' ) ) {
152 delete_option( 'rank_math_rollback_version' );
153 }
154
155 // Save install date.
156 if ( false === boolval( get_option( 'rank_math_install_date' ) ) ) {
157 update_option( 'rank_math_install_date', Helper::get_current_time() );
158 }
159
160 // Activate Watcher.
161 $watcher = new Watcher();
162 $watcher->check_activated_plugin();
163 $watcher->check_search_engine_visibility( ! get_option( 'blog_public' ) );
164
165 $this->clear_rewrite_rules( true );
166 Helper::clear_cache( 'activate' );
167
168 $this->do_action( 'activate' );
169 }
170
171 /**
172 * Runs on deactivation of the plugin.
173 */
174 private function deactivate() {
175 $this->clear_rewrite_rules( false );
176 $this->remove_cron_jobs();
177 Helper::clear_cache( 'deactivate' );
178 Admin_Helper::deregister_user();
179 $this->do_action( 'deactivate' );
180 }
181
182 /**
183 * Set up the database tables.
184 *
185 * @param mixed $modules Modules to create tables for.
186 * @return void
187 */
188 public static function create_tables( $modules = [] ) {
189 global $wpdb;
190
191 $tables = [];
192
193 if ( in_array( '404-monitor', $modules, true ) ) {
194 $tables['404-monitor'] = [
195 'rank_math_404_logs' => "id bigint(20) unsigned NOT NULL auto_increment,
196 uri varchar(255) NOT NULL,
197 accessed datetime NOT NULL default '0000-00-00 00:00:00',
198 times_accessed bigint(20) unsigned NOT NULL default 1,
199 referer varchar(255) NOT NULL default '',
200 user_agent varchar(255) NOT NULL default '',
201 PRIMARY KEY (id),
202 KEY uri (uri(191))",
203 ];
204 }
205
206 if ( in_array( 'redirections', $modules, true ) ) {
207 $tables['redirections'] = [
208 'rank_math_redirections' => "id bigint(20) unsigned NOT NULL auto_increment,
209 sources longtext CHARACTER SET {$wpdb->charset} COLLATE {$wpdb->charset}_bin NOT NULL,
210 url_to text NOT NULL,
211 header_code smallint(4) unsigned NOT NULL,
212 hits bigint(20) unsigned NOT NULL default '0',
213 status varchar(25) NOT NULL default 'active',
214 created datetime NOT NULL default '0000-00-00 00:00:00',
215 updated datetime NOT NULL default '0000-00-00 00:00:00',
216 last_accessed datetime NOT NULL default '0000-00-00 00:00:00',
217 PRIMARY KEY (id),
218 KEY status (status)",
219 'rank_math_redirections_cache' => "id bigint(20) unsigned NOT NULL auto_increment,
220 from_url text CHARACTER SET {$wpdb->charset} COLLATE {$wpdb->charset}_bin NOT NULL,
221 redirection_id bigint(20) unsigned NOT NULL,
222 object_id bigint(20) unsigned NOT NULL default '0',
223 object_type varchar(10) NOT NULL default 'post',
224 is_redirected tinyint(1) NOT NULL default '0',
225 PRIMARY KEY (id),
226 KEY redirection_id (redirection_id)",
227 ];
228 }
229
230 if ( in_array( 'link-counter', $modules, true ) ) {
231 $tables['link-counter'] = [
232 'rank_math_internal_links' => 'id bigint(20) unsigned NOT NULL auto_increment,
233 url varchar(255) NOT NULL,
234 post_id bigint(20) unsigned NOT NULL,
235 target_post_id bigint(20) unsigned NOT NULL,
236 type varchar(8) NOT NULL,
237 PRIMARY KEY (id),
238 KEY link_direction (post_id, type),
239 KEY target_post_id (target_post_id)',
240 'rank_math_internal_meta' => 'object_id bigint(20) unsigned NOT NULL,
241 internal_link_count int(10) unsigned NULL default 0,
242 external_link_count int(10) unsigned NULL default 0,
243 incoming_link_count int(10) unsigned NULL default 0,
244 PRIMARY KEY (object_id)',
245 ];
246 }
247
248 $tables = apply_filters( 'rank_math/admin/create_tables', $tables, $modules );
249 $old_schema = self::is_old_schema( $tables );
250
251 if ( $old_schema ) {
252 _deprecated_hook(
253 'rank_math/admin/create_tables',
254 '1.0.253',
255 'rank_math/admin/create_tables',
256 esc_html__( 'The format of the tables array has changed. Please update your code accordingly.', 'rank-math' )
257 );
258 foreach ( $old_schema as $query ) {
259 if ( preg_match( '/CREATE TABLE\s+[`"]?([^`"\s]+)[`"]?/i', $query, $match ) ) {
260 $table_name = str_replace( $wpdb->prefix, '', $match[1] );
261 $schema = preg_replace( '/^CREATE TABLE\s+[`"]?[^`"\s]+[`"]?\s*\((.*)\)\s*.+$/is', '$1', $query );
262
263 DB_Helper::create_table( $table_name, $schema );
264 }
265 }
266 }
267
268 foreach ( $tables as $module => $table_group ) {
269 foreach ( $table_group as $table_name => $schema ) {
270 DB_Helper::create_table( $table_name, $schema );
271 }
272 }
273 }
274
275 /**
276 * Check if the schema is old style.
277 *
278 * @param array $arr Array of tables.
279 */
280 public static function is_old_schema( &$arr ) {
281 $schema = [];
282
283 foreach ( array_keys( $arr ) as $key ) {
284 if ( is_int( $key ) ) {
285 $schema[] = $arr[ $key ];
286
287 unset( $arr[ $key ] );
288 }
289 }
290
291 return $schema;
292 }
293
294 /**
295 * Create options.
296 */
297 private function create_options() {
298 $this->create_misc_options();
299 $this->create_general_options();
300 $this->create_titles_sitemaps_options();
301 $this->create_instant_indexing_options();
302 }
303
304 /**
305 * Create misc options.
306 */
307 private function create_misc_options() {
308 // Update "known CPTs" list, so we can send notice about new ones later.
309 add_option( 'rank_math_known_post_types', Helper::get_accessible_post_types() );
310
311 $modules = [
312 'link-counter',
313 'analytics',
314 'seo-analysis',
315 'sitemap',
316 'rich-snippet',
317 'woocommerce',
318 'buddypress',
319 'bbpress',
320 'acf',
321 'web-stories',
322 'content-ai',
323 'instant-indexing',
324 ];
325
326 // Role Manager.
327 $users = get_users( [ 'role__in' => [ 'administrator', 'editor', 'author', 'contributor' ] ] );
328 if ( count( $users ) > 1 ) {
329 $modules[] = 'role-manager';
330 }
331
332 // If AMP plugin is installed.
333 if ( function_exists( 'is_amp_endpoint' ) || class_exists( 'Better_AMP' ) || class_exists( 'Weeblramp_Api' ) || class_exists( 'AMPHTML' ) ) {
334 $modules[] = 'amp';
335 }
336
337 // If 404-monitor is active as plugin.
338 if ( false !== get_option( 'rank_math_monitor_version', false ) ) {
339 $modules[] = '404-monitor';
340 }
341
342 add_option( 'rank_math_modules', $modules );
343 add_option( 'rank_math_react_settings_ui', 'on', '', false );
344 self::create_tables( $modules );
345 }
346
347 /**
348 * Add defaults for general options.
349 */
350 private function create_general_options() {
351 $post_types = Helper::get_accessible_post_types();
352 if ( isset( $post_types['attachment'] ) ) {
353 unset( $post_types['attachment'] );
354 }
355
356 add_option(
357 'rank-math-options-general',
358 $this->do_filter(
359 'settings/defaults/general',
360 [
361 'strip_category_base' => 'off',
362 'attachment_redirect_urls' => 'on',
363 'attachment_redirect_default' => get_home_url(),
364 'nofollow_external_links' => 'off',
365 'nofollow_image_links' => 'off',
366 'new_window_external_links' => 'on',
367 'add_img_alt' => 'off',
368 'img_alt_format' => ' %filename%',
369 'add_img_title' => 'off',
370 'img_title_format' => '%title% %count(title)%',
371 'breadcrumbs' => 'off',
372 'breadcrumbs_separator' => '-',
373 'breadcrumbs_home' => 'on',
374 'breadcrumbs_home_label' => esc_html__( 'Home', 'rank-math' ),
375 /* translators: Archive title */
376 'breadcrumbs_archive_format' => esc_html__( 'Archives for %s', 'rank-math' ),
377 /* translators: Search query term */
378 'breadcrumbs_search_format' => esc_html__( 'Results for %s', 'rank-math' ),
379 'breadcrumbs_404_label' => esc_html__( '404 Error: page not found', 'rank-math' ),
380 'breadcrumbs_ancestor_categories' => 'off',
381 'breadcrumbs_blog_page' => 'off',
382 '404_monitor_mode' => 'simple',
383 '404_monitor_limit' => 100,
384 '404_monitor_ignore_query_parameters' => 'on',
385 'redirections_header_code' => '301',
386 'redirections_debug' => 'off',
387 'console_caching_control' => '90',
388 'console_email_reports' => 'on',
389 'console_email_frequency' => 'monthly',
390 'wc_remove_product_base' => 'off',
391 'wc_remove_category_base' => 'off',
392 'wc_remove_category_parent_slugs' => 'off',
393 'rss_before_content' => '',
394 'rss_after_content' => '',
395 'wc_remove_generator' => 'on',
396 'remove_shop_snippet_data' => 'on',
397 'frontend_seo_score' => 'off',
398 'frontend_seo_score_post_types' => [ 'post' ],
399 'frontend_seo_score_position' => 'top',
400 'setup_mode' => 'advanced',
401 'content_ai_post_types' => array_keys( $post_types ),
402 'content_ai_country' => 'all',
403 'content_ai_tone' => 'Formal',
404 'content_ai_audience' => 'General Audience',
405 'content_ai_language' => Helper::content_ai_default_language(),
406 'analytics_stats' => 'on',
407 'toc_block_title' => 'Table of Contents',
408 'toc_block_list_style' => 'ul',
409 'llms_post_types' => array_keys( $post_types ),
410 ]
411 )
412 );
413 }
414
415 /**
416 * Add default values.
417 */
418 private function create_titles_sitemaps_options() {
419 $sitemap = [
420 'items_per_page' => 200,
421 'include_images' => 'on',
422 'include_featured_image' => 'off',
423 'exclude_roles' => $this->get_excluded_roles(),
424 'html_sitemap' => 'on',
425 'html_sitemap_display' => 'shortcode',
426 'html_sitemap_sort' => 'published',
427 'html_sitemap_seo_titles' => 'titles',
428 'authors_sitemap' => 'on',
429 ];
430 $titles = [
431 'noindex_empty_taxonomies' => 'on',
432 'title_separator' => '-',
433 'capitalize_titles' => 'off',
434 'twitter_card_type' => 'summary_large_image',
435 'knowledgegraph_type' => class_exists( 'Easy_Digital_Downloads' ) || class_exists( 'WooCommerce' ) ? 'company' : 'person',
436 'knowledgegraph_name' => get_bloginfo( 'name' ),
437 'website_name' => get_bloginfo( 'name' ),
438 'local_business_type' => 'Organization',
439 'local_address_format' => '{address} {locality}, {region} {postalcode}',
440 'opening_hours' => $this->get_opening_hours(),
441 'opening_hours_format' => 'off',
442 'homepage_title' => '%sitename% %page% %sep% %sitedesc%',
443 'homepage_description' => '',
444 'homepage_custom_robots' => 'off',
445 'disable_author_archives' => 'off',
446 'url_author_base' => 'author',
447 'author_custom_robots' => 'on',
448 'author_robots' => [ 'noindex' ],
449 'author_archive_title' => '%name% %sep% %sitename% %page%',
450 'author_add_meta_box' => 'on',
451 'disable_date_archives' => 'on',
452 'date_archive_title' => '%date% %page% %sep% %sitename%',
453 'search_title' => '%search_query% %page% %sep% %sitename%',
454 '404_title' => 'Page Not Found %sep% %sitename%',
455 'date_archive_robots' => [ 'noindex' ],
456 'noindex_search' => 'on',
457 'noindex_archive_subpages' => 'off',
458 'noindex_password_protected' => 'off',
459 ];
460
461 $this->create_post_type_options( $titles, $sitemap );
462 $this->create_taxonomy_options( $titles, $sitemap );
463
464 add_option( 'rank-math-options-titles', $this->do_filter( 'settings/defaults/titles', $titles ) );
465 add_option( 'rank-math-options-sitemap', $this->do_filter( 'settings/defaults/sitemap', $sitemap ) );
466 }
467
468 /**
469 * Create post type options.
470 *
471 * @param array $titles Hold title settings.
472 * @param array $sitemap Hold sitemap settings.
473 */
474 private function create_post_type_options( &$titles, &$sitemap ) {
475 $post_types = Helper::get_accessible_post_types();
476 array_push( $post_types, 'product', 'web-story' );
477
478 $titles['pt_download_default_rich_snippet'] = 'product';
479 $titles['author_slack_enhanced_sharing'] = 'on';
480
481 foreach ( $post_types as $post_type ) {
482 $defaults = $this->get_post_type_defaults( $post_type );
483
484 $titles[ 'pt_' . $post_type . '_title' ] = '%title% %sep% %sitename%';
485 $titles[ 'pt_' . $post_type . '_description' ] = '%excerpt%';
486 $titles[ 'pt_' . $post_type . '_robots' ] = $defaults['robots'];
487 $titles[ 'pt_' . $post_type . '_custom_robots' ] = $defaults['is_custom'];
488 $titles[ 'pt_' . $post_type . '_default_rich_snippet' ] = $defaults['rich_snippet'];
489 $titles[ 'pt_' . $post_type . '_default_article_type' ] = $defaults['article_type'];
490 $titles[ 'pt_' . $post_type . '_default_snippet_name' ] = '%seo_title%';
491 $titles[ 'pt_' . $post_type . '_default_snippet_desc' ] = '%seo_description%';
492
493 if ( $this->has_archive( $post_type ) ) {
494 $titles[ 'pt_' . $post_type . '_archive_title' ] = '%title% %page% %sep% %sitename%';
495 }
496
497 // Slack enhanced sharing is off by default, except for posts, pages, products, and downloads.
498 $titles[ 'pt_' . $post_type . '_slack_enhanced_sharing' ] = 'off';
499 if ( in_array( $post_type, [ 'post', 'page', 'product', 'download' ], true ) ) {
500 $titles[ 'pt_' . $post_type . '_slack_enhanced_sharing' ] = 'on';
501 }
502
503 if ( in_array( $post_type, [ 'attachment', 'web-story' ], true ) ) {
504 $sitemap[ 'pt_' . $post_type . '_sitemap' ] = 'off';
505 $titles[ 'pt_' . $post_type . '_add_meta_box' ] = 'off';
506 continue;
507 }
508
509 $sitemap[ 'pt_' . $post_type . '_sitemap' ] = 'on';
510 $titles[ 'pt_' . $post_type . '_ls_use_fk' ] = 'titles';
511 $titles[ 'pt_' . $post_type . '_add_meta_box' ] = 'on';
512 $titles[ 'pt_' . $post_type . '_bulk_editing' ] = 'editing';
513 $titles[ 'pt_' . $post_type . '_link_suggestions' ] = 'on';
514
515 // Primary Taxonomy.
516 $taxonomy_hash = [
517 'post' => 'category',
518 'product' => 'product_cat',
519 ];
520
521 if ( isset( $taxonomy_hash[ $post_type ] ) ) {
522 $titles[ 'pt_' . $post_type . '_primary_taxonomy' ] = $taxonomy_hash[ $post_type ];
523 }
524 }
525 }
526
527 /**
528 * Get robots default for post type.
529 *
530 * @param string $post_type Post type.
531 * @return array
532 */
533 private function get_post_type_defaults( $post_type ) {
534 $rich_snippets = [
535 'post' => 'article',
536 'page' => 'article',
537 'product' => 'product',
538 'download' => 'product',
539 'web-story' => 'article',
540 ];
541
542 $defaults = [
543 'robots' => [ 'index' ],
544 'is_custom' => 'off',
545 'rich_snippet' => isset( $rich_snippets[ $post_type ] ) ? $rich_snippets[ $post_type ] : 'off',
546 'article_type' => 'post' === $post_type ? 'BlogPosting' : 'Article',
547 ];
548
549 if ( 'attachment' === $post_type ) {
550 $defaults['is_custom'] = 'on';
551 $defaults['robots'] = [ 'noindex' ];
552 }
553
554 return $defaults;
555 }
556
557 /**
558 * Check post type has archive.
559 *
560 * @param string $post_type Post type.
561 * @return bool
562 */
563 private function has_archive( $post_type ) {
564 $post_type_obj = get_post_type_object( $post_type );
565 return ! is_null( $post_type_obj ) && $post_type_obj->has_archive;
566 }
567
568 /**
569 * Create post type options.
570 *
571 * @param array $titles Hold title settings.
572 * @param array $sitemap Hold sitemap settings.
573 */
574 private function create_taxonomy_options( &$titles, &$sitemap ) {
575 $taxonomies = Helper::get_accessible_taxonomies();
576 foreach ( $taxonomies as $taxonomy => $object ) {
577 $defaults = $this->get_taxonomy_defaults( $taxonomy );
578
579 $titles[ 'tax_' . $taxonomy . '_title' ] = '%term% %sep% %sitename%';
580 $titles[ 'tax_' . $taxonomy . '_robots' ] = $defaults['robots'];
581 $titles[ 'tax_' . $taxonomy . '_add_meta_box' ] = $defaults['metabox'];
582 $titles[ 'tax_' . $taxonomy . '_custom_robots' ] = $defaults['is_custom'];
583 $titles[ 'tax_' . $taxonomy . '_description' ] = '%term_description%';
584 $titles[ 'tax_' . $taxonomy . '_slack_enhanced_sharing' ] = 'on';
585 $titles[ 'tax_' . $taxonomy . '_bulk_editing' ] = 0;
586
587 $sitemap[ 'tax_' . $taxonomy . '_sitemap' ] = 'category' === $taxonomy ? 'on' : 'off';
588
589 if ( substr( $taxonomy, 0, 3 ) === 'pa_' ) {
590 $titles[ 'remove_' . $taxonomy . '_snippet_data' ] = 'on';
591 }
592 }
593
594 $titles['remove_product_cat_snippet_data'] = 'on';
595 $titles['remove_product_tag_snippet_data'] = 'on';
596 }
597
598 /**
599 * Get robots default for post type.
600 *
601 * @param string $taxonomy Taxonomy.
602 * @return array
603 */
604 private function get_taxonomy_defaults( $taxonomy ) {
605 $defaults = [
606 'robots' => [ 'index' ],
607 'is_custom' => 'off',
608 'metabox' => 'category' === $taxonomy ? 'on' : 'off',
609 ];
610
611 if ( in_array( $taxonomy, [ 'post_tag', 'post_format', 'product_tag' ], true ) ) {
612 $defaults['is_custom'] = 'on';
613 $defaults['robots'] = [ 'noindex' ];
614 }
615
616 return $defaults;
617 }
618
619 /**
620 * Create capabilities.
621 */
622 private function set_capabilities() {
623 $admin = get_role( 'administrator' );
624 if ( ! is_null( $admin ) ) {
625 $admin->add_cap( 'rank_math_edit_htaccess', true );
626 }
627
628 Capability_Manager::get()->create_capabilities();
629 }
630
631 /**
632 * Create cron jobs.
633 */
634 public function create_cron_jobs() {
635 $midnight = strtotime( 'tomorrow midnight' );
636 foreach ( $this->get_cron_jobs() as $job => $recurrence ) {
637 if ( ! wp_next_scheduled( "rank_math/{$job}" ) ) {
638 $timestamp = 'content-ai/update_prompts' === $job ? $midnight + wp_rand( 60, 86400 ) : $midnight;
639 wp_schedule_event( $timestamp, $this->do_filter( "{$job}_recurrence", $recurrence ), "rank_math/{$job}" );
640 }
641 }
642 }
643
644 /**
645 * Remove cron jobs.
646 */
647 private function remove_cron_jobs() {
648 foreach ( $this->get_cron_jobs() as $job => $recurrence ) {
649 wp_clear_scheduled_hook( "rank_math/{$job}" );
650 }
651 }
652
653 /**
654 * Get cron jobs.
655 *
656 * @return array
657 */
658 private function get_cron_jobs() {
659 return [
660 'redirection/clean_trashed' => 'daily', // Add cron for cleaning trashed redirects.
661 'links/internal_links' => 'daily', // Add cron for counting links.
662 'content-ai/update_prompts' => 'daily', // Add cron for updating the prompts data.
663 ];
664 }
665
666 /**
667 * Get opening hours.
668 *
669 * @return array
670 */
671 private function get_opening_hours() {
672 $hours = [];
673 $days = [ 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday' ];
674 foreach ( $days as $day ) {
675 $hours[] = [
676 'day' => $day,
677 'time' => '09:00-17:00',
678 ];
679 }
680
681 return $hours;
682 }
683
684 /**
685 * Get roles to exclude.
686 *
687 * @return array
688 */
689 private function get_excluded_roles() {
690 $roles = Helper::get_roles();
691 unset( $roles['administrator'], $roles['editor'], $roles['author'] );
692
693 return array_keys( $roles );
694 }
695
696 /**
697 * Clear rewrite rules.
698 *
699 * @param bool $activate True for plugin activation, false for de-activation.
700 */
701 private function clear_rewrite_rules( $activate ) {
702 if ( is_multisite() && ms_is_switched() ) {
703 delete_option( 'rewrite_rules' );
704 Helper::schedule_flush_rewrite();
705 return;
706 }
707
708 // On activation.
709 if ( $activate ) {
710 Helper::schedule_flush_rewrite();
711 return;
712 }
713
714 // On deactivation.
715 add_action( 'shutdown', 'flush_rewrite_rules' );
716 }
717
718 /**
719 * Add defaults for the Instant Indexing module options.
720 *
721 * @return void
722 */
723 private function create_instant_indexing_options() {
724 add_option(
725 'rank-math-options-instant-indexing',
726 $this->do_filter(
727 'settings/defaults/instant-indexing',
728 [
729 'bing_post_types' => [ 'post', 'page' ],
730 ]
731 )
732 );
733 }
734 }
735