about new ones later. add_option( 'rank_math_known_post_types', Helper::get_accessible_post_types() ); $modules = [ 'link-counter', 'analytics', 'seo-analysis', 'sitemap', 'rich-snippet', 'woocommerce', 'buddypress', 'bbpress', 'acf', 'web-stories', 'content-ai', 'instant-indexing', ]; // Role Manager. $users = get_users( [ 'role__in' => [ 'administrator', 'editor', 'author', 'contributor' ] ] ); if ( count( $users ) > 1 ) { $modules[] = 'role-manager'; } // If AMP plugin is installed. if ( function_exists( 'is_amp_endpoint' ) || class_exists( 'Better_AMP' ) || class_exists( 'Weeblramp_Api' ) || class_exists( 'AMPHTML' ) ) { $modules[] = 'amp'; } // If 404-monitor is active as plugin. if ( false !== get_option( 'rank_math_monitor_version', false ) ) { $modules[] = '404-monitor'; } add_option( 'rank_math_modules', $modules ); self::create_tables( $modules ); } /** * Add defaults for general options. */ private function create_general_options() { $post_types = Helper::get_accessible_post_types(); if ( isset( $post_types['attachment'] ) ) { unset( $post_types['attachment'] ); } add_option( 'rank-math-options-general', $this->do_filter( 'settings/defaults/general', [ 'strip_category_base' => 'off', 'attachment_redirect_urls' => 'on', 'attachment_redirect_default' => get_home_url(), 'nofollow_external_links' => 'off', 'nofollow_image_links' => 'off', 'new_window_external_links' => 'on', 'add_img_alt' => 'off', 'img_alt_format' => ' %filename%', 'add_img_title' => 'off', 'img_title_format' => '%title% %count(title)%', 'breadcrumbs' => 'off', 'breadcrumbs_separator' => '-', 'breadcrumbs_home' => 'on', 'breadcrumbs_home_label' => esc_html__( 'Home', 'rank-math' ), /* translators: Archive title */ 'breadcrumbs_archive_format' => esc_html__( 'Archives for %s', 'rank-math' ), /* translators: Search query term */ 'breadcrumbs_search_format' => esc_html__( 'Results for %s', 'rank-math' ), 'breadcrumbs_404_label' => esc_html__( '404 Error: page not found', 'rank-math' ), 'breadcrumbs_ancestor_categories' => 'off', 'breadcrumbs_blog_page' => 'off', '404_monitor_mode' => 'simple', '404_monitor_limit' => 100, '404_monitor_ignore_query_parameters' => 'on', 'redirections_header_code' => '301', 'redirections_debug' => 'off', 'console_caching_control' => '90', 'console_email_reports' => 'on', 'console_email_frequency' => 'monthly', 'link_builder_links_per_page' => '7', 'link_builder_links_per_target' => '1', 'wc_remove_product_base' => 'off', 'wc_remove_category_base' => 'off', 'wc_remove_category_parent_slugs' => 'off', 'rss_before_content' => '', 'rss_after_content' => '', 'wc_remove_generator' => 'on', 'remove_shop_snippet_data' => 'on', 'frontend_seo_score' => 'off', 'frontend_seo_score_post_types' => [ 'post' ], 'frontend_seo_score_position' => 'top', 'setup_mode' => 'advanced', 'content_ai_post_types' => array_keys( $post_types ), 'content_ai_country' => 'all', 'content_ai_tone' => 'Formal', 'content_ai_audience' => 'General Audience', 'content_ai_language' => Helper::content_ai_default_language(), 'analytics_stats' => 'on', 'toc_block_title' => 'Table of Contents', 'toc_block_list_style' => 'ul', ] ) ); } /** * Add default values. */ private function create_titles_sitemaps_options() { $sitemap = [ 'items_per_page' => 200, 'include_images' => 'on', 'include_featured_image' => 'off', 'exclude_roles' => $this->get_excluded_roles(), 'html_sitemap' => 'on', 'html_sitemap_display' => 'shortcode', 'html_sitemap_sort' => 'published', 'html_sitemap_seo_titles' => 'titles', 'authors_sitemap' => 'on', ]; $titles = [ 'noindex_empty_taxonomies' => 'on', 'title_separator' => '-', 'capitalize_titles' => 'off', 'twitter_card_type' => 'summary_large_image', 'knowledgegraph_type' => class_exists( 'Easy_Digital_Downloads' ) || class_exists( 'WooCommerce' ) ? 'company' : 'person', 'knowledgegraph_name' => get_bloginfo( 'name' ), 'website_name' => get_bloginfo( 'name' ), 'local_business_type' => 'Organization', 'local_address_format' => '{address} {locality}, {region} {postalcode}', 'opening_hours' => $this->get_opening_hours(), 'opening_hours_format' => 'off', 'homepage_title' => '%sitename% %page% %sep% %sitedesc%', 'homepage_description' => '', 'homepage_custom_robots' => 'off', 'disable_author_archives' => 'off', 'url_author_base' => 'author', 'author_custom_robots' => 'on', 'author_robots' => [ 'noindex' ], 'author_archive_title' => '%name% %sep% %sitename% %page%', 'author_add_meta_box' => 'on', 'disable_date_archives' => 'on', 'date_archive_title' => '%date% %page% %sep% %sitename%', 'search_title' => '%search_query% %page% %sep% %sitename%', '404_title' => 'Page Not Found %sep% %sitename%', 'date_archive_robots' => [ 'noindex' ], 'noindex_search' => 'on', 'noindex_archive_subpages' => 'off', 'noindex_password_protected' => 'off', ]; $this->create_post_type_options( $titles, $sitemap ); $this->create_taxonomy_options( $titles, $sitemap ); add_option( 'rank-math-options-titles', $this->do_filter( 'settings/defaults/titles', $titles ) ); add_option( 'rank-math-options-sitemap', $this->do_filter( 'settings/defaults/sitemap', $sitemap ) ); } /** * Create post type options. * * @param array $titles Hold title settings. * @param array $sitemap Hold sitemap settings. */ private function create_post_type_options( &$titles, &$sitemap ) { $post_types = Helper::get_accessible_post_types(); array_push( $post_types, 'product', 'web-story' ); $titles['pt_download_default_rich_snippet'] = 'product'; $titles['author_slack_enhanced_sharing'] = 'on'; foreach ( $post_types as $post_type ) { $defaults = $this->get_post_type_defaults( $post_type ); $titles[ 'pt_' . $post_type . '_title' ] = '%title% %sep% %sitename%'; $titles[ 'pt_' . $post_type . '_description' ] = '%excerpt%'; $titles[ 'pt_' . $post_type . '_robots' ] = $defaults['robots']; $titles[ 'pt_' . $post_type . '_custom_robots' ] = $defaults['is_custom']; $titles[ 'pt_' . $post_type . '_default_rich_snippet' ] = $defaults['rich_snippet']; $titles[ 'pt_' . $post_type . '_default_article_type' ] = $defaults['article_type']; $titles[ 'pt_' . $post_type . '_default_snippet_name' ] = '%seo_title%'; $titles[ 'pt_' . $post_type . '_default_snippet_desc' ] = '%seo_description%'; if ( $this->has_archive( $post_type ) ) { $titles[ 'pt_' . $post_type . '_archive_title' ] = '%title% %page% %sep% %sitename%'; } // Slack enhanced sharing is off by default, except for posts, pages, products, and downloads. $titles[ 'pt_' . $post_type . '_slack_enhanced_sharing' ] = 'off'; if ( in_array( $post_type, [ 'post', 'page', 'product', 'download' ], true ) ) { $titles[ 'pt_' . $post_type . '_slack_enhanced_sharing' ] = 'on'; } if ( in_array( $post_type, [ 'attachment', 'web-story' ], true ) ) { $sitemap[ 'pt_' . $post_type . '_sitemap' ] = 'off'; $titles[ 'pt_' . $post_type . '_add_meta_box' ] = 'off'; continue; } $sitemap[ 'pt_' . $post_type . '_sitemap' ] = 'on'; $titles[ 'pt_' . $post_type . '_ls_use_fk' ] = 'titles'; $titles[ 'pt_' . $post_type . '_add_meta_box' ] = 'on'; $titles[ 'pt_' . $post_type . '_bulk_editing' ] = 'editing'; $titles[ 'pt_' . $post_type . '_link_suggestions' ] = 'on'; // Primary Taxonomy. $taxonomy_hash = [ 'post' => 'category', 'product' => 'product_cat', ]; if ( isset( $taxonomy_hash[ $post_type ] ) ) { $titles[ 'pt_' . $post_type . '_primary_taxonomy' ] = $taxonomy_hash[ $post_type ]; } } } /** * Get robots default for post type. * * @param string $post_type Post type. * @return array */ private function get_post_type_defaults( $post_type ) { $rich_snippets = [ 'post' => 'article', 'page' => 'article', 'product' => 'product', 'download' => 'product', 'web-story' => 'article', ]; $defaults = [ 'robots' => [], 'is_custom' => 'off', 'rich_snippet' => isset( $rich_snippets[ $post_type ] ) ? $rich_snippets[ $post_type ] : 'off', 'article_type' => 'post' === $post_type ? 'BlogPosting' : 'Article', ]; if ( 'attachment' === $post_type ) { $defaults['is_custom'] = 'on'; $defaults['robots'] = [ 'noindex' ]; } return $defaults; } /** * Check post type has archive. * * @param string $post_type Post type. * @return bool */ private function has_archive( $post_type ) { $post_type_obj = get_post_type_object( $post_type ); return ! is_null( $post_type_obj ) && $post_type_obj->has_archive; } /** * Create post type options. * * @param array $titles Hold title settings. * @param array $sitemap Hold sitemap settings. */ private function create_taxonomy_options( &$titles, &$sitemap ) { $taxonomies = Helper::get_accessible_taxonomies(); foreach ( $taxonomies as $taxonomy => $object ) { $defaults = $this->get_taxonomy_defaults( $taxonomy ); $titles[ 'tax_' . $taxonomy . '_title' ] = '%term% %sep% %sitename%'; $titles[ 'tax_' . $taxonomy . '_robots' ] = $defaults['robots']; $titles[ 'tax_' . $taxonomy . '_add_meta_box' ] = $defaults['metabox']; $titles[ 'tax_' . $taxonomy . '_custom_robots' ] = $defaults['is_custom']; $titles[ 'tax_' . $taxonomy . '_description' ] = '%term_description%'; $titles[ 'tax_' . $taxonomy . '_slack_enhanced_sharing' ] = 'on'; $sitemap[ 'tax_' . $taxonomy . '_sitemap' ] = 'category' === $taxonomy ? 'on' : 'off'; if ( substr( $taxonomy, 0, 3 ) === 'pa_' ) { $titles[ 'remove_' . $taxonomy . '_snippet_data' ] = 'on'; } } $titles['remove_product_cat_snippet_data'] = 'on'; $titles['remove_product_tag_snippet_data'] = 'on'; } /** * Get robots default for post type. * * @param string $taxonomy Taxonomy. * @return array */ private function get_taxonomy_defaults( $taxonomy ) { $defaults = [ 'robots' => [], 'is_custom' => 'off', 'metabox' => 'category' === $taxonomy ? 'on' : 'off', ]; if ( in_array( $taxonomy, [ 'post_tag', 'post_format', 'product_tag' ], true ) ) { $defaults['is_custom'] = 'on'; $defaults['robots'] = [ 'noindex' ]; } return $defaults; } /** * Create capabilities. */ private function set_capabilities() { $admin = get_role( 'administrator' ); if ( ! is_null( $admin ) ) { $admin->add_cap( 'rank_math_edit_htaccess', true ); } Capability_Manager::get()->create_capabilities(); } /** * Create cron jobs. */ public function create_cron_jobs() { $midnight = strtotime( 'tomorrow midnight' ); foreach ( $this->get_cron_jobs() as $job => $recurrence ) { if ( ! wp_next_scheduled( "rank_math/{$job}" ) ) { $timestamp = 'content-ai/update_prompts' === $job ? $midnight + wp_rand( 60, 86400 ) : $midnight; wp_schedule_event( $timestamp, $this->do_filter( "{$job}_recurrence", $recurrence ), "rank_math/{$job}" ); } } } /** * Remove cron jobs. */ private function remove_cron_jobs() { foreach ( $this->get_cron_jobs() as $job => $recurrence ) { wp_clear_scheduled_hook( "rank_math/{$job}" ); } } /** * Get cron jobs. * * @return array */ private function get_cron_jobs() { return [ 'redirection/clean_trashed' => 'daily', // Add cron for cleaning trashed redirects. 'links/internal_links' => 'daily', // Add cron for counting links. 'content-ai/update_prompts' => 'daily', // Add cron for updating the prompts data. ]; } /** * Get opening hours. * * @return array */ private function get_opening_hours() { $hours = []; $days = [ 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday' ]; foreach ( $days as $day ) { $hours[] = [ 'day' => $day, 'time' => '09:00-17:00', ]; } return $hours; } /** * Get roles to exclude. * * @return array */ private function get_excluded_roles() { $roles = Helper::get_roles(); unset( $roles['administrator'], $roles['editor'], $roles['author'] ); return array_keys( $roles ); } /** * Clear rewrite rules. * * @param bool $activate True for plugin activation, false for de-activation. */ private function clear_rewrite_rules( $activate ) { if ( is_multisite() && ms_is_switched() ) { delete_option( 'rewrite_rules' ); Helper::schedule_flush_rewrite(); return; } // On activation. if ( $activate ) { Helper::schedule_flush_rewrite(); return; } // On deactivation. add_action( 'shutdown', 'flush_rewrite_rules' ); } /** * Add defaults for the Instant Indexing module options. * * @return void */ private function create_instant_indexing_options() { add_option( 'rank-math-options-instant-indexing', $this->do_filter( 'settings/defaults/instant-indexing', [ 'bing_post_types' => [ 'post', 'page' ], ] ) ); } }