Files
2026-04-28 15:13:50 +02:00

939 lines
28 KiB
PHP

<?php
namespace AIOSEO\Plugin\Common\SeoChecklist;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use AIOSEO\Plugin\Common\Models\SeoAnalyzerResult;
class SeoChecklist {
protected $checks = [];
/**
* Constructor.
*
* @since 4.9.4
*/
public function __construct() {
add_action( 'update_option_blog_public', [ $this, 'onBlogPublicUpdate' ], 10, 2 );
}
/**
* Handle blog_public option update.
* If the site is set to discourage search engines, mark the indexing check as incomplete.
*
* @since 4.9.4
*
* @param mixed $oldValue The old option value.
* @param mixed $newValue The new option value.
* @return void
*/
public function onBlogPublicUpdate( $oldValue, $newValue ) {
// If the new value discourages search engines (0), mark the check as incomplete.
if ( '0' === (string) $newValue ) {
$this->uncompleteCheck( 'enableIndexing' );
}
}
/**
* Get all the checks.
*
* @since 4.9.4
*
* @return array
*/
public function getChecks() {
// Reset checks array to prevent duplicates on multiple calls.
$this->checks = [];
$this->registerChecks();
$completedChecks = aioseo()->internalOptions->internal->seoChecklist->completed;
// Remove all checks that the user cannot access.
$this->checks = array_values(array_filter( $this->checks, function ( $check ) {
if ( ! isset( $check['capability'] ) ) {
return true;
}
return $this->hasCapability( $check['name'] );
} ) );
// Once all checks are registered, check which ones are completed.
foreach ( $completedChecks as $completedCheck ) {
// Look up the checks by name. If it exists, get the index. Then, use the index to mark the check as completed.
$index = array_search( $completedCheck, array_column( $this->checks, 'name' ), true );
if ( false !== $index ) {
$this->checks[ $index ]['completed'] = true;
}
}
// Now, check the incompleted checks to see if any were completed.
foreach ( $this->checks as $index => $check ) {
if ( ! $check['completed'] ) {
$isCompleted = false;
if ( null !== $check['callback'] && is_callable( [ $this, $check['callback'] ] ) ) {
$isCompleted = call_user_func( [ $this, $check['callback'] ] );
}
if ( $isCompleted ) {
$this->checks[ $index ]['completed'] = true;
$completedChecks[] = $check['name'];
aioseo()->internalOptions->internal->seoChecklist->completed = $completedChecks;
}
}
}
return array_values( $this->checks );
}
/**
* Register all the checks.
*
* @since 4.9.4
*
* @return void
*/
protected function registerChecks() {
// Undismissable checks first.
$this->checks[] = [
'name' => 'enableIndexing',
'title' => __( 'Enable Indexing for Search Engines', 'all-in-one-seo-pack' ),
'description' => __( 'Your site is currently hidden from search engines. Enable indexing so Google and other search engines can include your content in their search results.', 'all-in-one-seo-pack' ), // phpcs:ignore Generic.Files.LineLength.MaxExceeded
'priority' => 'high',
'time' => [
'label' => __( 'Instant', 'all-in-one-seo-pack' ),
'value' => 0
],
'callback' => 'checkIndexingEnabled',
'capability' => 'manage_options',
'actions' => [
[
'label' => __( 'Enable Indexing', 'all-in-one-seo-pack' ),
'callback' => 'enableIndexing'
]
],
'completed' => false,
'dismissable' => false
];
// Setup Wizard should be at the top of high priority tasks.
$this->checks[] = [
'name' => 'finishSetupWizard',
'title' => __( 'Complete the Setup Wizard', 'all-in-one-seo-pack' ),
'description' => __( 'Configure essential SEO settings for your site through our guided setup process.', 'all-in-one-seo-pack' ),
'priority' => 'high',
'time' => [
'label' => __( '10 minutes', 'all-in-one-seo-pack' ),
'value' => 600
],
'callback' => 'checkFinishSetupWizard',
'capability' => 'aioseo_setup_wizard',
'actions' => [
[
'label' => __( 'Launch Wizard', 'all-in-one-seo-pack' ),
'url' => admin_url( 'admin.php?page=aioseo-setup-wizard' )
]
],
'actionAfterCompletion' => [
[
'label' => __( 'Restart Wizard', 'all-in-one-seo-pack' ),
'url' => admin_url( 'admin.php?page=aioseo-setup-wizard' )
]
],
'completed' => false
];
$this->checks[] = [
'name' => 'connectGoogleSearchConsole',
'title' => __( 'Connect with Google Search Console', 'all-in-one-seo-pack' ),
'description' => __( 'Link your site to Google Search Console to submit sitemaps and monitor your search performance.', 'all-in-one-seo-pack' ),
'priority' => 'high',
'time' => [
'label' => __( '5 minutes', 'all-in-one-seo-pack' ),
'value' => 300
],
'callback' => 'checkConnectGoogleSearchConsole',
'capability' => 'aioseo_general_settings',
'actions' => [
[
'label' => __( 'Connect', 'all-in-one-seo-pack' ),
'url' => admin_url(
'admin.php?page=aioseo-settings' .
'&aioseo-scroll=google-search-console-settings' .
'&aioseo-highlight=google-search-console-settings' .
'#/webmaster-tools?activetool=googleSearchConsole'
)
]
],
'completed' => false
];
$this->checks[] = [
'name' => 'runHomepageAudit',
'title' => __( 'Run Homepage Audit', 'all-in-one-seo-pack' ),
'description' => __( 'Analyze your homepage for SEO issues and get actionable recommendations to improve your rankings.', 'all-in-one-seo-pack' ),
'priority' => 'high',
'time' => [
'label' => __( '10 minutes', 'all-in-one-seo-pack' ),
'value' => 600
],
'callback' => 'checkRunHomepageAudit',
'capability' => 'aioseo_seo_analysis_settings',
'actions' => [
[
'label' => __( 'Run Audit', 'all-in-one-seo-pack' ),
'url' => admin_url( 'admin.php?page=aioseo-seo-analysis' )
]
],
'completed' => false
];
$this->checks[] = [
'name' => 'deleteHelloWorld',
'title' => __( 'Delete the "Hello world!" post', 'all-in-one-seo-pack' ),
'description' => __( 'Remove the default WordPress sample post that was created when your site was installed.', 'all-in-one-seo-pack' ),
'priority' => 'medium',
'time' => [
'label' => __( 'Instant', 'all-in-one-seo-pack' ),
'value' => 0
],
'callback' => 'checkDeleteHelloWorld',
'capability' => [ $this, 'canDeleteHelloWorld' ],
'actions' => [
[
'label' => __( 'Delete Post', 'all-in-one-seo-pack' ),
'callback' => 'deleteHelloWorld'
]
],
'completed' => false
];
$this->checks[] = [
'name' => 'setSiteTitleAndTagline',
'title' => __( 'Set a Site Title and Tagline', 'all-in-one-seo-pack' ),
'description' => __( 'The Site Title and Tagline are used throughout AIOSEO as default values and fallbacks. We recommend always having these set.', 'all-in-one-seo-pack' ),
'priority' => 'medium',
'time' => [
'label' => __( '2 minutes', 'all-in-one-seo-pack' ),
'value' => 120
],
'callback' => 'checkSiteTitleAndTagline',
'capability' => 'manage_options',
'actions' => [
[
'label' => __( 'Open Settings', 'all-in-one-seo-pack' ),
'url' => admin_url( 'options-general.php' )
],
[
'label' => __( 'Mark Complete', 'all-in-one-seo-pack' ),
'callback' => 'completeCheck'
]
],
'completed' => false
];
$this->checks[] = [
'name' => 'fillKnowledgeGraph',
'title' => __( 'Add Organization or Person Info', 'all-in-one-seo-pack' ),
'description' => __( 'Add details about your organization or personal brand to help search engines understand your site better.', 'all-in-one-seo-pack' ),
'priority' => 'medium',
'time' => [
'label' => __( '10 minutes', 'all-in-one-seo-pack' ),
'value' => 600
],
'callback' => null,
'capability' => 'aioseo_search_appearance_settings',
'actions' => [
[
'label' => __( 'Open Settings', 'all-in-one-seo-pack' ),
'url' => admin_url( 'admin.php?page=aioseo-search-appearance&aioseo-scroll=aioseo-knowledge-graph&aioseo-highlight=aioseo-knowledge-graph#/global-settings' )
],
[
'label' => __( 'Mark Complete', 'all-in-one-seo-pack' ),
'callback' => 'completeCheck'
]
],
'completed' => false
];
$this->checks[] = [
'name' => 'reviewContentTypes',
'title' => __( 'Configure Post Settings', 'all-in-one-seo-pack' ),
'description' => __( 'Control how your posts and pages appear in search results.', 'all-in-one-seo-pack' ),
'priority' => 'medium',
'time' => [
'label' => __( '10 minutes', 'all-in-one-seo-pack' ),
'value' => 600
],
'callback' => null,
'capability' => 'aioseo_search_appearance_settings',
'actions' => [
[
'label' => __( 'Open Settings', 'all-in-one-seo-pack' ),
'url' => admin_url( 'admin.php?page=aioseo-search-appearance#/content-types' )
],
[
'label' => __( 'Mark Complete', 'all-in-one-seo-pack' ),
'callback' => 'completeCheck'
]
],
'completed' => false
];
$this->checks[] = [
'name' => 'reviewTaxonomies',
'title' => __( 'Configure Taxonomy Page Settings', 'all-in-one-seo-pack' ),
'description' => __( 'Control how your taxonomy pages, such as categories and tags, appear in search results.', 'all-in-one-seo-pack' ),
'priority' => 'low',
'time' => [
'label' => __( '10 minutes', 'all-in-one-seo-pack' ),
'value' => 600
],
'callback' => null,
'capability' => 'aioseo_search_appearance_settings',
'actions' => [
[
'label' => __( 'Open Settings', 'all-in-one-seo-pack' ),
'url' => admin_url( 'admin.php?page=aioseo-search-appearance#/taxonomies' )
],
[
'label' => __( 'Mark Complete', 'all-in-one-seo-pack' ),
'callback' => 'completeCheck'
]
],
'completed' => false
];
$this->checks[] = [
'name' => 'reviewArchives',
'title' => __( 'Configure Archive Page Settings', 'all-in-one-seo-pack' ),
'description' => __( 'Control how your archive pages appear in search results.', 'all-in-one-seo-pack' ),
'priority' => 'low',
'time' => [
'label' => __( '10 minutes', 'all-in-one-seo-pack' ),
'value' => 600
],
'callback' => null,
'capability' => 'aioseo_search_appearance_settings',
'actions' => [
[
'label' => __( 'Open Settings', 'all-in-one-seo-pack' ),
'url' => admin_url( 'admin.php?page=aioseo-search-appearance#/archives' )
],
[
'label' => __( 'Mark Complete', 'all-in-one-seo-pack' ),
'callback' => 'completeCheck'
]
],
'completed' => false
];
$this->checks[] = [
'name' => 'fillSocialProfiles',
'title' => __( 'Add Social Profiles', 'all-in-one-seo-pack' ),
'description' => __( 'Add your social media profiles to enhance your online presence and help search engines connect your brand across platforms.', 'all-in-one-seo-pack' ),
'priority' => 'medium',
'time' => [
'label' => __( '5 minutes', 'all-in-one-seo-pack' ),
'value' => 300
],
'callback' => 'checkFillSocialProfiles',
'capability' => 'aioseo_social_networks_settings',
'actions' => [
[
'label' => __( 'Add Profiles', 'all-in-one-seo-pack' ),
'url' => admin_url( 'admin.php?page=aioseo-social-networks&aioseo-scroll=aioseo-social-profiles&aioseo-highlight=aioseo-social-profiles#/social-profiles' )
]
],
'completed' => false
];
$this->checks[] = [
'name' => 'enableLlmsTxt',
'title' => __( 'Enable llms.txt', 'all-in-one-seo-pack' ),
'description' => __( 'Help AI tools like ChatGPT and Claude better understand and reference your site content.', 'all-in-one-seo-pack' ),
'priority' => 'medium',
'time' => [
'label' => __( 'Instant', 'all-in-one-seo-pack' ),
'value' => 0
],
'callback' => 'checkLlmsTxtEnabled',
'capability' => 'aioseo_sitemap_settings',
'actions' => [
[
'label' => __( 'Enable', 'all-in-one-seo-pack' ),
'callback' => 'enableLlmsTxt'
]
],
'completed' => false
];
// Only show if llms.txt is enabled.
if ( aioseo()->options->sitemap->llms->enable ) {
$this->checks[] = [
'name' => 'reviewLlmsTxtSettings',
'title' => __( 'Configure llms.txt Settings', 'all-in-one-seo-pack' ),
'description' => __( 'Control which content is included in your llms.txt file to optimize how AI models understand your site.', 'all-in-one-seo-pack' ),
'priority' => 'low',
'time' => [
'label' => __( '5 minutes', 'all-in-one-seo-pack' ),
'value' => 300
],
'callback' => null,
'capability' => 'aioseo_sitemap_settings',
'actions' => [
[
'label' => __( 'Open Settings', 'all-in-one-seo-pack' ),
'url' => admin_url( 'admin.php?page=aioseo-sitemaps#/llms-sitemap' )
],
[
'label' => __( 'Mark Complete', 'all-in-one-seo-pack' ),
'callback' => 'completeCheck'
]
],
'completed' => false
];
}
// Broken Link Checker install check - always register, callback determines completion.
$this->checks[] = [
'name' => 'installBrokenLinkChecker',
'title' => __( 'Install Broken Link Checker', 'all-in-one-seo-pack' ),
'description' => __( 'Broken links hurt your SEO and user experience. Install the Broken Link Checker plugin to automatically find and fix them.', 'all-in-one-seo-pack' ),
'priority' => 'optional',
'time' => [
'label' => __( 'Instant', 'all-in-one-seo-pack' ),
'value' => 0
],
'callback' => 'checkBrokenLinkCheckerInstalled',
'capability' => 'install_plugins',
'actions' => [
[
'label' => __( 'Install Plugin', 'all-in-one-seo-pack' ),
'callback' => 'installBrokenLinkChecker'
]
],
'completed' => false
];
// Broken Link Checker connect check - only show if BLC is installed and active.
if ( $this->isBrokenLinkCheckerActive() ) {
$this->checks[] = [
'name' => 'connectBrokenLinkChecker',
'title' => __( 'Connect Broken Link Checker', 'all-in-one-seo-pack' ),
'description' => __( 'Connect your site with Broken Link Checker to start monitoring for broken links.', 'all-in-one-seo-pack' ),
'priority' => 'optional',
'time' => [
'label' => __( '5 minutes', 'all-in-one-seo-pack' ),
'value' => 300
],
'callback' => 'checkBrokenLinkCheckerConnected',
'capability' => 'aioseo_broken_link_checker_settings',
'actions' => [
[
'label' => __( 'Connect BLC', 'all-in-one-seo-pack' ),
'url' => admin_url( 'admin.php?page=broken-link-checker#settings' )
]
],
'completed' => false
];
}
}
/**
* Check if the user can delete the hello world post.
*
* @since 4.9.4
*
* @return bool True if user can delete the hello world post.
*/
protected function canDeleteHelloWorld() {
$post = get_post( 1 );
if ( empty( $post ) ) {
// If the post does not exist, return true.
// This means the post has been deleted. Otherwise, the task will be hidden.
return true;
}
// If the post has been modified from the default "Hello World", hide the task.
if ( ! $this->isDefaultHelloWorldPost( $post ) ) {
return false;
}
return current_user_can( 'delete_post', 1 );
}
/**
* Check if a post is the default WordPress "Hello World" post.
* Compares the title and slug against the English defaults and the current locale's translated defaults.
*
* @since 4.9.5
*
* @param \WP_Post $post The post object with post_title and post_name properties.
* @return bool True if the post matches the default "Hello World" post.
*/
protected function isDefaultHelloWorldPost( $post ) {
// Ensure admin translations are loaded for install-related strings like "Hello world!".
// These strings live in admin-{locale}.mo, which isn't loaded during REST API requests.
static $adminTranslationsLoaded = false;
if ( ! $adminTranslationsLoaded ) {
$adminTranslationsLoaded = true;
$locale = determine_locale();
if ( 'en_US' !== $locale ) {
load_textdomain( 'default', WP_LANG_DIR . "/admin-{$locale}.mo" );
}
}
$defaultTitles = array_unique( [ 'Hello world!', __( 'Hello world!' ) ] ); // phpcs:ignore AIOSEO.Wp.I18n.MissingArgDomain
$defaultSlugs = array_unique( [ 'hello-world', sanitize_title( _x( 'hello-world', 'Default post slug' ) ) ] ); // phpcs:ignore AIOSEO.Wp.I18n.MissingArgDomain
// WordPress appends "__trashed" to the post slug when a post is trashed (see wp_trash_post()).
$defaultSlugs = array_merge( $defaultSlugs, array_map( function ( $slug ) {
return $slug . '__trashed';
}, $defaultSlugs ) );
return in_array( $post->post_title, $defaultTitles, true ) && in_array( $post->post_name, $defaultSlugs, true );
}
/**
* Check if the hello world post has been deleted.
*
* @since 4.9.4
*
* @return bool True if hello world post has been deleted.
*/
protected function checkDeleteHelloWorld() {
$post = get_post( 1 );
return empty( $post->ID ) || ! empty( $post->post_status ) && 'trash' === $post->post_status;
}
/**
* Check if the setup wizard has been completed.
*
* @since 4.9.4
*
* @return bool True if completed.
*/
protected function checkFinishSetupWizard() {
return aioseo()->internalOptions->internal->wizardCompleted;
}
/**
* Check if Google Search Console is connected.
*
* @since 4.9.4
*
* @return bool True if connected.
*/
protected function checkConnectGoogleSearchConsole() {
return aioseo()->searchStatistics->api->auth->isConnected();
}
/**
* Check if a homepage SEO audit has been run.
*
* @since 4.9.4
*
* @return bool True if audit has been run.
*/
protected function checkRunHomepageAudit() {
return ! empty( SeoAnalyzerResult::getResults() );
}
/**
* Check if Site Title is set.
*
* @since 4.9.4
*
* @return bool True if Site Title is set.
*/
protected function checkSiteTitle() {
$siteTitle = get_option( 'blogname' );
return ! empty( $siteTitle );
}
/**
* Check if Tagline is set.
*
* @since 4.9.4
*
* @return bool True if Tagline is set.
*/
protected function checkTagline() {
$tagline = get_option( 'blogdescription' );
return ! empty( $tagline );
}
/**
* Check if both Site Title and Tagline are set.
*
* @since 4.9.4
*
* @return bool True if both Site Title and Tagline are set.
*/
protected function checkSiteTitleAndTagline() {
return $this->checkSiteTitle() && $this->checkTagline();
}
/**
* Check if Social Profiles have been filled out.
*
* @since 4.9.4
*
* @return bool True if at least one social profile is configured.
*/
protected function checkFillSocialProfiles() {
$profiles = aioseo()->options->social->profiles->all();
// Check if "Use the same username for multiple social networks" is enabled with a username and at least one network selected.
if (
! empty( $profiles['sameUsername']['enable'] ) &&
! empty( $profiles['sameUsername']['username'] ) &&
! empty( $profiles['sameUsername']['included'] )
) {
return true;
}
// Check if any social URL is set.
$urls = $profiles['urls'] ?? [];
foreach ( $urls as $url ) {
if ( ! empty( $url ) ) {
return true;
}
}
// Check if additional profiles URLs are set.
if ( ! empty( trim( $profiles['additionalUrls'] ?? '' ) ) ) {
return true;
}
return false;
}
/**
* Check if site indexing is enabled.
*
* @since 4.9.4
*
* @return bool True if indexing is enabled (blog_public is 1).
*/
protected function checkIndexingEnabled() {
return '1' === get_option( 'blog_public' );
}
/**
* Check if llms.txt is enabled.
*
* @since 4.9.4
*
* @return bool True if llms.txt is enabled.
*/
protected function checkLlmsTxtEnabled() {
return aioseo()->options->sitemap->llms->enable;
}
/**
* Check if Broken Link Checker is installed.
*
* @since 4.9.4
*
* @return bool True if BLC is installed.
*/
protected function checkBrokenLinkCheckerInstalled() {
$pluginData = aioseo()->helpers->getPluginData();
return ! empty( $pluginData['brokenLinkChecker']['installed'] );
}
/**
* Check if Broken Link Checker is connected.
*
* @since 4.9.4
*
* @return bool True if BLC is connected.
*/
protected function checkBrokenLinkCheckerConnected() {
return $this->isBrokenLinkCheckerConnected();
}
/**
* Helper to check if Broken Link Checker is active.
*
* @since 4.9.4
*
* @return bool True if BLC is installed and active.
*/
protected function isBrokenLinkCheckerActive() {
return function_exists( 'aioseoBrokenLinkChecker' );
}
/**
* Helper to check if Broken Link Checker is connected.
*
* @since 4.9.4
*
* @return bool True if BLC is connected.
*/
protected function isBrokenLinkCheckerConnected() {
if ( ! $this->isBrokenLinkCheckerActive() ) {
return false;
}
// Check if BLC has completed its initial scan or has an API key set.
return aioseoBrokenLinkChecker()->license->isActive();
}
/**
* Complete a check.
*
* @since 4.9.4
*
* @param string $checkName The name of the check to complete.
* @return void
*/
public function completeCheck( $checkName ) {
// Check permissions if the user is logged in.
// Don't do this if wp_get_current_user() is not loaded.
// This prevents errors when the method is called inside the plugin during init, and not via the API.
if ( function_exists( 'wp_get_current_user' ) ) {
// User needs access to the general settings or setup wizard.
if ( ! aioseo()->access->hasCapability( 'aioseo_general_settings' ) && ! aioseo()->access->hasCapability( 'aioseo_setup_wizard' ) ) {
return;
}
// User should also have the cap required to complete this check.
if ( ! $this->hasCapability( $checkName ) ) {
return;
}
}
$completedChecks = aioseo()->internalOptions->internal->seoChecklist->completed;
$completedChecks[] = $checkName;
$completedChecks = array_values( array_unique( $completedChecks ) );
aioseo()->internalOptions->internal->seoChecklist->completed = $completedChecks;
}
/**
* Uncomplete a check (remove completed status).
*
* @since 4.9.4
*
* @param string $checkName The name of the check to uncomplete.
* @return void
*/
public function uncompleteCheck( $checkName ) {
// Check permissions if the user is logged in.
// Don't do this if wp_get_current_user() is not loaded.
// This prevents errors when the method is called inside the plugin during init, and not via the API.
if ( function_exists( 'wp_get_current_user' ) ) {
// User needs access to the general settings or setup wizard.
if ( ! aioseo()->access->hasCapability( 'aioseo_general_settings' ) && ! aioseo()->access->hasCapability( 'aioseo_setup_wizard' ) ) {
return;
}
// User should also have the cap required to uncomplete this check.
if ( ! $this->hasCapability( $checkName ) ) {
return;
}
}
$completedChecks = aioseo()->internalOptions->internal->seoChecklist->completed;
$completedChecks = array_values( array_unique( array_diff( $completedChecks, [ $checkName ] ) ) );
aioseo()->internalOptions->internal->seoChecklist->completed = $completedChecks;
}
/**
* Execute an action for a check.
*
* @since 4.9.4
*
* @param string $checkName The name of the check to execute the action for.
* @param string $action The action to execute.
* @return bool True if successful.
*/
public function doAction( $checkName, $action ) {
// Check if the user is logged in and has access to the general settings or setup wizard.
// Don't do this if wp_get_current_user() is not loaded.
// This prevents errors when the method is called inside the plugin during init, and not via the API.
if ( function_exists( 'wp_get_current_user' ) ) {
// User needs access to the general settings or setup wizard.
if ( ! aioseo()->access->hasCapability( 'aioseo_general_settings' ) && ! aioseo()->access->hasCapability( 'aioseo_setup_wizard' ) ) {
return;
}
// User should also have the cap required to uncomplete this check.
if ( ! $this->hasCapability( $checkName ) ) {
return;
}
}
switch ( $action ) {
case 'completeCheck':
// Just mark as complete, no additional action needed.
return true;
case 'deleteHelloWorld':
return $this->deleteHelloWorld();
case 'enableIndexing':
return $this->enableIndexing();
case 'enableLlmsTxt':
return $this->enableLlmsTxt();
case 'installBrokenLinkChecker':
return $this->installBrokenLinkChecker();
default:
return false;
}
}
/**
* Delete the Hello World post.
*
* @since 4.9.4
*
* @return bool True if successful.
*/
private function deleteHelloWorld() {
// Check if user has permission to delete the post.
if ( ! current_user_can( 'delete_post', 1 ) ) {
return false;
}
// Only delete if the post is still the default "Hello World" post.
$post = get_post( 1 );
if ( empty( $post ) || ! $this->isDefaultHelloWorldPost( $post ) ) {
return false;
}
// Delete the post.
wp_trash_post( 1 );
return true;
}
/**
* Enable site indexing.
*
* @since 4.9.4
*
* @return bool True if successful.
*/
private function enableIndexing() {
if ( ! current_user_can( 'manage_options' ) ) {
return false;
}
update_option( 'blog_public', '1' );
return true;
}
/**
* Enable llms.txt.
*
* @since 4.9.4
*
* @return bool True if successful.
*/
private function enableLlmsTxt() {
if ( ! aioseo()->access->hasCapability( 'aioseo_sitemap_settings' ) ) {
return false;
}
aioseo()->options->sitemap->llms->enable = true;
// Schedule llms.txt generation.
if ( aioseo()->llms ) {
aioseo()->llms->scheduleSingleGenerationForLlmsTxt();
}
return true;
}
/**
* Install Broken Link Checker.
*
* @since 4.9.4
*
* @return bool True if successful.
*/
private function installBrokenLinkChecker() {
if ( ! current_user_can( 'install_plugins' ) ) {
return false;
}
if ( ! aioseo()->addons->canInstall() ) {
return false;
}
$installed = aioseo()->addons->installAddon( 'brokenLinkChecker' );
if ( $installed && function_exists( 'aioseoBrokenLinkChecker' ) ) {
aioseoBrokenLinkChecker()->core->cache->delete( 'activation_redirect' );
}
return $installed;
}
/**
* Check if the user has the capability to complete a check.
*
* @since 4.9.4
*
* @param string $checkName The name of the check.
* @return bool True if the user has the capability.
*/
public function hasCapability( $checkName ) {
// Ensure checks are registered before looking up capabilities.
if ( empty( $this->checks ) ) {
$this->registerChecks();
}
// Find the check by name.
$check = array_filter( $this->checks, function ( $check ) use ( $checkName ) {
return $check['name'] === $checkName;
} );
$check = reset( $check );
// If the check was not found, deny access by default.
if ( false === $check ) {
return false;
}
// If the check does not have a capability, return true.
if ( ! isset( $check['capability'] ) ) {
return true;
}
if ( is_callable( $check['capability'] ) ) {
return call_user_func( $check['capability'] );
}
if ( is_string( $check['capability'] ) ) {
return aioseo()->access->hasCapability( $check['capability'] );
}
if ( is_array( $check['capability'] ) ) {
foreach ( $check['capability'] as $capability ) {
// If user has any allowed capability, return true.
if ( aioseo()->access->hasCapability( $capability ) ) {
return true;
}
}
return false;
}
return false;
}
}