Initial commit: Atomaste website
This commit is contained in:
@@ -0,0 +1,453 @@
|
||||
<?php
|
||||
namespace AIOSEO\Plugin\Common\Tools;
|
||||
|
||||
// Exit if accessed directly.
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
class BadBotBlocker {
|
||||
/**
|
||||
* Holds the logger.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
private $log = null;
|
||||
|
||||
/**
|
||||
* An array of bad referers.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $refererList = [
|
||||
'semalt.com',
|
||||
'kambasoft.com',
|
||||
'savetubevideo.com',
|
||||
'buttons-for-website.com',
|
||||
'sharebutton.net',
|
||||
'soundfrost.org',
|
||||
'srecorder.com',
|
||||
'softomix.com',
|
||||
'softomix.net',
|
||||
'myprintscreen.com',
|
||||
'joinandplay.me',
|
||||
'fbfreegifts.com',
|
||||
'openmediasoft.com',
|
||||
'zazagames.org',
|
||||
'extener.org',
|
||||
'openfrost.com',
|
||||
'openfrost.net',
|
||||
'googlsucks.com',
|
||||
'best-seo-offer.com',
|
||||
'buttons-for-your-website.com',
|
||||
'www.Get-Free-Traffic-Now.com',
|
||||
'best-seo-solution.com',
|
||||
'buy-cheap-online.info',
|
||||
'site3.free-share-buttons.com',
|
||||
'webmaster-traffic.com'
|
||||
];
|
||||
|
||||
/**
|
||||
* An array of bad bots.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $botList = [
|
||||
'Abonti',
|
||||
'aggregator',
|
||||
'AhrefsBot',
|
||||
'asterias',
|
||||
'BDCbot',
|
||||
'BLEXBot',
|
||||
'BuiltBotTough',
|
||||
'Bullseye',
|
||||
'BunnySlippers',
|
||||
'ca-crawler',
|
||||
'CCBot',
|
||||
'Cegbfeieh',
|
||||
'CheeseBot',
|
||||
'CherryPicker',
|
||||
'CopyRightCheck',
|
||||
'cosmos',
|
||||
'Crescent',
|
||||
'discobot',
|
||||
'DittoSpyder',
|
||||
'DotBot',
|
||||
'Download Ninja',
|
||||
'EasouSpider',
|
||||
'EmailCollector',
|
||||
'EmailSiphon',
|
||||
'EmailWolf',
|
||||
'EroCrawler',
|
||||
'ExtractorPro',
|
||||
'Fasterfox',
|
||||
'FeedBooster',
|
||||
'Foobot',
|
||||
'Genieo',
|
||||
'grub-client',
|
||||
'Harvest',
|
||||
'hloader',
|
||||
'httplib',
|
||||
'HTTrack',
|
||||
'humanlinks',
|
||||
'ieautodiscovery',
|
||||
'InfoNaviRobot',
|
||||
'IstellaBot',
|
||||
'Java/1.',
|
||||
'JennyBot',
|
||||
'k2spider',
|
||||
'Kenjin Spider',
|
||||
'Keyword Density/0.9',
|
||||
'larbin',
|
||||
'LexiBot',
|
||||
'libWeb',
|
||||
'libwww',
|
||||
'LinkextractorPro',
|
||||
'linko',
|
||||
'LinkScan/8.1a Unix',
|
||||
'LinkWalker',
|
||||
'LNSpiderguy',
|
||||
'lwp-trivial',
|
||||
'magpie',
|
||||
'Mata Hari',
|
||||
'MaxPointCrawler',
|
||||
'MegaIndex',
|
||||
'Microsoft URL Control',
|
||||
'MIIxpc',
|
||||
'Mippin',
|
||||
'Missigua Locator',
|
||||
'Mister PiX',
|
||||
'MJ12bot',
|
||||
'moget',
|
||||
'MSIECrawler',
|
||||
'NetAnts',
|
||||
'NICErsPRO',
|
||||
'Niki-Bot',
|
||||
'NPBot',
|
||||
'Nutch',
|
||||
'Offline Explorer',
|
||||
'Openfind',
|
||||
'panscient.com',
|
||||
'PHP/5.{',
|
||||
'ProPowerBot/2.14',
|
||||
'ProWebWalker',
|
||||
'Python-urllib',
|
||||
'QueryN Metasearch',
|
||||
'RepoMonkey',
|
||||
'SISTRIX',
|
||||
'sitecheck.Internetseer.com',
|
||||
'SiteSnagger',
|
||||
'SnapPreviewBot',
|
||||
'Sogou',
|
||||
'SpankBot',
|
||||
'spanner',
|
||||
'spbot',
|
||||
'Spinn3r',
|
||||
'suzuran',
|
||||
'Szukacz/1.4',
|
||||
'Teleport',
|
||||
'Telesoft',
|
||||
'The Intraformant',
|
||||
'TheNomad',
|
||||
'TightTwatBot',
|
||||
'Titan',
|
||||
'toCrawl/UrlDispatcher',
|
||||
'True_Robot',
|
||||
'turingos',
|
||||
'TurnitinBot',
|
||||
'UbiCrawler',
|
||||
'UnisterBot',
|
||||
'URLy Warning',
|
||||
'VCI',
|
||||
'WBSearchBot',
|
||||
'Web Downloader/6.9',
|
||||
'Web Image Collector',
|
||||
'WebAuto',
|
||||
'WebBandit',
|
||||
'WebCopier',
|
||||
'WebEnhancer',
|
||||
'WebmasterWorldForumBot',
|
||||
'WebReaper',
|
||||
'WebSauger',
|
||||
'Website Quester',
|
||||
'Webster Pro',
|
||||
'WebStripper',
|
||||
'WebZip',
|
||||
'Wotbox',
|
||||
'wsr-agent',
|
||||
'WWW-Collector-E',
|
||||
'Xenu',
|
||||
'Zao',
|
||||
'Zeus',
|
||||
'ZyBORG',
|
||||
'coccoc',
|
||||
'Incutio',
|
||||
'lmspider',
|
||||
'memoryBot',
|
||||
'serf',
|
||||
'Unknown',
|
||||
'uptime files',
|
||||
];
|
||||
|
||||
/**
|
||||
* Initialize the blocker.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function init() {
|
||||
if ( aioseo()->options->deprecated->tools->blocker->blockBots ) {
|
||||
$uploadDirectory = wp_upload_dir();
|
||||
$logDirectory = $uploadDirectory['basedir'] . '/aioseo/logs/';
|
||||
if ( wp_mkdir_p( $logDirectory ) ) {
|
||||
$fs = aioseo()->core->fs;
|
||||
$filePath = $logDirectory . 'aioseo-bad-bot-blocker.log';
|
||||
if ( ! $fs->exists( $filePath ) ) {
|
||||
$fs->touch( $filePath );
|
||||
}
|
||||
|
||||
if ( $fs->exists( $filePath ) ) {
|
||||
$this->log = new \AIOSEO\Vendor\Monolog\Logger( 'aioseo-bad-bot-blocker' );
|
||||
$this->log->pushHandler( new \AIOSEO\Vendor\Monolog\Handler\StreamHandler( $filePath ) );
|
||||
}
|
||||
}
|
||||
|
||||
$blockReferer = aioseo()->options->deprecated->tools->blocker->blockReferer;
|
||||
$track = aioseo()->options->deprecated->tools->blocker->track;
|
||||
$ip = ! empty( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : '';
|
||||
$ip = aioseo()->helpers->validateIp( $ip ) ? $ip : __( '(Invalid IP)', 'all-in-one-seo-pack' );
|
||||
if ( ! $this->allowBot() ) {
|
||||
if ( $track ) {
|
||||
$userAgent = ! empty( $_SERVER['HTTP_USER_AGENT'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) : __( 'Unknown User Agent', 'all-in-one-seo-pack' );
|
||||
// Translators: 1 - The IP address. 2 - The user agent.
|
||||
$this->track( sprintf( __( 'Blocked bot with IP %1$s -- matched user agent %2$s found in blocklist.', 'all-in-one-seo-pack' ), $ip, $userAgent ) );
|
||||
}
|
||||
status_header( 503 );
|
||||
exit;
|
||||
} elseif ( $blockReferer && $this->isBadReferer() ) {
|
||||
status_header( 503 );
|
||||
if ( $track ) {
|
||||
$referer = ! empty( $_SERVER['HTTP_REFERER'] ) ? esc_url_raw( wp_unslash( $_SERVER['HTTP_REFERER'] ) ) : '';
|
||||
// Translators: 1 - The IP address. 2 - The referer.
|
||||
$this->track( sprintf( __( 'Blocked bot with IP %1$s -- matched referer %2$s found in blocklist.', 'all-in-one-seo-pack' ), $ip, $referer ) );
|
||||
}
|
||||
status_header( 503 );
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the size of the log file.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @return integer The size of the log file.
|
||||
*/
|
||||
public function getLogSize() {
|
||||
$uploadDirectory = wp_upload_dir();
|
||||
$logDirectory = $uploadDirectory['basedir'] . '/aioseo/logs/';
|
||||
$filePath = $logDirectory . 'aioseo-bad-bot-blocker.log';
|
||||
$fs = aioseo()->core->fs;
|
||||
if ( $fs->exists( $filePath ) ) {
|
||||
return $fs->size( $filePath );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the log for the bad bot blocker.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @return integer The file size.
|
||||
*/
|
||||
public function clearLog() {
|
||||
$uploadDirectory = wp_upload_dir();
|
||||
$logDirectory = $uploadDirectory['basedir'] . '/aioseo/logs/';
|
||||
$filePath = $logDirectory . 'aioseo-bad-bot-blocker.log';
|
||||
$fs = aioseo()->core->fs;
|
||||
if ( $fs->exists( $filePath ) ) {
|
||||
$fs->putContents( $filePath, '' );
|
||||
}
|
||||
|
||||
return $this->getLogSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the bot list.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @return array The bot list.
|
||||
*/
|
||||
public function getBotList() {
|
||||
return $this->botList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the referer list.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @return array The referer list.
|
||||
*/
|
||||
public function getRefererList() {
|
||||
return $this->refererList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not to allow the bot through.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @return boolean True if this is a good bot and we can allow it through.
|
||||
*/
|
||||
private function allowBot() {
|
||||
$allow = true;
|
||||
if ( ! $this->isGoodBot() && $this->isBadBot() && ! is_user_logged_in() ) {
|
||||
$allow = false;
|
||||
}
|
||||
|
||||
return apply_filters( 'aioseo_allow_bot', $allow );
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this a good bot?
|
||||
*
|
||||
* @see Original code, thanks to Sean M. Brown.
|
||||
* @link http://smbrown.wordpress.com/2009/04/29/verify-googlebot-forward-reverse-dns/
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @return boolean True if this is a good bot.
|
||||
*/
|
||||
private function isGoodBot() {
|
||||
$botList = [
|
||||
'Yahoo! Slurp' => 'crawl.yahoo.net',
|
||||
'googlebot' => '.googlebot.com',
|
||||
'msnbot' => 'search.msn.com',
|
||||
];
|
||||
$botList = apply_filters( 'aioseo_good_bot_list', $botList );
|
||||
if ( ! empty( $botList ) ) {
|
||||
if ( ! isset( $_SERVER['HTTP_USER_AGENT'] ) ) {
|
||||
return false;
|
||||
}
|
||||
$ua = ! empty( $_SERVER['HTTP_USER_AGENT'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) : '';
|
||||
$uas = $this->prepareList( $botList );
|
||||
if ( preg_match( '/' . $uas . '/i', (string) $ua ) ) {
|
||||
$ip = ! empty( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : '';
|
||||
$hostname = gethostbyaddr( $ip );
|
||||
$ipByHostName = gethostbyname( $hostname );
|
||||
if ( $ipByHostName === $ip ) {
|
||||
$hosts = array_values( $botList );
|
||||
foreach ( $hosts as $k => $h ) {
|
||||
$hosts[ $k ] = preg_quote( (string) $h ) . '$';
|
||||
}
|
||||
$hosts = join( '|', $hosts );
|
||||
if ( preg_match( '/' . $hosts . '/i', (string) $hostname ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this a bad bot?
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @return boolean True if it is a bad bot.
|
||||
*/
|
||||
private function isBadBot() {
|
||||
$botList = aioseo()->options->deprecated->tools->blocker->custom->enable
|
||||
? explode( "\n", aioseo()->options->deprecated->tools->blocker->custom->bots )
|
||||
: $this->botList;
|
||||
$botList = apply_filters( 'aioseo_bad_bot_list', $botList );
|
||||
if ( ! empty( $botList ) ) {
|
||||
if ( ! isset( $_SERVER['HTTP_USER_AGENT'] ) ) {
|
||||
return false;
|
||||
}
|
||||
$ua = ! empty( $_SERVER['HTTP_USER_AGENT'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) : '';
|
||||
$uas = $this->prepareList( $botList );
|
||||
if ( preg_match( '/' . $uas . '/i', (string) $ua ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this a bad referer?
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @return boolean True if this is a bad referer.
|
||||
*/
|
||||
private function isBadReferer() {
|
||||
$refererList = aioseo()->options->deprecated->tools->blocker->custom->enable
|
||||
? explode( "\n", aioseo()->options->deprecated->tools->blocker->custom->referer )
|
||||
: $this->refererList;
|
||||
$refererList = apply_filters( 'aioseo_bad_referer_list', $refererList );
|
||||
|
||||
if ( ! empty( $refererList ) && ! empty( $_SERVER ) && ! empty( $_SERVER['HTTP_REFERER'] ) ) {
|
||||
$referer = esc_url_raw( sanitize_text_field( wp_unslash( $_SERVER['HTTP_REFERER'] ) ) );
|
||||
$regex = $this->prepareList( $refererList );
|
||||
if ( preg_match( '/' . $regex . '/i', (string) $referer ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quote List for Regex
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @param $list
|
||||
* @param string $quote
|
||||
* @return string
|
||||
*/
|
||||
private function prepareList( $list, $quote = '/' ) {
|
||||
$regex = '';
|
||||
$cont = 0;
|
||||
foreach ( $list as $l ) {
|
||||
$trim_l = trim( $l ); // phpcs:ignore Squiz.NamingConventions.ValidVariableName
|
||||
if ( ! empty( $trim_l ) ) { // phpcs:ignore Squiz.NamingConventions.ValidVariableName
|
||||
if ( $cont ) {
|
||||
$regex .= '|';
|
||||
}
|
||||
$cont = 1;
|
||||
$regex .= preg_quote( (string) trim( $l ), $quote );
|
||||
}
|
||||
}
|
||||
|
||||
return $regex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracks the bad bot that was blocked.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @param string $message The message to log.
|
||||
* @return void
|
||||
*/
|
||||
public function track( $message ) {
|
||||
if ( $this->log ) {
|
||||
$this->log->info( $message );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
namespace AIOSEO\Plugin\Common\Tools;
|
||||
|
||||
// Exit if accessed directly.
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
class Htaccess {
|
||||
/**
|
||||
* The path to the .htaccess file.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $path = '';
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->path = ABSPATH . '.htaccess';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the contents of the .htaccess file.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @return string The contents of the file.
|
||||
*/
|
||||
public function getContents() {
|
||||
$fs = aioseo()->core->fs;
|
||||
if ( ! $fs->exists( $this->path ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$contents = $fs->getContents( $this->path );
|
||||
|
||||
return aioseo()->helpers->encodeOutputHtml( $contents );
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the contents of the .htaccess file.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @param string $contents The contents to write.
|
||||
* @return boolean True if the file was updated.
|
||||
*/
|
||||
public function saveContents( $contents ) {
|
||||
$fs = aioseo()->core->fs;
|
||||
if ( ! $fs->isWritable( $this->path ) ) {
|
||||
return [
|
||||
'success' => false,
|
||||
'reason' => 'file-not-writable',
|
||||
'message' => __( 'We were unable to save the .htaccess file because the file was not writable. Please check the file permissions and try again.', 'all-in-one-seo-pack' )
|
||||
];
|
||||
}
|
||||
|
||||
$fileExists = $fs->exists( $this->path );
|
||||
$originalContents = $fileExists ? $fs->getContents( $this->path ) : null;
|
||||
$fileSaved = $fs->putContents( $this->path, $contents );
|
||||
if ( false === $fileSaved ) {
|
||||
return [
|
||||
'success' => false,
|
||||
'reason' => 'file-not-saved'
|
||||
];
|
||||
}
|
||||
|
||||
$response = wp_remote_get( home_url( '?' . time() ) );
|
||||
$isValidRequest = wp_remote_retrieve_response_code( $response );
|
||||
|
||||
if (
|
||||
// Add an exception for Windows devs since the request fails in Local.
|
||||
! defined( 'AIOSEO_DEV_WINDOWS' ) &&
|
||||
( is_wp_error( $response ) || 200 !== $isValidRequest )
|
||||
) {
|
||||
$fs->putContents( $this->path, $originalContents );
|
||||
|
||||
return [
|
||||
'success' => false,
|
||||
'reason' => 'syntax-errors',
|
||||
'message' => __( 'We were unable to save the .htaccess file due to syntax errors. Please check the code below and try again.', 'all-in-one-seo-pack' )
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'success' => true
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,666 @@
|
||||
<?php
|
||||
namespace AIOSEO\Plugin\Common\Tools;
|
||||
|
||||
// Exit if accessed directly.
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
use AIOSEO\Plugin\Common\Models;
|
||||
|
||||
class RobotsTxt {
|
||||
/**
|
||||
* Which directives are allowed to be extracted.
|
||||
*
|
||||
* @since 4.4.2
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $allowedDirectives = [ 'user-agent', 'allow', 'disallow', 'clean-param', 'crawl-delay' ];
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function __construct() {
|
||||
add_filter( 'robots_txt', [ $this, 'buildRules' ], 10000 );
|
||||
|
||||
if ( ! is_admin() || wp_doing_ajax() || wp_doing_cron() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
add_action( 'init', [ $this, 'checkForPhysicalFiles' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Build out the robots.txt rules.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @param string $original The original rules to parse.
|
||||
* @return string The parsed/appended/modified rules.
|
||||
*/
|
||||
public function buildRules( $original ) {
|
||||
// Other plugins might call this too early.
|
||||
if ( ! property_exists( aioseo(), 'sitemap' ) ) {
|
||||
return $original;
|
||||
}
|
||||
|
||||
$searchAppearanceRules = $this->extractSearchAppearanceRules();
|
||||
$networkRules = [];
|
||||
if ( is_multisite() ) {
|
||||
$searchAppearanceRules = array_merge(
|
||||
$searchAppearanceRules,
|
||||
$this->extractSearchAppearanceRules( aioseo()->networkOptions->tools->robots->rules )
|
||||
);
|
||||
$networkRules = aioseo()->networkOptions->tools->robots->enable ? aioseo()->networkOptions->tools->robots->rules : [];
|
||||
}
|
||||
|
||||
$originalRules = $this->extractRules( $original );
|
||||
$ruleset = $this->mergeRules( $originalRules, $this->groupRulesByUserAgent( $searchAppearanceRules ) );
|
||||
if ( ! aioseo()->options->tools->robots->enable ) {
|
||||
$ruleset = $this->mergeRules( $ruleset, $this->groupRulesByUserAgent( $networkRules ) );
|
||||
} else {
|
||||
$ruleset = $this->mergeRules(
|
||||
$ruleset,
|
||||
$this->mergeRules( $this->groupRulesByUserAgent( $networkRules ), $this->groupRulesByUserAgent( aioseo()->options->tools->robots->rules ) ),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Any plugin can wrongly modify the robots.txt output by hoking into the `do_robots` action hook,
|
||||
* instead of hooking into the `robots_txt` filter hook.
|
||||
* For the first scenario, to make sure our output doesn't conflict with theirs, a new line is necessary.
|
||||
*/
|
||||
return $this->stringifyRuleset( $ruleset ) . "\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges two rulesets.
|
||||
*
|
||||
* @since 4.0.0
|
||||
* @version 4.4.2
|
||||
*
|
||||
* @param array $rules1 An array of rules to merge with.
|
||||
* @param array $rules2 An array of rules to merge.
|
||||
* @param boolean $allowOverride Whether to allow overriding.
|
||||
* @param boolean $allowDuplicates Whether to allow duplicates.
|
||||
* @return array The validated rules.
|
||||
*/
|
||||
private function mergeRules( $rules1, $rules2, $allowOverride = false, $allowDuplicates = false ) {
|
||||
foreach ( $rules2 as $userAgent => $rules ) {
|
||||
if ( empty( $userAgent ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( empty( $rules1[ $userAgent ] ) ) {
|
||||
$rules1[ $userAgent ] = array_unique( $rules2[ $userAgent ] );
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
list( $rules1, $rules2 ) = $this->mergeRulesHelper( 'allow', $userAgent, $rules, $rules1, $rules2, $allowDuplicates, $allowOverride );
|
||||
list( $rules1, $rules2 ) = $this->mergeRulesHelper( 'disallow', $userAgent, $rules, $rules1, $rules2, $allowDuplicates, $allowOverride );
|
||||
|
||||
$rules1[ $userAgent ] = array_unique( array_merge(
|
||||
$rules1[ $userAgent ],
|
||||
$rules2[ $userAgent ]
|
||||
) );
|
||||
}
|
||||
|
||||
return $rules1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for {@see mergeRules()}.
|
||||
*
|
||||
* @since 4.1.2
|
||||
* @version 4.4.2
|
||||
*
|
||||
* @param string $directive The directive (allow/disallow).
|
||||
* @param string $userAgent The user agent.
|
||||
* @param array $rules The rules.
|
||||
* @param array $rules1 The original rules.
|
||||
* @param array $rules2 The extra rules.
|
||||
* @param bool $allowDuplicates Whether duplicates should be allowed
|
||||
* @param bool $allowOverride Whether the extra rules can override the original ones.
|
||||
* @return array The original and extra rules.
|
||||
*/
|
||||
private function mergeRulesHelper( $directive, $userAgent, $rules, $rules1, $rules2, $allowDuplicates, $allowOverride ) {
|
||||
$otherDirective = ( 'allow' === $directive ) ? 'disallow' : 'allow';
|
||||
foreach ( $rules as $index1 => $rule ) {
|
||||
list( , $ruleValue ) = $this->parseRule( $rule );
|
||||
$index2 = array_search( "$otherDirective: $ruleValue", $rules1[ $userAgent ], true );
|
||||
if ( false !== $index2 && ! $allowDuplicates ) {
|
||||
if ( $allowOverride ) {
|
||||
unset( $rules1[ $userAgent ][ $index2 ] );
|
||||
} else {
|
||||
unset( $rules2[ $userAgent ][ $index1 ] );
|
||||
}
|
||||
}
|
||||
|
||||
$pattern = str_replace( [ '.', '*', '?', '$' ], [ '\.', '(.*)', '\?', '\$' ], $ruleValue );
|
||||
|
||||
foreach ( $rules1[ $userAgent ] as $rule1 ) {
|
||||
$matches = [];
|
||||
preg_match( "#^$otherDirective: $pattern$#", (string) $rule1, $matches );
|
||||
}
|
||||
|
||||
if ( ! empty( $matches ) && ! $allowDuplicates ) {
|
||||
unset( $rules2[ $userAgent ][ $index1 ] );
|
||||
}
|
||||
}
|
||||
|
||||
return [ $rules1, $rules2 ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a rule and extracts the directive and value.
|
||||
*
|
||||
* @since 4.4.2
|
||||
*
|
||||
* @param string $rule The rule to parse.
|
||||
* @return array An array containing the parsed directive and value.
|
||||
*/
|
||||
private function parseRule( $rule ) {
|
||||
list( $directive, $value ) = array_map( 'trim', array_pad( explode( ':', $rule, 2 ), 2, '' ) );
|
||||
|
||||
return [ $directive, $value ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Stringifies the parsed rules.
|
||||
*
|
||||
* @since 4.0.0
|
||||
* @version 4.4.2
|
||||
*
|
||||
* @param array $allRules The rules array.
|
||||
* @return string The stringified rules.
|
||||
*/
|
||||
private function stringifyRuleset( $allRules ) {
|
||||
$robots = [];
|
||||
foreach ( $allRules as $userAgent => $rules ) {
|
||||
if ( empty( $userAgent ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$robots[] = "\r\nUser-agent: $userAgent";
|
||||
foreach ( $rules as $rule ) {
|
||||
list( $directive, $value ) = $this->parseRule( $rule );
|
||||
if ( empty( $directive ) || empty( $value ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$robots[] = sprintf( '%s: %s', ucfirst( $directive ), $value );
|
||||
}
|
||||
}
|
||||
|
||||
$robots = implode( "\r\n", $robots );
|
||||
$sitemapUrls = $this->getSitemapRules();
|
||||
if ( ! empty( $sitemapUrls ) ) {
|
||||
$sitemapUrls = implode( "\r\n", $sitemapUrls );
|
||||
$robots .= "\r\n\r\n$sitemapUrls";
|
||||
}
|
||||
|
||||
return trim( $robots );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Sitemap URLs excluding the default ones.
|
||||
*
|
||||
* @since 4.1.7
|
||||
*
|
||||
* @return array An array of the Sitemap URLs.
|
||||
*/
|
||||
private function getSitemapRules() {
|
||||
$defaultSitemaps = $this->extractSitemapUrls( aioseo()->robotsTxt->getDefaultRobotsTxtContent() );
|
||||
$sitemapRules = aioseo()->sitemap->helpers->getSitemapUrlsPrefixed();
|
||||
|
||||
return array_diff( $sitemapRules, $defaultSitemaps );
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the Search Appearance related rules.
|
||||
*
|
||||
* @since 4.8.1
|
||||
*
|
||||
* @param array $rules The rules to extract from.
|
||||
* @return array The Search Appearance related rules.
|
||||
*/
|
||||
public function extractSearchAppearanceRules( $rules = [] ) {
|
||||
$currentRules = $rules ?: aioseo()->options->tools->robots->rules;
|
||||
|
||||
return array_filter( $currentRules, function ( $rule ) {
|
||||
$parseRule = json_decode( $rule, true );
|
||||
|
||||
return ! empty( $parseRule['bot'] ) || ! empty( $parseRule['preventCrawling'] );
|
||||
} );
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the rules.
|
||||
*
|
||||
* @since 4.0.0
|
||||
* @version 4.4.2
|
||||
*
|
||||
* @param array $rules An array of rules.
|
||||
* @return array The rules grouped by user agent.
|
||||
*/
|
||||
private function groupRulesByUserAgent( $rules ) {
|
||||
$groups = [];
|
||||
foreach ( $rules as $rule ) {
|
||||
$r = is_string( $rule ) ? json_decode( $rule, true ) : $rule;
|
||||
if ( empty( $r['userAgent'] ) || empty( $r['fieldValue'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( empty( $groups[ $r['userAgent'] ] ) ) {
|
||||
$groups[ $r['userAgent'] ] = [];
|
||||
}
|
||||
|
||||
$groups[ $r['userAgent'] ][] = "{$r['directive']}: {$r['fieldValue']}";
|
||||
}
|
||||
|
||||
return $groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract rules from a string.
|
||||
*
|
||||
* @since 4.0.0
|
||||
* @version 4.4.2
|
||||
*
|
||||
* @param string $lines The lines to extract from.
|
||||
* @return array An array of extracted rules.
|
||||
*/
|
||||
public function extractRules( $lines ) {
|
||||
$lines = array_filter( array_map( 'trim', explode( "\n", (string) $lines ) ) );
|
||||
$rules = [];
|
||||
$userAgent = null;
|
||||
$prevDirective = null;
|
||||
$prevValue = null;
|
||||
$siblingsUserAgents = [];
|
||||
foreach ( $lines as $line ) {
|
||||
list( $directive, $value ) = $this->parseRule( $line );
|
||||
if ( empty( $directive ) || empty( $value ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$directive = strtolower( $directive );
|
||||
if ( ! in_array( $directive, $this->allowedDirectives, true ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$value = $this->sanitizeDirectiveValue( $directive, $value );
|
||||
if ( ! $value ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( 'user-agent' === $directive ) {
|
||||
if (
|
||||
! empty( $prevDirective ) &&
|
||||
! empty( $prevValue ) &&
|
||||
'user-agent' === $prevDirective
|
||||
) {
|
||||
$siblingsUserAgents[] = $prevValue;
|
||||
}
|
||||
|
||||
$userAgent = $value;
|
||||
$rules[ $userAgent ] = ! empty( $rules[ $userAgent ] ) ? $rules[ $userAgent ] : [];
|
||||
} else {
|
||||
$rules[ $userAgent ][] = "$directive: $value";
|
||||
if ( $siblingsUserAgents ) {
|
||||
foreach ( $siblingsUserAgents as $siblingUserAgent ) {
|
||||
$rules[ $siblingUserAgent ] = $rules[ $userAgent ];
|
||||
}
|
||||
|
||||
$siblingsUserAgents = [];
|
||||
}
|
||||
}
|
||||
|
||||
$prevDirective = $directive;
|
||||
$prevValue = $value;
|
||||
}
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract sitemap URLs from a string.
|
||||
*
|
||||
* @since 4.0.10
|
||||
*
|
||||
* @param string $lines The lines to extract from.
|
||||
* @return array An array of sitemap URLs.
|
||||
*/
|
||||
public function extractSitemapUrls( $lines ) {
|
||||
$lines = array_filter( array_map( 'trim', explode( "\n", (string) $lines ) ) );
|
||||
$sitemapUrls = [];
|
||||
foreach ( $lines as $line ) {
|
||||
$array = array_map( 'trim', explode( 'sitemap:', strtolower( $line ) ) );
|
||||
if ( ! empty( $array[1] ) ) {
|
||||
$sitemapUrls[] = trim( $line );
|
||||
}
|
||||
}
|
||||
|
||||
return $sitemapUrls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize the robots.txt rule directive value.
|
||||
*
|
||||
* @since 4.0.0
|
||||
* @version 4.4.2
|
||||
*
|
||||
* @param string $directive The directive.
|
||||
* @param string $value The value.
|
||||
* @return string The directive value.
|
||||
*/
|
||||
private function sanitizeDirectiveValue( $directive, $value ) {
|
||||
// Percent-encoded characters are stripped from our option values, so we decode.
|
||||
$value = rawurldecode( trim( $value ) );
|
||||
if ( ! $value ) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
$value = preg_replace( '/[><]/', '', (string) $value );
|
||||
|
||||
if ( 'user-agent' === $directive ) {
|
||||
$value = preg_replace( '/[^a-z0-9\-_*,.\s]/i', '', (string) $value );
|
||||
}
|
||||
|
||||
if ( 'allow' === $directive || 'disallow' === $directive ) {
|
||||
$value = preg_replace( '/^\/+/', '/', (string) $value );
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a physical robots.txt file exists, and if it does add a notice.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function checkForPhysicalFiles() {
|
||||
if ( ! $this->hasPhysicalRobotsTxt() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$notification = Models\Notification::getNotificationByName( 'robots-physical-file' );
|
||||
if ( $notification->exists() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
Models\Notification::addNotification( [
|
||||
'slug' => uniqid(),
|
||||
'notification_name' => 'robots-physical-file',
|
||||
'title' => __( 'Physical Robots.txt File Detected', 'all-in-one-seo-pack' ),
|
||||
'content' => sprintf(
|
||||
// Translators: 1 - The plugin short name ("AIOSEO"), 2 - The plugin short name ("AIOSEO").
|
||||
__( '%1$s has detected a physical robots.txt file in the root folder of your WordPress installation. We recommend removing this file as it could cause conflicts with WordPress\' dynamically generated one. %2$s can import this file and delete it, or you can simply delete it.', 'all-in-one-seo-pack' ), // phpcs:ignore Generic.Files.LineLength.MaxExceeded
|
||||
AIOSEO_PLUGIN_SHORT_NAME,
|
||||
AIOSEO_PLUGIN_SHORT_NAME
|
||||
),
|
||||
'type' => 'error',
|
||||
'level' => [ 'all' ],
|
||||
'button1_label' => __( 'Import and Delete', 'all-in-one-seo-pack' ),
|
||||
'button1_action' => 'http://action#tools/import-robots-txt?redirect=aioseo-tools:robots-editor',
|
||||
'button2_label' => __( 'Delete', 'all-in-one-seo-pack' ),
|
||||
'button2_action' => 'http://action#tools/delete-robots-txt?redirect=aioseo-tools:robots-editor',
|
||||
'start' => gmdate( 'Y-m-d H:i:s' )
|
||||
] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Import physical robots.txt file.
|
||||
*
|
||||
* @since 4.0.0
|
||||
* @version 4.4.2
|
||||
*
|
||||
* @param int|string $blogId The blog ID or 'network'.
|
||||
* @throws \Exception If request fails or file is not readable.
|
||||
* @return boolean Whether the file imported correctly.
|
||||
*/
|
||||
public function importPhysicalRobotsTxt( $blogId ) {
|
||||
try {
|
||||
$fs = aioseo()->core->fs;
|
||||
if ( ! $fs->isWpfsValid() ) {
|
||||
$invalid = true;
|
||||
}
|
||||
|
||||
$file = trailingslashit( $fs->fs->abspath() ) . 'robots.txt';
|
||||
if (
|
||||
isset( $invalid ) ||
|
||||
! $fs->isReadable( $file )
|
||||
) {
|
||||
throw new \Exception( esc_html__( 'There was an error importing the static robots.txt file.', 'all-in-one-seo-pack' ) );
|
||||
}
|
||||
|
||||
$lines = trim( (string) $fs->getContents( $file ) );
|
||||
if ( $lines ) {
|
||||
$this->importRobotsTxtFromText( $lines, $blogId );
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch ( \Exception $e ) {
|
||||
throw new \Exception( esc_html( $e->getMessage() ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Import robots.txt from a URL.
|
||||
*
|
||||
* @since 4.4.2
|
||||
*
|
||||
* @param string $text The text to import from.
|
||||
* @param int|string $blogId The blog ID or 'network'.
|
||||
* @throws \Exception If no User-agent is found.
|
||||
* @return boolean Whether the file imported correctly or not.
|
||||
*/
|
||||
public function importRobotsTxtFromText( $text, $blogId ) {
|
||||
$newRules = $this->extractRules( $text );
|
||||
if ( ! key( $newRules ) ) {
|
||||
throw new \Exception( esc_html__( 'No User-agent found in the content beginning.', 'all-in-one-seo-pack' ) );
|
||||
}
|
||||
|
||||
$options = aioseo()->options;
|
||||
if ( 'network' === $blogId ) {
|
||||
$options = aioseo()->networkOptions;
|
||||
}
|
||||
|
||||
$options->tools->robots->rules = array_unique( array_merge( $options->tools->robots->rules, $this->prepareRobotsTxt( $newRules ) ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Import robots.txt from a URL.
|
||||
*
|
||||
* @since 4.4.2
|
||||
*
|
||||
* @param string $url The URL to import from.
|
||||
* @param int|string $blogId The blog ID or 'network'.
|
||||
* @throws \Exception If request fails.
|
||||
* @return bool Whether the import was successful or not.
|
||||
*/
|
||||
public function importRobotsTxtFromUrl( $url, $blogId ) {
|
||||
$request = wp_remote_get( $url, [
|
||||
'timeout' => 10,
|
||||
'sslverify' => false
|
||||
] );
|
||||
$robotsTxtContent = wp_remote_retrieve_body( $request );
|
||||
if ( ! $robotsTxtContent ) {
|
||||
throw new \Exception( esc_html__( 'There was an error importing the robots.txt content from the URL.', 'all-in-one-seo-pack' ) );
|
||||
}
|
||||
|
||||
$options = aioseo()->options;
|
||||
if ( 'network' === $blogId ) {
|
||||
$options = aioseo()->networkOptions;
|
||||
}
|
||||
|
||||
$newRules = $this->extractRules( $robotsTxtContent );
|
||||
|
||||
$options->tools->robots->rules = array_unique( array_merge( $options->tools->robots->rules, $this->prepareRobotsTxt( $newRules ) ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the physical robots.txt file.
|
||||
*
|
||||
* @since 4.4.5
|
||||
*
|
||||
* @throws \Exception If the file is not readable, or it can't be deleted.
|
||||
* @return true True if the file was successfully deleted.
|
||||
*/
|
||||
public function deletePhysicalRobotsTxt() {
|
||||
try {
|
||||
$fs = aioseo()->core->fs;
|
||||
if (
|
||||
! $fs->isWpfsValid() ||
|
||||
! $fs->fs->delete( trailingslashit( $fs->fs->abspath() ) . 'robots.txt' )
|
||||
) {
|
||||
throw new \Exception( __( 'There was an error deleting the physical robots.txt file.', 'all-in-one-seo-pack' ) );
|
||||
}
|
||||
|
||||
Models\Notification::deleteNotificationByName( 'robots-physical-file' );
|
||||
|
||||
return true;
|
||||
} catch ( \Exception $e ) {
|
||||
throw new \Exception( esc_html( $e->getMessage() ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare robots.txt rules to save.
|
||||
*
|
||||
* @since 4.1.4
|
||||
*
|
||||
* @param array $allRules Array with the rules.
|
||||
* @return array The prepared rules array.
|
||||
*/
|
||||
public function prepareRobotsTxt( $allRules = [] ) {
|
||||
$robots = [];
|
||||
foreach ( $allRules as $userAgent => $rules ) {
|
||||
if ( empty( $userAgent ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ( $rules as $rule ) {
|
||||
list( $directive, $value ) = $this->parseRule( $rule );
|
||||
if ( empty( $directive ) || empty( $value ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
'*' === $userAgent &&
|
||||
(
|
||||
'allow' === $directive && '/wp-admin/admin-ajax.php' === $value ||
|
||||
'disallow' === $directive && '/wp-admin/' === $value
|
||||
)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$robots[] = wp_json_encode( [
|
||||
'userAgent' => $userAgent,
|
||||
'directive' => $directive,
|
||||
'fieldValue' => $value
|
||||
] );
|
||||
}
|
||||
}
|
||||
|
||||
return $robots;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a physical robots.txt file exists.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @return boolean True if it does, false if not.
|
||||
*/
|
||||
public function hasPhysicalRobotsTxt() {
|
||||
$fs = aioseo()->core->fs;
|
||||
if ( ! $fs->isWpfsValid() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$accessType = get_filesystem_method();
|
||||
if ( 'direct' === $accessType ) {
|
||||
$file = trailingslashit( $fs->fs->abspath() ) . 'robots.txt';
|
||||
|
||||
return $fs->exists( $file );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default Robots.txt lines (excluding our own).
|
||||
*
|
||||
* @since 4.1.7
|
||||
* @version 4.4.2
|
||||
*
|
||||
* @return string The robots.txt content rules (excluding our own).
|
||||
*/
|
||||
public function getDefaultRobotsTxtContent() {
|
||||
// First, we need to remove our filter, so that it doesn't run unintentionally.
|
||||
remove_filter( 'robots_txt', [ $this, 'buildRules' ], 10000 );
|
||||
|
||||
ob_start();
|
||||
do_robots();
|
||||
if ( is_admin() ) {
|
||||
header( 'Content-Type: text/html; charset=utf-8' );
|
||||
}
|
||||
$rules = strval( ob_get_clean() );
|
||||
|
||||
// Add the filter back.
|
||||
add_filter( 'robots_txt', [ $this, 'buildRules' ], 10000 );
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
/**
|
||||
* A check to see if the rewrite rules are set.
|
||||
* This isn't perfect, but it will help us know in most cases.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @return boolean Whether the rewrite rules are set or not.
|
||||
*/
|
||||
public function rewriteRulesExist() {
|
||||
// If we have a physical file, it's almost impossible to tell if the rewrite rules are set.
|
||||
// The only scenario is if we still get a 404.
|
||||
$response = wp_remote_get( aioseo()->helpers->getSiteUrl() . '/robots.txt' );
|
||||
if ( 299 < wp_remote_retrieve_response_code( $response ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the Search Appearance related rules.
|
||||
*
|
||||
* @since 4.8.1
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function resetSearchAppearanceRules() {
|
||||
$currentRules = aioseo()->options->tools->robots->rules;
|
||||
$newRules = [];
|
||||
foreach ( ( $currentRules ?? [] ) as $rule ) {
|
||||
$parseRule = json_decode( $rule, true );
|
||||
if ( empty( $parseRule['bot'] ) && empty( $parseRule['preventCrawling'] ) ) {
|
||||
$newRules[] = $rule;
|
||||
}
|
||||
}
|
||||
|
||||
aioseo()->options->tools->robots->rules = $newRules;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,421 @@
|
||||
<?php
|
||||
namespace AIOSEO\Plugin\Common\Tools;
|
||||
|
||||
// Exit if accessed directly.
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
class SystemStatus {
|
||||
/**
|
||||
* Get an aggregated list of all system info.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @return array An array of system information.
|
||||
*/
|
||||
public static function getSystemStatusInfo() {
|
||||
return [
|
||||
'wordPress' => self::getWordPressInfo(),
|
||||
'constants' => self::getConstants(),
|
||||
'serverInfo' => self::getServerInfo(),
|
||||
'muPlugins' => self::mustUsePlugins(),
|
||||
'activeTheme' => self::activeTheme(),
|
||||
'activePlugins' => self::activePlugins(),
|
||||
'inactivePlugins' => self::inactivePlugins(),
|
||||
'database' => self::getDatabaseInfo()
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of system info from WordPress.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @return array An array of system info.
|
||||
*/
|
||||
public static function getWordPressInfo() {
|
||||
$uploadsDir = wp_upload_dir();
|
||||
$version = get_bloginfo( 'version' );
|
||||
$updates = get_site_transient( 'update_core' );
|
||||
$updateVersion = ! empty( $updates->updates[0]->version ) ? $updates->updates[0]->version : '';
|
||||
if ( version_compare( $version, $updateVersion, '<' ) ) {
|
||||
$version .= ' (' . __( 'Latest version:', 'all-in-one-seo-pack' ) . ' ' . $updateVersion . ')';
|
||||
}
|
||||
|
||||
return [
|
||||
'label' => 'WordPress',
|
||||
'results' => [
|
||||
[
|
||||
'header' => __( 'Version', 'all-in-one-seo-pack' ),
|
||||
'value' => $version
|
||||
],
|
||||
[
|
||||
'header' => __( 'Site Title', 'all-in-one-seo-pack' ),
|
||||
'value' => get_bloginfo( 'name' )
|
||||
],
|
||||
[
|
||||
'header' => __( 'Site Language', 'all-in-one-seo-pack' ),
|
||||
'value' => get_locale() ?: 'en_US'
|
||||
],
|
||||
[
|
||||
'header' => __( 'User Language', 'all-in-one-seo-pack' ),
|
||||
'value' => get_user_locale( get_current_user_id() )
|
||||
],
|
||||
[
|
||||
'header' => __( 'Timezone', 'all-in-one-seo-pack' ),
|
||||
'value' => wp_timezone_string()
|
||||
],
|
||||
[
|
||||
'header' => __( 'Home URL', 'all-in-one-seo-pack' ),
|
||||
'value' => home_url()
|
||||
],
|
||||
[
|
||||
'header' => __( 'Site URL', 'all-in-one-seo-pack' ),
|
||||
'value' => site_url()
|
||||
],
|
||||
[
|
||||
'header' => __( 'Permalink Structure', 'all-in-one-seo-pack' ),
|
||||
'value' => get_option( 'permalink_structure' ) ? get_option( 'permalink_structure' ) : __( 'Default', 'all-in-one-seo-pack' )
|
||||
],
|
||||
[
|
||||
'header' => __( 'Multisite', 'all-in-one-seo-pack' ),
|
||||
'value' => is_multisite() ? __( 'Yes', 'all-in-one-seo-pack' ) : __( 'No', 'all-in-one-seo-pack' )
|
||||
],
|
||||
[
|
||||
'header' => 'HTTPS',
|
||||
'value' => is_ssl() ? __( 'Yes', 'all-in-one-seo-pack' ) : __( 'No', 'all-in-one-seo-pack' )
|
||||
],
|
||||
[
|
||||
'header' => __( 'User Count', 'all-in-one-seo-pack' ),
|
||||
'value' => count_users()['total_users']
|
||||
],
|
||||
[
|
||||
'header' => __( 'Front Page Info', 'all-in-one-seo-pack' ),
|
||||
'value' => 'page' === get_option( 'show_on_front' ) ? get_option( 'show_on_front' ) . ' [ID: ' . get_option( 'page_on_front' ) . ']' : get_option( 'show_on_front' )
|
||||
],
|
||||
[
|
||||
'header' => __( 'Search Engine Visibility', 'all-in-one-seo-pack' ),
|
||||
'value' => get_option( 'blog_public' ) ? __( 'Visible', 'all-in-one-seo-pack' ) : __( 'Hidden', 'all-in-one-seo-pack' )
|
||||
],
|
||||
[
|
||||
'header' => __( 'Upload Directory Info', 'all-in-one-seo-pack' ),
|
||||
'value' =>
|
||||
__( 'Path:', 'all-in-one-seo-pack' ) . ' ' . $uploadsDir['path'] . ', ' .
|
||||
__( 'Url:', 'all-in-one-seo-pack' ) . ' ' . $uploadsDir['url'] . ', ' .
|
||||
__( 'Base Directory:', 'all-in-one-seo-pack' ) . ' ' . $uploadsDir['basedir'] . ', ' .
|
||||
__( 'Base URL:', 'all-in-one-seo-pack' ) . ' ' . $uploadsDir['baseurl']
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of database info from WordPress.
|
||||
*
|
||||
* @since 4.4.5
|
||||
*
|
||||
* @return array An array of database info.
|
||||
*/
|
||||
public static function getDatabaseInfo() {
|
||||
$dbInfo = aioseo()->core->db->getDatabaseInfo();
|
||||
if ( empty( $dbInfo['tables'] ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if ( ! aioseo()->helpers->isDev() ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$results = [];
|
||||
$tables = array_merge( $dbInfo['tables']['aioseo'], $dbInfo['tables']['other'] );
|
||||
foreach ( $tables as $tableName => $tableData ) {
|
||||
$results[] = [
|
||||
'header' => $tableName,
|
||||
'value' => sprintf(
|
||||
// Translators: %1$s is the data size, %2$s is the index size, %3$s is the engine type.
|
||||
__( 'Data: %1$.2f MB / Index: %2$.2f MB / Engine: %3$s / Collation: %4$s', 'all-in-one-seo-pack' ),
|
||||
$tableData['data'],
|
||||
$tableData['index'],
|
||||
$tableData['engine'],
|
||||
$tableData['collation']
|
||||
)
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'label' => __( 'Database', 'all-in-one-seo-pack' ),
|
||||
'results' => array_merge( [
|
||||
[
|
||||
'header' => __( 'Database Size', 'all-in-one-seo-pack' ),
|
||||
'value' => sprintf( '%.2f MB', $dbInfo['size']['data'] + $dbInfo['size']['index'] )
|
||||
]
|
||||
], $results )
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of system info from WordPress constants.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @return array An array of system info.
|
||||
*/
|
||||
public static function getConstants() {
|
||||
return [
|
||||
'label' => __( 'Constants', 'all-in-one-seo-pack' ),
|
||||
'results' => [
|
||||
[
|
||||
'header' => 'ABSPATH',
|
||||
'value' => ABSPATH
|
||||
],
|
||||
[
|
||||
'header' => 'WP_CONTENT_DIR',
|
||||
'value' => defined( 'WP_CONTENT_DIR' ) ? ( WP_CONTENT_DIR ? WP_CONTENT_DIR : __( 'Disabled', 'all-in-one-seo-pack' ) ) : __( 'Not set', 'all-in-one-seo-pack' )
|
||||
],
|
||||
[
|
||||
'header' => 'WP_CONTENT_URL',
|
||||
'value' => defined( 'WP_CONTENT_URL' ) ? ( WP_CONTENT_URL ? WP_CONTENT_URL : __( 'Disabled', 'all-in-one-seo-pack' ) ) : __( 'Not set', 'all-in-one-seo-pack' )
|
||||
],
|
||||
[
|
||||
'header' => 'UPLOADS',
|
||||
'value' => defined( 'UPLOADS' ) ? ( UPLOADS ? UPLOADS : __( 'Disabled', 'all-in-one-seo-pack' ) ) : __( 'Not set', 'all-in-one-seo-pack' )
|
||||
],
|
||||
[
|
||||
'header' => 'WP_DEBUG',
|
||||
'value' => defined( 'WP_DEBUG' ) ? ( WP_DEBUG ? WP_DEBUG : __( 'Disabled', 'all-in-one-seo-pack' ) ) : __( 'Not set', 'all-in-one-seo-pack' )
|
||||
],
|
||||
[
|
||||
'header' => 'WP_DEBUG_LOG',
|
||||
'value' => defined( 'WP_DEBUG_LOG' ) ? ( WP_DEBUG_LOG ? WP_DEBUG_LOG : __( 'Disabled', 'all-in-one-seo-pack' ) ) : __( 'Not set', 'all-in-one-seo-pack' )
|
||||
],
|
||||
[
|
||||
'header' => 'WP_DEBUG_DISPLAY',
|
||||
'value' => defined( 'WP_DEBUG_DISPLAY' ) ? ( WP_DEBUG_DISPLAY ? WP_DEBUG_DISPLAY : __( 'Disabled', 'all-in-one-seo-pack' ) ) : __( 'Not set', 'all-in-one-seo-pack' )
|
||||
],
|
||||
[
|
||||
'header' => 'WP_POST_REVISIONS',
|
||||
'value' => defined( 'WP_POST_REVISIONS' ) ? WP_POST_REVISIONS : __( 'Not set', 'all-in-one-seo-pack' )
|
||||
],
|
||||
[
|
||||
'header' => 'DISABLE_WP_CRON',
|
||||
'value' => defined( 'DISABLE_WP_CRON' ) ? DISABLE_WP_CRON : __( 'Not set', 'all-in-one-seo-pack' )
|
||||
],
|
||||
[
|
||||
'header' => 'EMPTY_TRASH_DAYS',
|
||||
'value' => defined( 'EMPTY_TRASH_DAYS' ) ? EMPTY_TRASH_DAYS : __( 'Not set', 'all-in-one-seo-pack' )
|
||||
],
|
||||
[
|
||||
'header' => 'AUTOSAVE_INTERVAL',
|
||||
'value' => defined( 'AUTOSAVE_INTERVAL' ) ? AUTOSAVE_INTERVAL : __( 'Not set', 'all-in-one-seo-pack' )
|
||||
],
|
||||
[
|
||||
'header' => 'SCRIPT_DEBUG',
|
||||
'value' => defined( 'SCRIPT_DEBUG' ) ? SCRIPT_DEBUG : __( 'Not set', 'all-in-one-seo-pack' )
|
||||
],
|
||||
[
|
||||
'header' => 'DB_CHARSET',
|
||||
'value' => defined( 'DB_CHARSET' ) ? ( DB_CHARSET ? DB_CHARSET : __( 'Disabled', 'all-in-one-seo-pack' ) ) : __( 'Not set', 'all-in-one-seo-pack' )
|
||||
],
|
||||
[
|
||||
'header' => 'DB_COLLATE',
|
||||
'value' => defined( 'DB_COLLATE' ) ? ( DB_COLLATE ? DB_COLLATE : __( 'Disabled', 'all-in-one-seo-pack' ) ) : __( 'Not set', 'all-in-one-seo-pack' )
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of system info from the server.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @return array An array of system info.
|
||||
*/
|
||||
public static function getServerInfo() {
|
||||
$sqlMode = null;
|
||||
$mysqlInfo = aioseo()->core->db->db->get_results( "SHOW VARIABLES LIKE 'sql_mode'" );
|
||||
if ( ! empty( $mysqlInfo ) && is_array( $mysqlInfo ) ) {
|
||||
$sqlMode = $mysqlInfo[0]->Value;
|
||||
}
|
||||
|
||||
$dbServerInfo = method_exists( aioseo()->core->db->db, 'db_server_info' )
|
||||
? aioseo()->core->db->db->db_server_info()
|
||||
: ( function_exists( 'mysqli_get_server_info' )
|
||||
? mysqli_get_server_info( aioseo()->core->db->db->dbh ) // phpcs:ignore WordPress.DB.RestrictedFunctions.mysql_mysqli_get_server_info
|
||||
: ''
|
||||
);
|
||||
|
||||
return [
|
||||
'label' => __( 'Server Info', 'all-in-one-seo-pack' ),
|
||||
'results' => [
|
||||
[
|
||||
'header' => __( 'Operating System', 'all-in-one-seo-pack' ),
|
||||
'value' => PHP_OS
|
||||
],
|
||||
[
|
||||
'header' => __( 'Web Server', 'all-in-one-seo-pack' ),
|
||||
'value' => ! empty( $_SERVER['SERVER_SOFTWARE'] ) ? sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ) : __( 'unknown', 'all-in-one-seo-pack' )
|
||||
],
|
||||
[
|
||||
'header' => __( 'Memory Usage', 'all-in-one-seo-pack' ),
|
||||
'value' => function_exists( 'memory_get_usage' ) ? round( memory_get_usage() / 1024 / 1024, 2 ) . 'M' : __( 'N/A', 'all-in-one-seo-pack' )
|
||||
],
|
||||
[
|
||||
'header' => __( 'Database Powered By', 'all-in-one-seo-pack' ),
|
||||
'value' => stripos( $dbServerInfo, 'mariadb' ) !== false ? 'MariaDB' : 'MySQL'
|
||||
],
|
||||
[
|
||||
'header' => __( 'Database Version', 'all-in-one-seo-pack' ),
|
||||
'value' => aioseo()->core->db->db->db_version()
|
||||
],
|
||||
[
|
||||
'header' => __( 'SQL Mode', 'all-in-one-seo-pack' ),
|
||||
'value' => $sqlMode ?? __( 'Not Set', 'all-in-one-seo-pack' ),
|
||||
],
|
||||
[
|
||||
'header' => __( 'PHP Version', 'all-in-one-seo-pack' ),
|
||||
'value' => PHP_VERSION
|
||||
],
|
||||
[
|
||||
'header' => __( 'PHP Memory Limit', 'all-in-one-seo-pack' ),
|
||||
'value' => ini_get( 'memory_limit' )
|
||||
],
|
||||
[
|
||||
'header' => __( 'PHP Max Upload Size', 'all-in-one-seo-pack' ),
|
||||
'value' => ini_get( 'upload_max_filesize' )
|
||||
],
|
||||
[
|
||||
'header' => __( 'PHP Max Post Size', 'all-in-one-seo-pack' ),
|
||||
'value' => ini_get( 'post_max_size' )
|
||||
],
|
||||
[
|
||||
'header' => __( 'PHP Max Script Execution Time', 'all-in-one-seo-pack' ),
|
||||
'value' => ini_get( 'max_execution_time' )
|
||||
],
|
||||
[
|
||||
'header' => __( 'PHP Exif Support', 'all-in-one-seo-pack' ),
|
||||
'value' => is_callable( 'exif_read_data' ) ? __( 'Yes', 'all-in-one-seo-pack' ) : __( 'No', 'all-in-one-seo-pack' )
|
||||
],
|
||||
[
|
||||
'header' => __( 'PHP IPTC Support', 'all-in-one-seo-pack' ),
|
||||
'value' => is_callable( 'iptcparse' ) ? __( 'Yes', 'all-in-one-seo-pack' ) : __( 'No', 'all-in-one-seo-pack' )
|
||||
],
|
||||
[
|
||||
'header' => __( 'PHP XML Support', 'all-in-one-seo-pack' ),
|
||||
'value' => is_callable( 'xml_parser_create' ) ? __( 'Yes', 'all-in-one-seo-pack' ) : __( 'No', 'all-in-one-seo-pack' )
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of system info from the active theme.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @return array An array of system info.
|
||||
*/
|
||||
public static function activeTheme() {
|
||||
$themeData = wp_get_theme();
|
||||
|
||||
return [
|
||||
'label' => __( 'Active Theme', 'all-in-one-seo-pack' ),
|
||||
'results' => [
|
||||
[
|
||||
'header' => $themeData->name,
|
||||
'value' => $themeData->version
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of system info from must-use plugins.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @return array An array of system info.
|
||||
*/
|
||||
public static function mustUsePlugins() {
|
||||
$plugins = [];
|
||||
$muPlugins = get_mu_plugins();
|
||||
if ( ! empty( $muPlugins ) ) {
|
||||
foreach ( $muPlugins as $pluginData ) {
|
||||
$plugins[] = [
|
||||
'header' => $pluginData['Name'],
|
||||
'value' => $pluginData['Version']
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'label' => __( 'Must-Use Plugins', 'all-in-one-seo-pack' ),
|
||||
'results' => $plugins
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of system info from active plugins.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @return array An array of system info.
|
||||
*/
|
||||
public static function activePlugins() {
|
||||
$plugins = [];
|
||||
$allPlugins = get_plugins();
|
||||
$activePlugins = get_option( 'active_plugins', [] );
|
||||
$updates = get_plugin_updates();
|
||||
if ( ! empty( $allPlugins ) ) {
|
||||
foreach ( $allPlugins as $pluginPath => $pluginData ) {
|
||||
if ( ! in_array( $pluginPath, $activePlugins, true ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$update = ( array_key_exists( $pluginPath, $updates ) ) ? ' (' . __( 'needs update', 'all-in-one-seo-pack' ) . ' - ' . $updates[ $pluginPath ]->update->new_version . ')' : '';
|
||||
$plugins[] = [
|
||||
'header' => $pluginData['Name'],
|
||||
'value' => $pluginData['Version'] . $update
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'label' => __( 'Active Plugins', 'all-in-one-seo-pack' ),
|
||||
'results' => $plugins
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of system info from inactive plugins.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @return array An array of system info.
|
||||
*/
|
||||
public static function inactivePlugins() {
|
||||
$plugins = [];
|
||||
$allPlugins = get_plugins();
|
||||
$activePlugins = get_option( 'active_plugins', [] );
|
||||
$updates = get_plugin_updates();
|
||||
if ( ! empty( $allPlugins ) ) {
|
||||
foreach ( $allPlugins as $pluginPath => $pluginData ) {
|
||||
if ( in_array( $pluginPath, $activePlugins, true ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$update = ( array_key_exists( $pluginPath, $updates ) ) ? ' (' . __( 'needs update', 'all-in-one-seo-pack' ) . ' - ' . $updates[ $pluginPath ]->update->new_version . ')' : '';
|
||||
$plugins[] = [
|
||||
'header' => $pluginData['Name'],
|
||||
'value' => $pluginData['Version'] . $update
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'label' => __( 'Inactive Plugins', 'all-in-one-seo-pack' ),
|
||||
'results' => $plugins
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user