Commit realizado el 12:13:52 08-04-2024
This commit is contained in:
@@ -0,0 +1,619 @@
|
||||
<?php
|
||||
/**
|
||||
* Admin helper Functions.
|
||||
*
|
||||
* This file contains functions needed on the admin screens.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @package RankMath
|
||||
* @subpackage RankMath\Admin
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Admin;
|
||||
|
||||
use RankMath\Helper;
|
||||
use RankMath\Admin\Admin_Helper as Free_Admin_Helper;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Admin_Helper class.
|
||||
*/
|
||||
class Admin_Helper {
|
||||
|
||||
/**
|
||||
* Get primary term ID.
|
||||
*
|
||||
* @param int $post_id Post ID.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function get_primary_term_id( $post_id = null ) {
|
||||
$taxonomy = self::get_primary_taxonomy( $post_id );
|
||||
if ( ! $taxonomy ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$id = get_post_meta( $post_id ? $post_id : get_the_ID(), 'rank_math_primary_' . $taxonomy['name'], true );
|
||||
|
||||
return $id ? absint( $id ) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current post type.
|
||||
*
|
||||
* @param int $post_id Post ID.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_current_post_type( $post_id = null ) {
|
||||
if ( ! $post_id && function_exists( 'get_current_screen' ) ) {
|
||||
$screen = get_current_screen();
|
||||
return isset( $screen->post_type ) ? $screen->post_type : '';
|
||||
}
|
||||
|
||||
return get_post_type( $post_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get primary taxonomy.
|
||||
*
|
||||
* @param int $post_id Post ID.
|
||||
*
|
||||
* @return bool|array
|
||||
*/
|
||||
public static function get_primary_taxonomy( $post_id = null ) {
|
||||
$taxonomy = false;
|
||||
$post_type = self::get_current_post_type( $post_id );
|
||||
|
||||
/**
|
||||
* Allow disabling the primary term feature.
|
||||
*
|
||||
* @param bool $return True to disable.
|
||||
*/
|
||||
if ( false === apply_filters( 'rank_math/admin/disable_primary_term', false ) ) {
|
||||
$taxonomy = Helper::get_settings( 'titles.pt_' . $post_type . '_primary_taxonomy', false );
|
||||
}
|
||||
|
||||
if ( ! $taxonomy ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$taxonomy = get_taxonomy( $taxonomy );
|
||||
if ( ! $taxonomy ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$primary_taxonomy = [
|
||||
'title' => $taxonomy->labels->singular_name,
|
||||
'name' => $taxonomy->name,
|
||||
'singularLabel' => $taxonomy->labels->singular_name,
|
||||
'restBase' => ( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name,
|
||||
];
|
||||
|
||||
return $primary_taxonomy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if current plan is business.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public static function is_business_plan() {
|
||||
return in_array( self::get_plan(), [ 'business', 'agency' ], true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current plan.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_plan() {
|
||||
$registered = Free_Admin_Helper::get_registration_data();
|
||||
|
||||
return isset( $registered['plan'] ) ? $registered['plan'] : 'pro';
|
||||
}
|
||||
|
||||
/**
|
||||
* Country.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function choices_countries() {
|
||||
return [
|
||||
'all' => __( 'Worldwide', 'rank-math-pro' ),
|
||||
'AF' => __( 'Afghanistan', 'rank-math-pro' ),
|
||||
'AL' => __( 'Albania', 'rank-math-pro' ),
|
||||
'DZ' => __( 'Algeria', 'rank-math-pro' ),
|
||||
'AS' => __( 'American Samoa', 'rank-math-pro' ),
|
||||
'AD' => __( 'Andorra', 'rank-math-pro' ),
|
||||
'AO' => __( 'Angola', 'rank-math-pro' ),
|
||||
'AI' => __( 'Anguilla', 'rank-math-pro' ),
|
||||
'AQ' => __( 'Antarctica', 'rank-math-pro' ),
|
||||
'AG' => __( 'Antigua and Barbuda', 'rank-math-pro' ),
|
||||
'AR' => __( 'Argentina', 'rank-math-pro' ),
|
||||
'AM' => __( 'Armenia', 'rank-math-pro' ),
|
||||
'AW' => __( 'Aruba', 'rank-math-pro' ),
|
||||
'AU' => __( 'Australia', 'rank-math-pro' ),
|
||||
'AT' => __( 'Austria', 'rank-math-pro' ),
|
||||
'AZ' => __( 'Azerbaijan', 'rank-math-pro' ),
|
||||
'BS' => __( 'Bahamas', 'rank-math-pro' ),
|
||||
'BH' => __( 'Bahrain', 'rank-math-pro' ),
|
||||
'BD' => __( 'Bangladesh', 'rank-math-pro' ),
|
||||
'BB' => __( 'Barbados', 'rank-math-pro' ),
|
||||
'BY' => __( 'Belarus', 'rank-math-pro' ),
|
||||
'BE' => __( 'Belgium', 'rank-math-pro' ),
|
||||
'BZ' => __( 'Belize', 'rank-math-pro' ),
|
||||
'BJ' => __( 'Benin', 'rank-math-pro' ),
|
||||
'BM' => __( 'Bermuda', 'rank-math-pro' ),
|
||||
'BT' => __( 'Bhutan', 'rank-math-pro' ),
|
||||
'BO' => __( 'Bolivia', 'rank-math-pro' ),
|
||||
'BA' => __( 'Bosnia and Herzegovina', 'rank-math-pro' ),
|
||||
'BW' => __( 'Botswana', 'rank-math-pro' ),
|
||||
'BV' => __( 'Bouvet Island', 'rank-math-pro' ),
|
||||
'BR' => __( 'Brazil', 'rank-math-pro' ),
|
||||
'IO' => __( 'British Indian Ocean Territory', 'rank-math-pro' ),
|
||||
'BN' => __( 'Brunei Darussalam', 'rank-math-pro' ),
|
||||
'BG' => __( 'Bulgaria', 'rank-math-pro' ),
|
||||
'BF' => __( 'Burkina Faso', 'rank-math-pro' ),
|
||||
'BI' => __( 'Burundi', 'rank-math-pro' ),
|
||||
'KH' => __( 'Cambodia', 'rank-math-pro' ),
|
||||
'CM' => __( 'Cameroon', 'rank-math-pro' ),
|
||||
'CA' => __( 'Canada', 'rank-math-pro' ),
|
||||
'CV' => __( 'Cape Verde', 'rank-math-pro' ),
|
||||
'KY' => __( 'Cayman Islands', 'rank-math-pro' ),
|
||||
'CF' => __( 'Central African Republic', 'rank-math-pro' ),
|
||||
'TD' => __( 'Chad', 'rank-math-pro' ),
|
||||
'CL' => __( 'Chile', 'rank-math-pro' ),
|
||||
'CN' => __( 'China', 'rank-math-pro' ),
|
||||
'CX' => __( 'Christmas Island', 'rank-math-pro' ),
|
||||
'CC' => __( 'Cocos (Keeling) Islands', 'rank-math-pro' ),
|
||||
'CO' => __( 'Colombia', 'rank-math-pro' ),
|
||||
'KM' => __( 'Comoros', 'rank-math-pro' ),
|
||||
'CG' => __( 'Congo', 'rank-math-pro' ),
|
||||
'CD' => __( 'Congo, the Democratic Republic of the', 'rank-math-pro' ),
|
||||
'CK' => __( 'Cook Islands', 'rank-math-pro' ),
|
||||
'CR' => __( 'Costa Rica', 'rank-math-pro' ),
|
||||
'CI' => __( "Cote D'ivoire", 'rank-math-pro' ),
|
||||
'HR' => __( 'Croatia', 'rank-math-pro' ),
|
||||
'CU' => __( 'Cuba', 'rank-math-pro' ),
|
||||
'CY' => __( 'Cyprus', 'rank-math-pro' ),
|
||||
'CZ' => __( 'Czech Republic', 'rank-math-pro' ),
|
||||
'DK' => __( 'Denmark', 'rank-math-pro' ),
|
||||
'DJ' => __( 'Djibouti', 'rank-math-pro' ),
|
||||
'DM' => __( 'Dominica', 'rank-math-pro' ),
|
||||
'DO' => __( 'Dominican Republic', 'rank-math-pro' ),
|
||||
'EC' => __( 'Ecuador', 'rank-math-pro' ),
|
||||
'EG' => __( 'Egypt', 'rank-math-pro' ),
|
||||
'SV' => __( 'El Salvador', 'rank-math-pro' ),
|
||||
'GQ' => __( 'Equatorial Guinea', 'rank-math-pro' ),
|
||||
'ER' => __( 'Eritrea', 'rank-math-pro' ),
|
||||
'EE' => __( 'Estonia', 'rank-math-pro' ),
|
||||
'ET' => __( 'Ethiopia', 'rank-math-pro' ),
|
||||
'FK' => __( 'Falkland Islands (Malvinas)', 'rank-math-pro' ),
|
||||
'FO' => __( 'Faroe Islands', 'rank-math-pro' ),
|
||||
'FJ' => __( 'Fiji', 'rank-math-pro' ),
|
||||
'FI' => __( 'Finland', 'rank-math-pro' ),
|
||||
'FR' => __( 'France', 'rank-math-pro' ),
|
||||
'GF' => __( 'French Guiana', 'rank-math-pro' ),
|
||||
'PF' => __( 'French Polynesia', 'rank-math-pro' ),
|
||||
'TF' => __( 'French Southern Territories', 'rank-math-pro' ),
|
||||
'GA' => __( 'Gabon', 'rank-math-pro' ),
|
||||
'GM' => __( 'Gambia', 'rank-math-pro' ),
|
||||
'GE' => __( 'Georgia', 'rank-math-pro' ),
|
||||
'DE' => __( 'Germany', 'rank-math-pro' ),
|
||||
'GH' => __( 'Ghana', 'rank-math-pro' ),
|
||||
'GI' => __( 'Gibraltar', 'rank-math-pro' ),
|
||||
'GR' => __( 'Greece', 'rank-math-pro' ),
|
||||
'GL' => __( 'Greenland', 'rank-math-pro' ),
|
||||
'GD' => __( 'Grenada', 'rank-math-pro' ),
|
||||
'GP' => __( 'Guadeloupe', 'rank-math-pro' ),
|
||||
'GU' => __( 'Guam', 'rank-math-pro' ),
|
||||
'GT' => __( 'Guatemala', 'rank-math-pro' ),
|
||||
'GN' => __( 'Guinea', 'rank-math-pro' ),
|
||||
'GW' => __( 'Guinea-Bissau', 'rank-math-pro' ),
|
||||
'GY' => __( 'Guyana', 'rank-math-pro' ),
|
||||
'HT' => __( 'Haiti', 'rank-math-pro' ),
|
||||
'HM' => __( 'Heard Island and Mcdonald Islands', 'rank-math-pro' ),
|
||||
'VA' => __( 'Holy See (Vatican City State)', 'rank-math-pro' ),
|
||||
'HN' => __( 'Honduras', 'rank-math-pro' ),
|
||||
'HK' => __( 'Hong Kong', 'rank-math-pro' ),
|
||||
'HU' => __( 'Hungary', 'rank-math-pro' ),
|
||||
'IS' => __( 'Iceland', 'rank-math-pro' ),
|
||||
'IN' => __( 'India', 'rank-math-pro' ),
|
||||
'ID' => __( 'Indonesia', 'rank-math-pro' ),
|
||||
'IR' => __( 'Iran, Islamic Republic of', 'rank-math-pro' ),
|
||||
'IQ' => __( 'Iraq', 'rank-math-pro' ),
|
||||
'IE' => __( 'Ireland', 'rank-math-pro' ),
|
||||
'IL' => __( 'Israel', 'rank-math-pro' ),
|
||||
'IT' => __( 'Italy', 'rank-math-pro' ),
|
||||
'JM' => __( 'Jamaica', 'rank-math-pro' ),
|
||||
'JP' => __( 'Japan', 'rank-math-pro' ),
|
||||
'JO' => __( 'Jordan', 'rank-math-pro' ),
|
||||
'KZ' => __( 'Kazakhstan', 'rank-math-pro' ),
|
||||
'KE' => __( 'Kenya', 'rank-math-pro' ),
|
||||
'KI' => __( 'Kiribati', 'rank-math-pro' ),
|
||||
'KP' => __( "Korea, Democratic People's Republic of", 'rank-math-pro' ),
|
||||
'KR' => __( 'Korea, Republic of', 'rank-math-pro' ),
|
||||
'KW' => __( 'Kuwait', 'rank-math-pro' ),
|
||||
'KG' => __( 'Kyrgyzstan', 'rank-math-pro' ),
|
||||
'LA' => __( "Lao People's Democratic Republic", 'rank-math-pro' ),
|
||||
'LV' => __( 'Latvia', 'rank-math-pro' ),
|
||||
'LB' => __( 'Lebanon', 'rank-math-pro' ),
|
||||
'LS' => __( 'Lesotho', 'rank-math-pro' ),
|
||||
'LR' => __( 'Liberia', 'rank-math-pro' ),
|
||||
'LY' => __( 'Libyan Arab Jamahiriya', 'rank-math-pro' ),
|
||||
'LI' => __( 'Liechtenstein', 'rank-math-pro' ),
|
||||
'LT' => __( 'Lithuania', 'rank-math-pro' ),
|
||||
'LU' => __( 'Luxembourg', 'rank-math-pro' ),
|
||||
'MO' => __( 'Macao', 'rank-math-pro' ),
|
||||
'MK' => __( 'Macedonia, the Former Yugosalv Republic of', 'rank-math-pro' ),
|
||||
'MG' => __( 'Madagascar', 'rank-math-pro' ),
|
||||
'MW' => __( 'Malawi', 'rank-math-pro' ),
|
||||
'MY' => __( 'Malaysia', 'rank-math-pro' ),
|
||||
'MV' => __( 'Maldives', 'rank-math-pro' ),
|
||||
'ML' => __( 'Mali', 'rank-math-pro' ),
|
||||
'MT' => __( 'Malta', 'rank-math-pro' ),
|
||||
'MH' => __( 'Marshall Islands', 'rank-math-pro' ),
|
||||
'MQ' => __( 'Martinique', 'rank-math-pro' ),
|
||||
'MR' => __( 'Mauritania', 'rank-math-pro' ),
|
||||
'MU' => __( 'Mauritius', 'rank-math-pro' ),
|
||||
'YT' => __( 'Mayotte', 'rank-math-pro' ),
|
||||
'MX' => __( 'Mexico', 'rank-math-pro' ),
|
||||
'FM' => __( 'Micronesia, Federated States of', 'rank-math-pro' ),
|
||||
'MC' => __( 'Moldova, Republic of', 'rank-math-pro' ),
|
||||
'MP' => __( 'Northern Mariana Islands', 'rank-math-pro' ),
|
||||
'MC' => __( 'Monaco', 'rank-math-pro' ),
|
||||
'MN' => __( 'Mongolia', 'rank-math-pro' ),
|
||||
'MS' => __( 'Montserrat', 'rank-math-pro' ),
|
||||
'MA' => __( 'Morocco', 'rank-math-pro' ),
|
||||
'MZ' => __( 'Mozambique', 'rank-math-pro' ),
|
||||
'MM' => __( 'Myanmar', 'rank-math-pro' ),
|
||||
'NA' => __( 'Namibia', 'rank-math-pro' ),
|
||||
'NR' => __( 'Nauru', 'rank-math-pro' ),
|
||||
'NP' => __( 'Nepal', 'rank-math-pro' ),
|
||||
'NL' => __( 'Netherlands', 'rank-math-pro' ),
|
||||
'AN' => __( 'Netherlands Antilles', 'rank-math-pro' ),
|
||||
'NC' => __( 'New Caledonia', 'rank-math-pro' ),
|
||||
'NZ' => __( 'New Zealand', 'rank-math-pro' ),
|
||||
'NI' => __( 'Nicaragua', 'rank-math-pro' ),
|
||||
'NE' => __( 'Niger', 'rank-math-pro' ),
|
||||
'NG' => __( 'Nigeria', 'rank-math-pro' ),
|
||||
'NU' => __( 'Niue', 'rank-math-pro' ),
|
||||
'NF' => __( 'Norfolk Island', 'rank-math-pro' ),
|
||||
'MP' => __( 'Northern Mariana Islands', 'rank-math-pro' ),
|
||||
'NO' => __( 'Norway', 'rank-math-pro' ),
|
||||
'OM' => __( 'Oman', 'rank-math-pro' ),
|
||||
'PK' => __( 'Pakistan', 'rank-math-pro' ),
|
||||
'PW' => __( 'Palau', 'rank-math-pro' ),
|
||||
'PS' => __( 'Palestinian Territory, Occupied', 'rank-math-pro' ),
|
||||
'PA' => __( 'Panama', 'rank-math-pro' ),
|
||||
'PG' => __( 'Papua New Guinea', 'rank-math-pro' ),
|
||||
'PY' => __( 'Paraguay', 'rank-math-pro' ),
|
||||
'PE' => __( 'Peru', 'rank-math-pro' ),
|
||||
'PH' => __( 'Philippines', 'rank-math-pro' ),
|
||||
'PN' => __( 'Pitcairn', 'rank-math-pro' ),
|
||||
'PL' => __( 'Poland', 'rank-math-pro' ),
|
||||
'PT' => __( 'Portugal', 'rank-math-pro' ),
|
||||
'PR' => __( 'Puerto Rico', 'rank-math-pro' ),
|
||||
'QA' => __( 'Qatar', 'rank-math-pro' ),
|
||||
'RE' => __( 'Reunion', 'rank-math-pro' ),
|
||||
'RO' => __( 'Romania', 'rank-math-pro' ),
|
||||
'RU' => __( 'Russian Federation', 'rank-math-pro' ),
|
||||
'RW' => __( 'Rwanda', 'rank-math-pro' ),
|
||||
'SH' => __( 'Saint Helena', 'rank-math-pro' ),
|
||||
'KN' => __( 'Saint Kitts and Nevis', 'rank-math-pro' ),
|
||||
'LC' => __( 'Saint Lucia', 'rank-math-pro' ),
|
||||
'PM' => __( 'Saint Pierre and Miquelon', 'rank-math-pro' ),
|
||||
'VC' => __( 'Saint Vincent and the Grenadines', 'rank-math-pro' ),
|
||||
'WS' => __( 'Samoa', 'rank-math-pro' ),
|
||||
'SM' => __( 'San Marino', 'rank-math-pro' ),
|
||||
'ST' => __( 'Sao Tome and Principe', 'rank-math-pro' ),
|
||||
'SA' => __( 'Saudi Arabia', 'rank-math-pro' ),
|
||||
'SN' => __( 'Senegal', 'rank-math-pro' ),
|
||||
'CS' => __( 'Serbia and Montenegro', 'rank-math-pro' ),
|
||||
'SC' => __( 'Seychelles', 'rank-math-pro' ),
|
||||
'SL' => __( 'Sierra Leone', 'rank-math-pro' ),
|
||||
'SG' => __( 'Singapore', 'rank-math-pro' ),
|
||||
'SK' => __( 'Slovakia', 'rank-math-pro' ),
|
||||
'SI' => __( 'Slovenia', 'rank-math-pro' ),
|
||||
'SB' => __( 'Solomon Islands', 'rank-math-pro' ),
|
||||
'SO' => __( 'Somalia', 'rank-math-pro' ),
|
||||
'ZA' => __( 'South Africa', 'rank-math-pro' ),
|
||||
'GS' => __( 'South Georgia and the South Sandwich Islands', 'rank-math-pro' ),
|
||||
'ES' => __( 'Spain', 'rank-math-pro' ),
|
||||
'LK' => __( 'Sri Lanka', 'rank-math-pro' ),
|
||||
'SD' => __( 'Sudan', 'rank-math-pro' ),
|
||||
'SR' => __( 'Suriname', 'rank-math-pro' ),
|
||||
'SJ' => __( 'Svalbard and Jan Mayen', 'rank-math-pro' ),
|
||||
'SZ' => __( 'Swaziland', 'rank-math-pro' ),
|
||||
'SE' => __( 'Sweden', 'rank-math-pro' ),
|
||||
'CH' => __( 'Switzerland', 'rank-math-pro' ),
|
||||
'SY' => __( 'Syrian Arab Republic', 'rank-math-pro' ),
|
||||
'TW' => __( 'Taiwan, Province of China', 'rank-math-pro' ),
|
||||
'TJ' => __( 'Tajikistan', 'rank-math-pro' ),
|
||||
'TZ' => __( 'Tanzania, United Republic of', 'rank-math-pro' ),
|
||||
'TH' => __( 'Thailand', 'rank-math-pro' ),
|
||||
'TL' => __( 'Timor-Leste', 'rank-math-pro' ),
|
||||
'TG' => __( 'Togo', 'rank-math-pro' ),
|
||||
'TK' => __( 'Tokelau', 'rank-math-pro' ),
|
||||
'TO' => __( 'Tonga', 'rank-math-pro' ),
|
||||
'TT' => __( 'Trinidad and Tobago', 'rank-math-pro' ),
|
||||
'TN' => __( 'Tunisia', 'rank-math-pro' ),
|
||||
'TR' => __( 'Turkey', 'rank-math-pro' ),
|
||||
'TM' => __( 'Turkmenistan', 'rank-math-pro' ),
|
||||
'TC' => __( 'Turks and Caicos Islands', 'rank-math-pro' ),
|
||||
'TV' => __( 'Tuvalu', 'rank-math-pro' ),
|
||||
'UG' => __( 'Uganda', 'rank-math-pro' ),
|
||||
'UA' => __( 'Ukraine', 'rank-math-pro' ),
|
||||
'AE' => __( 'United Arab Emirates', 'rank-math-pro' ),
|
||||
'GB' => __( 'United Kingdom', 'rank-math-pro' ),
|
||||
'US' => __( 'United States', 'rank-math-pro' ),
|
||||
'UM' => __( 'United States Minor Outlying Islands', 'rank-math-pro' ),
|
||||
'UY' => __( 'Uruguay', 'rank-math-pro' ),
|
||||
'UZ' => __( 'Uzbekistan', 'rank-math-pro' ),
|
||||
'VU' => __( 'Vanuatu', 'rank-math-pro' ),
|
||||
'VE' => __( 'Venezuela', 'rank-math-pro' ),
|
||||
'VN' => __( 'Viet Nam', 'rank-math-pro' ),
|
||||
'VG' => __( 'Virgin Islands, British', 'rank-math-pro' ),
|
||||
'VI' => __( 'Virgin Islands, U.S.', 'rank-math-pro' ),
|
||||
'WF' => __( 'Wallis and Futuna', 'rank-math-pro' ),
|
||||
'EH' => __( 'Western Sahara', 'rank-math-pro' ),
|
||||
'YE' => __( 'Yemen', 'rank-math-pro' ),
|
||||
'ZM' => __( 'Zambia', 'rank-math-pro' ),
|
||||
'ZW' => __( 'Zimbabwe', 'rank-math-pro' ),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Country.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function choices_countries_3() {
|
||||
return [
|
||||
'all' => __( 'Worldwide', 'rank-math-pro' ),
|
||||
'AFG' => __( 'Afghanistan', 'rank-math-pro' ),
|
||||
'ALA' => __( 'Aland Islands', 'rank-math-pro' ),
|
||||
'ALB' => __( 'Albania', 'rank-math-pro' ),
|
||||
'DZA' => __( 'Algeria', 'rank-math-pro' ),
|
||||
'ASM' => __( 'American Samoa', 'rank-math-pro' ),
|
||||
'AND' => __( 'Andorra', 'rank-math-pro' ),
|
||||
'AGO' => __( 'Angola', 'rank-math-pro' ),
|
||||
'AIA' => __( 'Anguilla', 'rank-math-pro' ),
|
||||
'ATA' => __( 'Antarctica', 'rank-math-pro' ),
|
||||
'ATG' => __( 'Antigua & Barbuda', 'rank-math-pro' ),
|
||||
'ARG' => __( 'Argentina', 'rank-math-pro' ),
|
||||
'ARM' => __( 'Armenia', 'rank-math-pro' ),
|
||||
'ABW' => __( 'Aruba', 'rank-math-pro' ),
|
||||
'AUS' => __( 'Australia', 'rank-math-pro' ),
|
||||
'AUT' => __( 'Austria', 'rank-math-pro' ),
|
||||
'AZE' => __( 'Azerbaijan', 'rank-math-pro' ),
|
||||
'BHS' => __( 'Bahamas', 'rank-math-pro' ),
|
||||
'BHR' => __( 'Bahrain', 'rank-math-pro' ),
|
||||
'BGD' => __( 'Bangladesh', 'rank-math-pro' ),
|
||||
'BRB' => __( 'Barbados', 'rank-math-pro' ),
|
||||
'BLR' => __( 'Belarus', 'rank-math-pro' ),
|
||||
'BEL' => __( 'Belgium', 'rank-math-pro' ),
|
||||
'BLZ' => __( 'Belize', 'rank-math-pro' ),
|
||||
'BEN' => __( 'Benin', 'rank-math-pro' ),
|
||||
'BMU' => __( 'Bermuda', 'rank-math-pro' ),
|
||||
'BTN' => __( 'Bhutan', 'rank-math-pro' ),
|
||||
'BOL' => __( 'Bolivia', 'rank-math-pro' ),
|
||||
'BIH' => __( 'Bosnia & Herzegovina', 'rank-math-pro' ),
|
||||
'BWA' => __( 'Botswana', 'rank-math-pro' ),
|
||||
'BRA' => __( 'Brazil', 'rank-math-pro' ),
|
||||
'IOT' => __( 'British Indian Ocean Territory', 'rank-math-pro' ),
|
||||
'VGB' => __( 'British Virgin Islands', 'rank-math-pro' ),
|
||||
'BRN' => __( 'Brunei', 'rank-math-pro' ),
|
||||
'BGR' => __( 'Bulgaria', 'rank-math-pro' ),
|
||||
'BFA' => __( 'Burkina Faso', 'rank-math-pro' ),
|
||||
'BDI' => __( 'Burundi', 'rank-math-pro' ),
|
||||
'KHM' => __( 'Cambodia', 'rank-math-pro' ),
|
||||
'CMR' => __( 'Cameroon', 'rank-math-pro' ),
|
||||
'CAN' => __( 'Canada', 'rank-math-pro' ),
|
||||
'CPV' => __( 'Cape Verde', 'rank-math-pro' ),
|
||||
'BES' => __( 'Caribbean Netherlands', 'rank-math-pro' ),
|
||||
'CYM' => __( 'Cayman Islands', 'rank-math-pro' ),
|
||||
'CAF' => __( 'Central African Republic', 'rank-math-pro' ),
|
||||
'TCD' => __( 'Chad', 'rank-math-pro' ),
|
||||
'CHL' => __( 'Chile', 'rank-math-pro' ),
|
||||
'CHN' => __( 'China', 'rank-math-pro' ),
|
||||
'CXR' => __( 'Christmas Island', 'rank-math-pro' ),
|
||||
'COL' => __( 'Colombia', 'rank-math-pro' ),
|
||||
'COM' => __( 'Comoros', 'rank-math-pro' ),
|
||||
'COG' => __( 'Congo - Brazzaville', 'rank-math-pro' ),
|
||||
'COD' => __( 'Congo - Kinshasa', 'rank-math-pro' ),
|
||||
'COK' => __( 'Cook Islands', 'rank-math-pro' ),
|
||||
'CRI' => __( 'Costa Rica', 'rank-math-pro' ),
|
||||
'HRV' => __( 'Croatia', 'rank-math-pro' ),
|
||||
'CUB' => __( 'Cuba', 'rank-math-pro' ),
|
||||
'CUW' => __( 'Curaçao', 'rank-math-pro' ),
|
||||
'CYP' => __( 'Cyprus', 'rank-math-pro' ),
|
||||
'CZE' => __( 'Czechia', 'rank-math-pro' ),
|
||||
'DJI' => __( "Côte d'Ivoire", 'rank-math-pro' ),
|
||||
'DNK' => __( 'Denmark', 'rank-math-pro' ),
|
||||
'DJI' => __( 'Djibouti', 'rank-math-pro' ),
|
||||
'DMA' => __( 'Dominica', 'rank-math-pro' ),
|
||||
'DOM' => __( 'Dominican Republic', 'rank-math-pro' ),
|
||||
'ECU' => __( 'Ecuador', 'rank-math-pro' ),
|
||||
'EGY' => __( 'Egypt', 'rank-math-pro' ),
|
||||
'SLV' => __( 'El Salvador', 'rank-math-pro' ),
|
||||
'GNQ' => __( 'Equatorial Guinea', 'rank-math-pro' ),
|
||||
'ERI' => __( 'Eritrea', 'rank-math-pro' ),
|
||||
'EST' => __( 'Estonia', 'rank-math-pro' ),
|
||||
'ETH' => __( 'Ethiopia', 'rank-math-pro' ),
|
||||
'FLK' => __( 'Falkland Islands (Islas Malvinas)', 'rank-math-pro' ),
|
||||
'FRO' => __( 'Faroe Islands', 'rank-math-pro' ),
|
||||
'FJI' => __( 'Fiji', 'rank-math-pro' ),
|
||||
'FIN' => __( 'Finland', 'rank-math-pro' ),
|
||||
'FRA' => __( 'France', 'rank-math-pro' ),
|
||||
'GUF' => __( 'French Guiana', 'rank-math-pro' ),
|
||||
'PYF' => __( 'French Polynesia', 'rank-math-pro' ),
|
||||
'GAB' => __( 'Gabon', 'rank-math-pro' ),
|
||||
'GMB' => __( 'Gambia', 'rank-math-pro' ),
|
||||
'GEO' => __( 'Georgia', 'rank-math-pro' ),
|
||||
'DEU' => __( 'Germany', 'rank-math-pro' ),
|
||||
'GHA' => __( 'Ghana', 'rank-math-pro' ),
|
||||
'GIB' => __( 'Gibraltar', 'rank-math-pro' ),
|
||||
'GRC' => __( 'Greece', 'rank-math-pro' ),
|
||||
'GRL' => __( 'Greenland', 'rank-math-pro' ),
|
||||
'GRD' => __( 'Grenada', 'rank-math-pro' ),
|
||||
'GLP' => __( 'Guadeloupe', 'rank-math-pro' ),
|
||||
'GUM' => __( 'Guam', 'rank-math-pro' ),
|
||||
'GTM' => __( 'Guatemala', 'rank-math-pro' ),
|
||||
'GGY' => __( 'Guernsey', 'rank-math-pro' ),
|
||||
'GIN' => __( 'Guinea', 'rank-math-pro' ),
|
||||
'GNB' => __( 'Guinea-Bissau', 'rank-math-pro' ),
|
||||
'GUY' => __( 'Guyana', 'rank-math-pro' ),
|
||||
'HTI' => __( 'Haiti', 'rank-math-pro' ),
|
||||
'HND' => __( 'Honduras', 'rank-math-pro' ),
|
||||
'HKG' => __( 'Hong Kong', 'rank-math-pro' ),
|
||||
'HUN' => __( 'Hungary', 'rank-math-pro' ),
|
||||
'ISL' => __( 'Iceland', 'rank-math-pro' ),
|
||||
'IND' => __( 'India', 'rank-math-pro' ),
|
||||
'IDN' => __( 'Indonesia', 'rank-math-pro' ),
|
||||
'IRN' => __( 'Iran', 'rank-math-pro' ),
|
||||
'IRQ' => __( 'Iraq', 'rank-math-pro' ),
|
||||
'IRL' => __( 'Ireland', 'rank-math-pro' ),
|
||||
'IMN' => __( 'Isle of Man', 'rank-math-pro' ),
|
||||
'ISR' => __( 'Israel', 'rank-math-pro' ),
|
||||
'ITA' => __( 'Italy', 'rank-math-pro' ),
|
||||
'JAM' => __( 'Jamaica', 'rank-math-pro' ),
|
||||
'JPN' => __( 'Japan', 'rank-math-pro' ),
|
||||
'JEY' => __( 'Jersey', 'rank-math-pro' ),
|
||||
'JOR' => __( 'Jordan', 'rank-math-pro' ),
|
||||
'KAZ' => __( 'Kazakhstan', 'rank-math-pro' ),
|
||||
'KEN' => __( 'Kenya', 'rank-math-pro' ),
|
||||
'KIR' => __( 'Kiribati', 'rank-math-pro' ),
|
||||
'XKK' => __( 'Kosovo', 'rank-math-pro' ),
|
||||
'KWT' => __( 'Kuwait', 'rank-math-pro' ),
|
||||
'KGZ' => __( 'Kyrgyzstan', 'rank-math-pro' ),
|
||||
'LAO' => __( 'Laos', 'rank-math-pro' ),
|
||||
'LBN' => __( 'Lebanon', 'rank-math-pro' ),
|
||||
'LSO' => __( 'Lesotho', 'rank-math-pro' ),
|
||||
'LBR' => __( 'Liberia', 'rank-math-pro' ),
|
||||
'LBY' => __( 'Libya', 'rank-math-pro' ),
|
||||
'LIE' => __( 'Liechtenstein', 'rank-math-pro' ),
|
||||
'LTU' => __( 'Lithuania', 'rank-math-pro' ),
|
||||
'LUX' => __( 'Luxembourg', 'rank-math-pro' ),
|
||||
'MAC' => __( 'Macau', 'rank-math-pro' ),
|
||||
'MKD' => __( 'Macedonia', 'rank-math-pro' ),
|
||||
'MDG' => __( 'Madagascar', 'rank-math-pro' ),
|
||||
'MWI' => __( 'Malawi', 'rank-math-pro' ),
|
||||
'MYS' => __( 'Malaysia', 'rank-math-pro' ),
|
||||
'MDV' => __( 'Maldives', 'rank-math-pro' ),
|
||||
'MLI' => __( 'Mali', 'rank-math-pro' ),
|
||||
'MLT' => __( 'Malta', 'rank-math-pro' ),
|
||||
'MHL' => __( 'Marshall Islands', 'rank-math-pro' ),
|
||||
'MTQ' => __( 'Martinique', 'rank-math-pro' ),
|
||||
'MRT' => __( 'Mauritania', 'rank-math-pro' ),
|
||||
'MUS' => __( 'Mauritius', 'rank-math-pro' ),
|
||||
'MYT' => __( 'Mayotte', 'rank-math-pro' ),
|
||||
'MEX' => __( 'Mexico', 'rank-math-pro' ),
|
||||
'FSM' => __( 'Micronesia', 'rank-math-pro' ),
|
||||
'MDA' => __( 'Moldova', 'rank-math-pro' ),
|
||||
'MCO' => __( 'Monaco', 'rank-math-pro' ),
|
||||
'MNG' => __( 'Mongolia', 'rank-math-pro' ),
|
||||
'MNE' => __( 'Montenegro', 'rank-math-pro' ),
|
||||
'MSR' => __( 'Montserrat', 'rank-math-pro' ),
|
||||
'MAR' => __( 'Morocco', 'rank-math-pro' ),
|
||||
'MOZ' => __( 'Mozambique', 'rank-math-pro' ),
|
||||
'MMR' => __( 'Myanmar (Burma)', 'rank-math-pro' ),
|
||||
'NAM' => __( 'Namibia', 'rank-math-pro' ),
|
||||
'NRU' => __( 'Nauru', 'rank-math-pro' ),
|
||||
'NPL' => __( 'Nepal', 'rank-math-pro' ),
|
||||
'NLD' => __( 'Netherlands', 'rank-math-pro' ),
|
||||
'NCL' => __( 'New Caledonia', 'rank-math-pro' ),
|
||||
'NZL' => __( 'New Zealand', 'rank-math-pro' ),
|
||||
'NIC' => __( 'Nicaragua', 'rank-math-pro' ),
|
||||
'NER' => __( 'Niger', 'rank-math-pro' ),
|
||||
'NGA' => __( 'Nigeria', 'rank-math-pro' ),
|
||||
'NIU' => __( 'Niue', 'rank-math-pro' ),
|
||||
'NFK' => __( 'Norfolk Island', 'rank-math-pro' ),
|
||||
'PRK' => __( 'North Korea', 'rank-math-pro' ),
|
||||
'MNP' => __( 'Northern Mariana Islands', 'rank-math-pro' ),
|
||||
'NOR' => __( 'Norway', 'rank-math-pro' ),
|
||||
'OMN' => __( 'Oman', 'rank-math-pro' ),
|
||||
'PAK' => __( 'Pakistan', 'rank-math-pro' ),
|
||||
'PLW' => __( 'Palau', 'rank-math-pro' ),
|
||||
'PSE' => __( 'Palestine', 'rank-math-pro' ),
|
||||
'PAN' => __( 'Panama', 'rank-math-pro' ),
|
||||
'PNG' => __( 'Papua New Guinea', 'rank-math-pro' ),
|
||||
'PRY' => __( 'Paraguay', 'rank-math-pro' ),
|
||||
'PER' => __( 'Peru', 'rank-math-pro' ),
|
||||
'PHL' => __( 'Philippines', 'rank-math-pro' ),
|
||||
'POL' => __( 'Poland', 'rank-math-pro' ),
|
||||
'PRT' => __( 'Portugal', 'rank-math-pro' ),
|
||||
'PRI' => __( 'Puerto Rico', 'rank-math-pro' ),
|
||||
'QAT' => __( 'Qatar', 'rank-math-pro' ),
|
||||
'ROU' => __( 'Romania', 'rank-math-pro' ),
|
||||
'RUS' => __( 'Russia', 'rank-math-pro' ),
|
||||
'RWA' => __( 'Rwanda', 'rank-math-pro' ),
|
||||
'REU' => __( 'Réunion', 'rank-math-pro' ),
|
||||
'WSM' => __( 'Samoa', 'rank-math-pro' ),
|
||||
'SMR' => __( 'San Marino', 'rank-math-pro' ),
|
||||
'SAU' => __( 'Saudi Arabia', 'rank-math-pro' ),
|
||||
'SEN' => __( 'Senegal', 'rank-math-pro' ),
|
||||
'SRB' => __( 'Serbia', 'rank-math-pro' ),
|
||||
'SYC' => __( 'Seychelles', 'rank-math-pro' ),
|
||||
'SLE' => __( 'Sierra Leone', 'rank-math-pro' ),
|
||||
'SGP' => __( 'Singapore', 'rank-math-pro' ),
|
||||
'SXM' => __( 'Sint Maarten', 'rank-math-pro' ),
|
||||
'SVK' => __( 'Slovakia', 'rank-math-pro' ),
|
||||
'SVN' => __( 'Slovenia', 'rank-math-pro' ),
|
||||
'SLB' => __( 'Solomon Islands', 'rank-math-pro' ),
|
||||
'SOM' => __( 'Somalia', 'rank-math-pro' ),
|
||||
'ZAF' => __( 'South Africa', 'rank-math-pro' ),
|
||||
'KOR' => __( 'South Korea', 'rank-math-pro' ),
|
||||
'SSD' => __( 'South Sudan', 'rank-math-pro' ),
|
||||
'ESP' => __( 'Spain', 'rank-math-pro' ),
|
||||
'LKA' => __( 'Sri Lanka', 'rank-math-pro' ),
|
||||
'SHN' => __( 'St. Helena', 'rank-math-pro' ),
|
||||
'KNA' => __( 'St. Kitts & Nevis', 'rank-math-pro' ),
|
||||
'LCA' => __( 'St. Lucia', 'rank-math-pro' ),
|
||||
'MAF' => __( 'St. Martin', 'rank-math-pro' ),
|
||||
'SPM' => __( 'St. Pierre & Miquelon', 'rank-math-pro' ),
|
||||
'VCT' => __( 'St. Vincent & Grenadines', 'rank-math-pro' ),
|
||||
'SDN' => __( 'Sudan', 'rank-math-pro' ),
|
||||
'SUR' => __( 'Suriname', 'rank-math-pro' ),
|
||||
'SJM' => __( 'Svalbard & Jan Mayen', 'rank-math-pro' ),
|
||||
'SWZ' => __( 'Swaziland', 'rank-math-pro' ),
|
||||
'SWE' => __( 'Sweden', 'rank-math-pro' ),
|
||||
'CHE' => __( 'Switzerland', 'rank-math-pro' ),
|
||||
'SYR' => __( 'Syria', 'rank-math-pro' ),
|
||||
'STP' => __( 'São Tomé & Príncipe', 'rank-math-pro' ),
|
||||
'TWN' => __( 'Taiwan', 'rank-math-pro' ),
|
||||
'TJK' => __( 'Tajikistan', 'rank-math-pro' ),
|
||||
'TZA' => __( 'Tanzania', 'rank-math-pro' ),
|
||||
'THA' => __( 'Thailand', 'rank-math-pro' ),
|
||||
'TLS' => __( 'Timor-Leste', 'rank-math-pro' ),
|
||||
'TGO' => __( 'Togo', 'rank-math-pro' ),
|
||||
'TON' => __( 'Tonga', 'rank-math-pro' ),
|
||||
'TTO' => __( 'Trinidad & Tobago', 'rank-math-pro' ),
|
||||
'TUN' => __( 'Tunisia', 'rank-math-pro' ),
|
||||
'TUR' => __( 'Turkey', 'rank-math-pro' ),
|
||||
'TKM' => __( 'Turkmenistan', 'rank-math-pro' ),
|
||||
'TCA' => __( 'Turks & Caicos Islands', 'rank-math-pro' ),
|
||||
'TUV' => __( 'Tuvalu', 'rank-math-pro' ),
|
||||
'VIR' => __( 'U.S. Virgin Islands', 'rank-math-pro' ),
|
||||
'UGA' => __( 'Uganda', 'rank-math-pro' ),
|
||||
'UKR' => __( 'Ukraine', 'rank-math-pro' ),
|
||||
'ARE' => __( 'United Arab Emirates', 'rank-math-pro' ),
|
||||
'GBR' => __( 'United Kingdom', 'rank-math-pro' ),
|
||||
'USA' => __( 'United States', 'rank-math-pro' ),
|
||||
'URY' => __( 'Uruguay', 'rank-math-pro' ),
|
||||
'UZB' => __( 'Uzbekistan', 'rank-math-pro' ),
|
||||
'VUT' => __( 'Vanuatu', 'rank-math-pro' ),
|
||||
'VEN' => __( 'Venezuela', 'rank-math-pro' ),
|
||||
'VNM' => __( 'Vietnam', 'rank-math-pro' ),
|
||||
'WLF' => __( 'Wallis & Futuna', 'rank-math-pro' ),
|
||||
'ESH' => __( 'Western Sahara', 'rank-math-pro' ),
|
||||
'YEM' => __( 'Yemen', 'rank-math-pro' ),
|
||||
'ZMB' => __( 'Zambia', 'rank-math-pro' ),
|
||||
'ZWE' => __( 'Zimbabwe', 'rank-math-pro' ),
|
||||
'ZZZ' => __( 'Unknown Region', 'rank-math-pro' ),
|
||||
];
|
||||
}
|
||||
}
|
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
/**
|
||||
* The admin-specific functionality of the plugin.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @package RankMath
|
||||
* @subpackage RankMathPro\Admin
|
||||
* @author MyThemeShop <admin@mythemeshop.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Admin;
|
||||
|
||||
use RankMathPro\Updates;
|
||||
use RankMathPro\Status\System_Status;
|
||||
use RankMath\Helper;
|
||||
use RankMath\Traits\Hooker;
|
||||
use MyThemeShop\Helpers\Param;
|
||||
use RankMathPro\Google\Adsense;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Admin class.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class Admin {
|
||||
|
||||
use Hooker;
|
||||
|
||||
/**
|
||||
* Stores object instances.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $components = [];
|
||||
|
||||
/**
|
||||
* Register hooks.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->action( 'init', 'init_components' );
|
||||
add_filter( 'rank_math/analytics/classic/pro_notice', '__return_empty_string' );
|
||||
$this->filter( 'rank_math/settings/sitemap', 'special_seprator' );
|
||||
$this->action( 'admin_enqueue_scripts', 'enqueue' );
|
||||
$this->filter( 'wp_helpers_notifications_render', 'prevent_pro_notice', 10, 3 );
|
||||
|
||||
new Updates();
|
||||
new System_Status();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the required components.
|
||||
*/
|
||||
public function init_components() {
|
||||
$components = [
|
||||
'bulk_actions' => 'RankMathPro\\Admin\\Bulk_Actions',
|
||||
'post_filters' => 'RankMathPro\\Admin\\Post_Filters',
|
||||
'media_filters' => 'RankMathPro\\Admin\\Media_Filters',
|
||||
'quick_edit' => 'RankMathPro\\Admin\\Quick_Edit',
|
||||
'trends_tool' => 'RankMathPro\\Admin\\Trends_Tool',
|
||||
'setup_wizard' => 'RankMathPro\\Admin\\Setup_Wizard',
|
||||
'links' => 'RankMathPro\\Admin\\Links',
|
||||
'misc' => 'RankMathPro\\Admin\\Misc',
|
||||
'csv_import' => 'RankMathPro\\Admin\\CSV_Import_Export\\CSV_Import_Export',
|
||||
];
|
||||
|
||||
if ( Helper::is_amp_active() ) {
|
||||
$components['amp'] = 'RankMathPro\\Admin\\Amp';
|
||||
}
|
||||
|
||||
$components = apply_filters( 'rank_math/admin/pro_components', $components );
|
||||
foreach ( $components as $name => $component ) {
|
||||
$this->components[ $name ] = new $component();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Special seprator into sitemap option panel
|
||||
*
|
||||
* @param array $tabs Hold tabs for optional panel.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function special_seprator( $tabs ) {
|
||||
if ( Helper::is_module_active( 'news-sitemap' ) || Helper::is_module_active( 'video-sitemap' ) || Helper::is_module_active( 'local-seo' ) ) {
|
||||
$tabs['special'] = [
|
||||
'title' => esc_html__( 'Special Sitemaps:', 'rank-math-pro' ),
|
||||
'type' => 'seprator',
|
||||
];
|
||||
}
|
||||
|
||||
return $tabs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load setup wizard.
|
||||
*/
|
||||
private function load_setup_wizard() {
|
||||
if ( Helper::is_wizard() ) {
|
||||
new Setup_Wizard();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enqueue assets.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function enqueue() {
|
||||
if ( Param::get( 'page' ) !== 'rank-math-options-general' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
wp_enqueue_style(
|
||||
'rank-math-pro-general-options',
|
||||
RANK_MATH_PRO_URL . 'assets/admin/css/general-options.css',
|
||||
null,
|
||||
rank_math_pro()->version
|
||||
);
|
||||
|
||||
wp_enqueue_script( 'rank-math-pro-general-options', RANK_MATH_PRO_URL . 'assets/admin/js/general-options.js', [ 'wp-hooks' ], rank_math_pro()->version );
|
||||
|
||||
Helper::add_json( 'isAdsenseConnected', Adsense::is_adsense_connected() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that our "Upgrade to Pro" admin notice is not showing when the
|
||||
* Pro version is active.
|
||||
*
|
||||
* @param string $output Notice HTML output.
|
||||
* @param string $message Notice message text.
|
||||
* @param array $options Notice options.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function prevent_pro_notice( $output, $message, $options ) {
|
||||
if ( 'rank_math_pro_notice' !== $options['id'] ) {
|
||||
return $output;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
/**
|
||||
* Pro AMP support.
|
||||
*
|
||||
* @since 1.0
|
||||
* @package RankMathPro
|
||||
* @subpackage RankMathPro\Admin
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Admin;
|
||||
|
||||
use RankMath\Helper;
|
||||
use RankMath\Traits\Hooker;
|
||||
use RankMath\Redirections\DB;
|
||||
use RankMath\Redirections\Redirection;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Amp tool class.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class Amp {
|
||||
|
||||
use Hooker;
|
||||
|
||||
/**
|
||||
* Register hooks.
|
||||
*/
|
||||
public function __construct() {
|
||||
if ( Helper::get_settings( 'general.redirections_post_redirect' ) ) {
|
||||
$this->action( 'rank_math/redirection/post_updated', 'add_amp_redirect', 20 );
|
||||
$this->action( 'rank_math/redirection/term_updated', 'add_amp_redirect', 20 );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Add /amp redirection based on the original redirection.
|
||||
*
|
||||
* @param int $redirection_id Redirection ID.
|
||||
* @return void
|
||||
*/
|
||||
public function add_amp_redirect( $redirection_id ) {
|
||||
$db_redirection = DB::get_redirection_by_id( $redirection_id );
|
||||
|
||||
$url_to = trailingslashit( $db_redirection['url_to'] ) . 'amp/';
|
||||
$redirection = Redirection::from(
|
||||
[
|
||||
'url_to' => $url_to,
|
||||
'header_code' => $db_redirection['header_code'],
|
||||
]
|
||||
);
|
||||
|
||||
$redirection->set_nocache( true );
|
||||
$redirection->add_source( trailingslashit( $db_redirection['sources'][0]['pattern'] ) . 'amp/', 'exact' );
|
||||
$redirection->add_destination( $url_to );
|
||||
$redirection->save();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,350 @@
|
||||
<?php
|
||||
/**
|
||||
* The RankMath API.
|
||||
*
|
||||
* @since 1.5.0
|
||||
* @package RankMathPro
|
||||
* @subpackage RankMathPro\Admin
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Admin;
|
||||
|
||||
use RankMath\Admin\Admin_Helper;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Api class.
|
||||
*/
|
||||
class Api {
|
||||
|
||||
/**
|
||||
* Rank Math SEO Checkup API.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $api_url = 'https://rankmath.com/wp-json/rankmath/v1/';
|
||||
|
||||
/**
|
||||
* Was the last request successful.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $is_success = false;
|
||||
|
||||
/**
|
||||
* Last error.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $last_error = '';
|
||||
|
||||
/**
|
||||
* Last response.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $last_response = [];
|
||||
|
||||
/**
|
||||
* Last response header code.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $last_code = 0;
|
||||
|
||||
/**
|
||||
* User agent.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $user_agent = '';
|
||||
|
||||
/**
|
||||
* Is request blocking (do we wait for response)?
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $is_blocking = true;
|
||||
|
||||
/**
|
||||
* Main instance
|
||||
*
|
||||
* Ensure only one instance is loaded or can be loaded.
|
||||
*
|
||||
* @return Api
|
||||
*/
|
||||
public static function get() {
|
||||
static $instance;
|
||||
|
||||
if ( is_null( $instance ) && ! ( $instance instanceof Api ) ) {
|
||||
$instance = new Api();
|
||||
$instance->is_blocking = true;
|
||||
$instance->user_agent = 'RankMath/' . md5( esc_url( home_url( '/' ) ) );
|
||||
}
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Was the last request successful?
|
||||
*
|
||||
* @return bool True for success, false for failure
|
||||
*/
|
||||
public function is_success() {
|
||||
return $this->is_success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last error returned by either the network transport, or by the API.
|
||||
* If something didn't work, this should contain the string describing the problem.
|
||||
*
|
||||
* @return array|false describing the error
|
||||
*/
|
||||
public function get_error() {
|
||||
return $this->last_error ? $this->last_error : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array containing the HTTP headers and the body of the API response.
|
||||
*
|
||||
* @return array Assoc array with keys 'headers' and 'body'
|
||||
*/
|
||||
public function get_response() {
|
||||
return $this->last_response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an HTTP GET request - for retrieving data.
|
||||
*
|
||||
* @param string $url URL to do request.
|
||||
* @param array $args Assoc array of arguments (usually your data).
|
||||
* @param int $timeout Timeout limit for request in seconds.
|
||||
*
|
||||
* @return array|false Assoc array of API response, decoded from JSON.
|
||||
*/
|
||||
public function http_get( $url, $args = [], $timeout = 10 ) {
|
||||
return $this->make_request( 'GET', $url, $args, $timeout );
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an HTTP POST request - for creating and updating items.
|
||||
*
|
||||
* @param string $url URL to do request.
|
||||
* @param array $args Assoc array of arguments (usually your data).
|
||||
* @param int $timeout Timeout limit for request in seconds.
|
||||
*
|
||||
* @return array|false Assoc array of API response, decoded from JSON.
|
||||
*/
|
||||
public function http_post( $url, $args = [], $timeout = 10 ) {
|
||||
return $this->make_request( 'POST', $url, $args, $timeout );
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an HTTP PUT request - for creating new items.
|
||||
*
|
||||
* @param string $url URL to do request.
|
||||
* @param array $args Assoc array of arguments (usually your data).
|
||||
* @param int $timeout Timeout limit for request in seconds.
|
||||
*
|
||||
* @return array|false Assoc array of API response, decoded from JSON.
|
||||
*/
|
||||
public function http_put( $url, $args = [], $timeout = 10 ) {
|
||||
return $this->make_request( 'PUT', $url, $args, $timeout );
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an HTTP DELETE request - for deleting data.
|
||||
*
|
||||
* @param string $url URL to do request.
|
||||
* @param array $args Assoc array of arguments (usually your data).
|
||||
* @param int $timeout Timeout limit for request in seconds.
|
||||
*
|
||||
* @return array|false Assoc array of API response, decoded from JSON.
|
||||
*/
|
||||
public function http_delete( $url, $args = [], $timeout = 10 ) {
|
||||
return $this->make_request( 'DELETE', $url, $args, $timeout );
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the underlying HTTP request. Not very exciting.
|
||||
*
|
||||
* @param string $http_verb The HTTP verb to use: get, post, put, patch, delete.
|
||||
* @param string $url URL to do request.
|
||||
* @param array $args Assoc array of parameters to be passed.
|
||||
* @param int $timeout Timeout limit for request in seconds.
|
||||
*
|
||||
* @return array|false Assoc array of decoded result.
|
||||
*/
|
||||
protected function make_request( $http_verb, $url, $args = [], $timeout = 10 ) {
|
||||
$params = [
|
||||
'timeout' => $timeout,
|
||||
'method' => $http_verb,
|
||||
'user-agent' => $this->user_agent,
|
||||
'blocking' => $this->is_blocking,
|
||||
];
|
||||
|
||||
if ( ! empty( $args ) && is_array( $args ) ) {
|
||||
$params['body'] = $args;
|
||||
}
|
||||
|
||||
$this->reset();
|
||||
$response = wp_remote_request( $this->api_url . $url, $params );
|
||||
$this->determine_success( $response );
|
||||
|
||||
return $this->format_response( $response );
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode the response and format any error messages for debugging
|
||||
*
|
||||
* @param array $response The response from the curl request.
|
||||
*
|
||||
* @return array|false The JSON decoded into an array
|
||||
*/
|
||||
protected function format_response( $response ) {
|
||||
$this->last_response = $response;
|
||||
|
||||
if ( is_wp_error( $response ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! empty( $response['body'] ) ) {
|
||||
return json_decode( $response['body'], true );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the response was successful or a failure. If it failed, store the error.
|
||||
*
|
||||
* @param array $response The response from the curl request.
|
||||
*/
|
||||
protected function determine_success( $response ) {
|
||||
if ( is_wp_error( $response ) ) {
|
||||
$this->last_error = 'WP_Error: ' . $response->get_error_message();
|
||||
return;
|
||||
}
|
||||
|
||||
$this->last_code = wp_remote_retrieve_response_code( $response );
|
||||
if ( in_array( $this->last_code, [ 200, 204 ], true ) ) {
|
||||
$this->is_success = true;
|
||||
return;
|
||||
}
|
||||
|
||||
$this->last_error = 'Unknown error, call getLastResponse() to find out what happened.';
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset request.
|
||||
*/
|
||||
protected function reset() {
|
||||
$this->last_code = 0;
|
||||
$this->last_error = '';
|
||||
$this->is_success = false;
|
||||
$this->is_blocking = true;
|
||||
$this->last_response = [
|
||||
'body' => null,
|
||||
'headers' => null,
|
||||
];
|
||||
}
|
||||
|
||||
public function get_settings() {
|
||||
$registered = Admin_Helper::get_registration_data();
|
||||
if ( ! $registered || empty( $registered['username'] ) || empty( $registered['api_key'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$response = $this->http_get(
|
||||
'siteSettings',
|
||||
[
|
||||
'username' => $registered['username'],
|
||||
'api_key' => $registered['api_key'],
|
||||
'site_url' => esc_url( home_url() ),
|
||||
]
|
||||
);
|
||||
|
||||
if ( ! $this->is_success() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$registered['plan'] = $response['plan'];
|
||||
Admin_Helper::get_registration_data( $registered );
|
||||
|
||||
update_option( 'rank_math_keyword_quota', $response['keywords'] );
|
||||
cmb2_update_option( 'rank-math-options-general', 'sync_global_setting', $response['settings']['analytics'] );
|
||||
}
|
||||
|
||||
public function sync_setting( $analytics ) {
|
||||
$registered = Admin_Helper::get_registration_data();
|
||||
if ( ! $registered || empty( $registered['username'] ) || empty( $registered['api_key'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->is_blocking = false;
|
||||
$response = $this->http_post(
|
||||
'siteSettings',
|
||||
[
|
||||
'username' => $registered['username'],
|
||||
'api_key' => $registered['api_key'],
|
||||
'site_url' => esc_url( home_url() ),
|
||||
'analytics' => $analytics,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove registration data and disconnect from RankMath.com.
|
||||
*
|
||||
* @param string $username Username.
|
||||
* @param string $api_key Api key.
|
||||
*/
|
||||
public function deactivate_site( $username, $api_key ) {
|
||||
$this->is_blocking = false;
|
||||
$this->http_post(
|
||||
'deactivateSite',
|
||||
[
|
||||
'username' => $username,
|
||||
'api_key' => $api_key,
|
||||
'site_url' => esc_url( home_url() ),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send analytics summary to RankMath.com.
|
||||
*/
|
||||
public function send_summary( $summary ) {
|
||||
$this->is_blocking = false;
|
||||
$this->http_post( 'siteStats', $summary );
|
||||
}
|
||||
|
||||
/**
|
||||
* Send keywords count data to RankMath.com.
|
||||
*
|
||||
* @param string $username Username.
|
||||
* @param string $api_key Api key.
|
||||
* @param int $count Total keywords count.
|
||||
*
|
||||
* @return array|false The respnose of API.
|
||||
*/
|
||||
public function keywords_info( $username, $api_key, $count ) {
|
||||
$response = $this->http_post(
|
||||
'keywordsInfo',
|
||||
[
|
||||
'username' => $username,
|
||||
'apiKey' => $api_key,
|
||||
'siteUrl' => esc_url( home_url() ),
|
||||
'count' => $count,
|
||||
]
|
||||
);
|
||||
|
||||
if ( ! $this->is_success() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
@@ -0,0 +1,414 @@
|
||||
<?php
|
||||
/**
|
||||
* Bulk actions for the manage posts screen.
|
||||
*
|
||||
* @since 1.0
|
||||
* @package RankMathPro
|
||||
* @subpackage RankMathPro\Admin
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Admin;
|
||||
|
||||
use RankMath\Helper;
|
||||
use RankMath\Traits\Hooker;
|
||||
use MyThemeShop\Helpers\Param;
|
||||
use RankMath\Admin\Admin_Helper;
|
||||
use RankMathPro\Admin\Admin_Helper as ProAdminHelper;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Bulk actions class.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class Bulk_Actions {
|
||||
|
||||
use Hooker;
|
||||
|
||||
/**
|
||||
* Register hooks.
|
||||
*/
|
||||
public function __construct() {
|
||||
$post_types = Helper::get_accessible_post_types();
|
||||
foreach ( $post_types as $post_type ) {
|
||||
$this->filter( "bulk_actions-edit-{$post_type}", 'post_bulk_actions' );
|
||||
$this->filter( "handle_bulk_actions-edit-{$post_type}", 'handle_post_bulk_actions', 10, 3 );
|
||||
}
|
||||
|
||||
$taxonomies = Helper::get_accessible_taxonomies();
|
||||
unset( $taxonomies['post_format'] );
|
||||
$taxonomies = wp_list_pluck( $taxonomies, 'label', 'name' );
|
||||
foreach ( $taxonomies as $taxonomy => $label ) {
|
||||
$this->filter( "bulk_actions-edit-{$taxonomy}", 'tax_bulk_actions' );
|
||||
$this->filter( "handle_bulk_actions-edit-{$taxonomy}", 'handle_tax_bulk_actions', 10, 3 );
|
||||
}
|
||||
|
||||
$this->action( 'save_post', 'save_post_primary_term' );
|
||||
$this->action( 'admin_enqueue_scripts', 'enqueue' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add bulk actions for applicable posts, pages, CPTs.
|
||||
*
|
||||
* @param array $actions Actions.
|
||||
* @return array New actions.
|
||||
*/
|
||||
public function post_bulk_actions( $actions ) {
|
||||
$new_actions = [ 'rank_math_options' => __( '↓ Rank Math', 'rank-math-pro' ) ];
|
||||
|
||||
if ( Helper::has_cap( 'onpage_advanced' ) ) {
|
||||
$new_actions['rank_math_bulk_robots_noindex'] = __( 'Set to noindex', 'rank-math-pro' );
|
||||
$new_actions['rank_math_bulk_robots_index'] = __( 'Set to index', 'rank-math-pro' );
|
||||
$new_actions['rank_math_bulk_robots_nofollow'] = __( 'Set to nofollow', 'rank-math-pro' );
|
||||
$new_actions['rank_math_bulk_robots_follow'] = __( 'Set to follow', 'rank-math-pro' );
|
||||
$new_actions['rank_math_bulk_remove_canonical'] = __( 'Remove custom canonical URL', 'rank-math-pro' );
|
||||
|
||||
if ( Helper::is_module_active( 'redirections' ) && Helper::has_cap( 'redirections' ) ) {
|
||||
$new_actions['rank_math_bulk_redirect'] = __( 'Redirect', 'rank-math-pro' );
|
||||
$new_actions['rank_math_bulk_stop_redirect'] = __( 'Remove redirection', 'rank-math-pro' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( Helper::is_module_active( 'rich-snippet' ) && Helper::has_cap( 'onpage_snippet' ) ) {
|
||||
$new_actions['rank_math_bulk_schema_none'] = __( 'Set Schema: None', 'rank-math-pro' );
|
||||
$post_type = Param::get( 'post_type', get_post_type() );
|
||||
$post_type_default = Helper::get_settings( 'titles.pt_' . $post_type . '_default_rich_snippet' );
|
||||
|
||||
if ( $post_type_default ) {
|
||||
// Translators: placeholder is the default Schema type setting.
|
||||
$new_actions['rank_math_bulk_schema_default'] = sprintf( __( 'Set Schema: Default (%s)', 'rank-math-pro' ), $post_type_default );
|
||||
}
|
||||
}
|
||||
|
||||
if ( is_array( $actions ) && count( $new_actions ) > 1 ) {
|
||||
return array_merge( $actions, $new_actions );
|
||||
}
|
||||
|
||||
return $actions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add bulk actions for applicable taxonomies.
|
||||
*
|
||||
* @param array $actions Actions.
|
||||
* @return array New actions.
|
||||
*/
|
||||
public function tax_bulk_actions( $actions ) {
|
||||
if ( ! Helper::has_cap( 'onpage_advanced' ) ) {
|
||||
return $actions;
|
||||
}
|
||||
|
||||
$actions['rank_math_options'] = __( '↓ Rank Math', 'rank-math-pro' );
|
||||
$actions['rank_math_bulk_robots_noindex'] = __( 'Set to noindex', 'rank-math-pro' );
|
||||
$actions['rank_math_bulk_robots_index'] = __( 'Set to index', 'rank-math-pro' );
|
||||
$actions['rank_math_bulk_robots_nofollow'] = __( 'Set to nofollow', 'rank-math-pro' );
|
||||
$actions['rank_math_bulk_robots_follow'] = __( 'Set to follow', 'rank-math-pro' );
|
||||
|
||||
if ( Helper::is_module_active( 'redirections' ) && Helper::has_cap( 'redirections' ) ) {
|
||||
$actions['rank_math_bulk_redirect'] = __( 'Redirect', 'rank-math-pro' );
|
||||
$actions['rank_math_bulk_stop_redirect'] = __( 'Remove redirection', 'rank-math-pro' );
|
||||
}
|
||||
|
||||
return $actions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle bulk actions for applicable posts, pages, CPTs.
|
||||
*
|
||||
* @param string $redirect Redirect URL.
|
||||
* @param string $doaction Performed action.
|
||||
* @param array $object_ids Post IDs.
|
||||
*
|
||||
* @return string New redirect URL.
|
||||
*/
|
||||
public function handle_post_bulk_actions( $redirect, $doaction, $object_ids ) {
|
||||
$redirect = remove_query_arg(
|
||||
[
|
||||
'rank_math_bulk_robots_noindex',
|
||||
'rank_math_bulk_robots_index',
|
||||
'rank_math_bulk_robots_nofollow',
|
||||
'rank_math_bulk_robots_follow',
|
||||
'rank_math_bulk_stop_redirect',
|
||||
'rank_math_bulk_schema_none',
|
||||
'rank_math_bulk_schema_default',
|
||||
'rank_math_bulk_remove_canonical',
|
||||
],
|
||||
$redirect
|
||||
);
|
||||
|
||||
$edited = 0;
|
||||
$message = '';
|
||||
|
||||
$post_type_object = false;
|
||||
|
||||
switch ( $doaction ) {
|
||||
case 'rank_math_bulk_robots_noindex':
|
||||
case 'rank_math_bulk_robots_index':
|
||||
case 'rank_math_bulk_robots_nofollow':
|
||||
case 'rank_math_bulk_robots_follow':
|
||||
foreach ( $object_ids as $post_id ) {
|
||||
if ( ! $post_type_object ) {
|
||||
$post_type_object = get_post_type_object( get_post_type( $post_id ) );
|
||||
}
|
||||
$action = str_replace( 'rank_math_bulk_robots_', '', $doaction );
|
||||
$robots = (array) get_post_meta( $post_id, 'rank_math_robots', true );
|
||||
$robots = array_filter( $robots );
|
||||
|
||||
// Remove "opposite" robots meta.
|
||||
$opposite = 'no' . $action;
|
||||
if ( substr( $action, 0, 2 ) === 'no' ) {
|
||||
$opposite = substr( $action, 2 );
|
||||
}
|
||||
if ( ( $key = array_search( $opposite, $robots ) ) !== false ) { // @codingStandardsIgnoreLine
|
||||
unset( $robots[ $key ] );
|
||||
}
|
||||
|
||||
// Add new robots meta.
|
||||
if ( ! in_array( $action, $robots, true ) ) {
|
||||
$robots[] = $action;
|
||||
}
|
||||
$robots = array_unique( $robots );
|
||||
|
||||
update_post_meta( $post_id, 'rank_math_robots', $robots );
|
||||
$edited++;
|
||||
|
||||
if ( 'index' === $action || 'noindex' === $action ) {
|
||||
$this->do_action( 'sitemap/invalidate_object_type', 'post', $post_id );
|
||||
}
|
||||
}
|
||||
// Translators: 1 The number of posts edited. 2 The post type name.
|
||||
$message = sprintf( __( 'Robots meta edited for %1$d %2$s.', 'rank-math-pro' ), $edited, ( $edited > 1 ? $post_type_object->labels->name : $post_type_object->labels->singular_name ) );
|
||||
break;
|
||||
|
||||
case 'rank_math_bulk_redirect':
|
||||
$redirect = Helper::get_admin_url( 'redirections' );
|
||||
$i = 0;
|
||||
foreach ( $object_ids as $post_id ) {
|
||||
$post_url = get_permalink( $post_id );
|
||||
$redirect = add_query_arg( "urls[{$i}]", $post_url, $redirect );
|
||||
$i++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'rank_math_bulk_stop_redirect':
|
||||
foreach ( $object_ids as $post_id ) {
|
||||
$redirection = \RankMath\Redirections\Cache::get_by_object_id( $post_id, 'post' );
|
||||
if ( $redirection ) {
|
||||
\RankMath\Redirections\DB::change_status( $redirection->redirection_id, 'trashed' );
|
||||
$edited++;
|
||||
}
|
||||
}
|
||||
// Translators: placeholder is the number of redirections deleted.
|
||||
$message = sprintf( _n( '%d redirection moved to Trash.', '%d redirections moved to Trash.', $edited, 'rank-math-pro' ), $edited );
|
||||
break;
|
||||
|
||||
case 'rank_math_bulk_schema_none':
|
||||
foreach ( $object_ids as $post_id ) {
|
||||
if ( ! $post_type_object ) {
|
||||
$post_type_object = get_post_type_object( get_post_type( $post_id ) );
|
||||
}
|
||||
update_post_meta( $post_id, 'rank_math_rich_snippet', 'off' );
|
||||
$this->delete_schema( $post_id );
|
||||
|
||||
$edited++;
|
||||
}
|
||||
// Translators: 1 The number of posts edited. 2 The post type name.
|
||||
$message = sprintf( __( 'Schema edited for %1$d %2$s.', 'rank-math-pro' ), $edited, ( $edited > 1 ? $post_type_object->labels->name : $post_type_object->labels->singular_name ) );
|
||||
break;
|
||||
|
||||
case 'rank_math_bulk_schema_default':
|
||||
foreach ( $object_ids as $post_id ) {
|
||||
if ( ! $post_type_object ) {
|
||||
$post_type_object = get_post_type_object( get_post_type( $post_id ) );
|
||||
}
|
||||
delete_post_meta( $post_id, 'rank_math_rich_snippet' );
|
||||
$this->delete_schema( $post_id );
|
||||
|
||||
$edited++;
|
||||
}
|
||||
// Translators: 1 The number of posts edited. 2 The post type name.
|
||||
$message = sprintf( __( 'Schema edited for %1$d %2$s.', 'rank-math-pro' ), $edited, ( $edited > 1 ? $post_type_object->labels->name : $post_type_object->labels->singular_name ) );
|
||||
break;
|
||||
|
||||
case 'rank_math_bulk_remove_canonical':
|
||||
foreach ( $object_ids as $post_id ) {
|
||||
if ( ! $post_type_object ) {
|
||||
$post_type_object = get_post_type_object( get_post_type( $post_id ) );
|
||||
}
|
||||
|
||||
if ( get_post_meta( $post_id, 'rank_math_canonical_url', true ) ) {
|
||||
delete_post_meta( $post_id, 'rank_math_canonical_url' );
|
||||
$edited++;
|
||||
}
|
||||
}
|
||||
// Translators: 1 The number of posts edited. 2 The post type name.
|
||||
$message = sprintf( __( 'Custom Canonical URL removed from %1$d %2$s.', 'rank-math-pro' ), $edited, ( $edited > 1 ? $post_type_object->labels->name : $post_type_object->labels->singular_name ) );
|
||||
break;
|
||||
}
|
||||
|
||||
if ( $message ) {
|
||||
Helper::add_notification( $message );
|
||||
}
|
||||
|
||||
return $redirect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete ALL existing Schema data for a post.
|
||||
*
|
||||
* @param int $post_id Post id.
|
||||
*/
|
||||
public function delete_schema( $post_id ) {
|
||||
global $wpdb;
|
||||
|
||||
$where = $wpdb->prepare( 'WHERE post_id = %d AND meta_key LIKE %s', $post_id, $wpdb->esc_like( 'rank_math_schema_' ) . '%' );
|
||||
$wpdb->query( "DELETE FROM {$wpdb->postmeta} {$where}" ); // phpcs:ignore
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle bulk actions for applicable posts, pages, CPTs.
|
||||
*
|
||||
* @param string $redirect Redirect URL.
|
||||
* @param string $doaction Performed action.
|
||||
* @param array $object_ids Post IDs.
|
||||
*
|
||||
* @return string New redirect URL.
|
||||
*/
|
||||
public function handle_tax_bulk_actions( $redirect, $doaction, $object_ids ) {
|
||||
$redirect = remove_query_arg(
|
||||
[
|
||||
'rank_math_bulk_robots_noindex',
|
||||
'rank_math_bulk_robots_index',
|
||||
'rank_math_bulk_robots_nofollow',
|
||||
'rank_math_bulk_robots_follow',
|
||||
'rank_math_bulk_stop_redirect',
|
||||
'rank_math_bulk_schema_none',
|
||||
'rank_math_bulk_schema_default',
|
||||
'rank_math_bulk_remove_canonical',
|
||||
],
|
||||
$redirect
|
||||
);
|
||||
|
||||
$edited = 0;
|
||||
$message = '';
|
||||
|
||||
$tax_object = false;
|
||||
|
||||
switch ( $doaction ) {
|
||||
case 'rank_math_bulk_robots_noindex':
|
||||
case 'rank_math_bulk_robots_index':
|
||||
case 'rank_math_bulk_robots_nofollow':
|
||||
case 'rank_math_bulk_robots_follow':
|
||||
foreach ( $object_ids as $term_id ) {
|
||||
if ( ! $tax_object ) {
|
||||
$tax_object = get_taxonomy( get_term( $term_id )->taxonomy );
|
||||
}
|
||||
$action = str_replace( 'rank_math_bulk_robots_', '', $doaction );
|
||||
$robots = (array) get_term_meta( $term_id, 'rank_math_robots', true );
|
||||
$robots = array_filter( $robots );
|
||||
|
||||
// Remove "opposite" robots meta.
|
||||
$opposite = 'no' . $action;
|
||||
if ( substr( $action, 0, 2 ) === 'no' ) {
|
||||
$opposite = substr( $action, 2 );
|
||||
}
|
||||
if ( ( $key = array_search( $opposite, $robots ) ) !== false ) { // @codingStandardsIgnoreLine
|
||||
unset( $robots[ $key ] );
|
||||
}
|
||||
|
||||
// Add new robots meta.
|
||||
if ( ! in_array( $action, $robots, true ) ) {
|
||||
$robots[] = $action;
|
||||
}
|
||||
$robots = array_unique( $robots );
|
||||
|
||||
update_term_meta( $term_id, 'rank_math_robots', $robots );
|
||||
$edited++;
|
||||
|
||||
if ( 'index' === $action || 'noindex' === $action ) {
|
||||
$this->do_action( 'sitemap/invalidate_object_type', 'term', $term_id );
|
||||
}
|
||||
}
|
||||
// Translators: 1 The number of terms edited. 2 The term taxonomy name.
|
||||
$message = sprintf( __( 'Robots meta edited for %1$d %2$s.', 'rank-math-pro' ), $edited, ( $edited > 1 ? $tax_object->labels->name : $tax_object->labels->singular_name ) );
|
||||
break;
|
||||
|
||||
case 'rank_math_bulk_redirect':
|
||||
$redirect = Helper::get_admin_url( 'redirections' );
|
||||
$i = 0;
|
||||
foreach ( $object_ids as $term_id ) {
|
||||
$term_url = get_term_link( (int) $term_id );
|
||||
if ( is_wp_error( $term_url ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$redirect = add_query_arg( "urls[{$i}]", $term_url, $redirect );
|
||||
$i++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'rank_math_bulk_stop_redirect':
|
||||
foreach ( $object_ids as $term_id ) {
|
||||
$redirection = \RankMath\Redirections\Cache::get_by_object_id( $term_id, 'term' );
|
||||
if ( $redirection ) {
|
||||
\RankMath\Redirections\DB::change_status( $redirection->redirection_id, 'trashed' );
|
||||
$edited++;
|
||||
}
|
||||
}
|
||||
// Translators: placeholder is the number of redirections deleted.
|
||||
$message = sprintf( _n( '%d redirection moved to Trash.', '%d redirections moved to Trash.', $edited, 'rank-math-pro' ), $edited );
|
||||
break;
|
||||
}
|
||||
|
||||
if ( $message ) {
|
||||
Helper::add_notification( $message );
|
||||
}
|
||||
|
||||
return $redirect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save primary term bulk edit. This handles the action performed when the
|
||||
* user selects one or more posts with the checkbox and then selects "Edit"
|
||||
* in the Bulk Edit dropdown.
|
||||
*
|
||||
* @param int $post_id Post ID.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function save_post_primary_term( $post_id ) {
|
||||
if ( Param::get( 'rank_math_quick_edit_nonce' ) ) {
|
||||
return;
|
||||
}
|
||||
if ( ! wp_verify_nonce( Param::get( 'rank_math_bulk_edit_primary_term' ), 'rank-math-edit-primary-term' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$taxonomy = ProAdminHelper::get_primary_taxonomy( $post_id );
|
||||
$input = absint( Param::get( 'rank_math_primary_' . $taxonomy['name'] ) );
|
||||
if ( ! $input ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! has_term( $input, $taxonomy['name'], $post_id ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
update_post_meta( $post_id, 'rank_math_primary_' . $taxonomy['name'], absint( $input ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue scripts and add JSON.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function enqueue() {
|
||||
if ( ! Admin_Helper::is_post_list() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
Helper::add_json( 'confirmSchemaDelete', __( 'Are you sure you want to change the Schema type for the selected posts? Doing so may irreversibly delete the existing Schema data.', 'rank-math-pro' ) );
|
||||
}
|
||||
}
|
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
/**
|
||||
* CSV
|
||||
*
|
||||
* This class defines all code necessary to run during the CSV export.
|
||||
*
|
||||
* @since x.x.x
|
||||
* @package RankMathPro
|
||||
* @subpackage RankMathPro
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Admin;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Installer class.
|
||||
*/
|
||||
class CSV {
|
||||
|
||||
/**
|
||||
* Do export.
|
||||
*
|
||||
* @param array $data Data to export.
|
||||
* @return void
|
||||
*/
|
||||
public function export( $data = [] ) {
|
||||
if ( empty( $data['items'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->increase_limits();
|
||||
$this->headers( $data['filename'] );
|
||||
$this->output( $data );
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Try to increase time limit on server.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function increase_limits() {
|
||||
set_time_limit( 300 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Send headers.
|
||||
*
|
||||
* @param string $name File name.
|
||||
* @return void
|
||||
*/
|
||||
public function headers( $name = '' ) {
|
||||
$sitename = sanitize_key( get_bloginfo( 'name' ) );
|
||||
$filename = $sitename . '_' .$name. '-' . date( 'Y-m-d_H-i-s' ) . '.csv'; // phpcs:ignore
|
||||
|
||||
header( 'Content-Type: application/csv' );
|
||||
header( 'Content-Description: File Transfer' );
|
||||
header( "Content-Disposition: attachment; filename={$filename}" );
|
||||
header( 'Pragma: no-cache' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Output
|
||||
*
|
||||
* @param array $data Data to export.
|
||||
* @return void
|
||||
*/
|
||||
public function output( $data = [] ) {
|
||||
$this->output_csv( $data['columns'] );
|
||||
foreach ( $data['items'] as $line ) {
|
||||
$this->output_csv( array_values( $line ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Output fputcsv instead of saving to a file.
|
||||
*
|
||||
* @param array $data Data array.
|
||||
* @return void
|
||||
*/
|
||||
public function output_csv( $data ) {
|
||||
echo implode( ',', $data ) . "\n"; // phpcs:ignore
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape CSV: quotes and slashes
|
||||
*
|
||||
* @param string $string String to escape.
|
||||
* @return string
|
||||
*/
|
||||
public function escape_csv( $string ) {
|
||||
return '"' . str_replace( [ "'", '"', '\\' ], [ "''", '""', '\\\\' ], $string ) . '"';
|
||||
}
|
||||
}
|
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
/**
|
||||
* Links related functionality.
|
||||
*
|
||||
* @since 1.0
|
||||
* @package RankMathPro
|
||||
* @subpackage RankMathPro\Admin
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Admin;
|
||||
|
||||
use RankMath\Helper;
|
||||
use RankMath\Admin\Admin_Helper;
|
||||
use RankMath\Traits\Hooker;
|
||||
use MyThemeShop\Helpers\Str;
|
||||
use MyThemeShop\Helpers\Arr;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Links class.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class Links {
|
||||
|
||||
use Hooker;
|
||||
|
||||
/**
|
||||
* Base host.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $base_host = '';
|
||||
|
||||
/**
|
||||
* Base path.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $base_path = '';
|
||||
|
||||
/**
|
||||
* Register hooks.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->base_host = Helper::get_url_part( home_url(), 'host' );
|
||||
|
||||
$base_path = Helper::get_url_part( home_url(), 'path' );
|
||||
if ( $base_path ) {
|
||||
$this->base_path = trailingslashit( $base_path );
|
||||
}
|
||||
|
||||
$this->action( 'cmb2_admin_init', 'cmb_init', 99 );
|
||||
$this->action( 'rank_math/links/is_external', 'link_is_external', 20, 2 );
|
||||
$this->action( 'rank_math/admin/enqueue_scripts', 'add_json', 20 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook CMB2 init process.
|
||||
*/
|
||||
public function cmb_init() {
|
||||
$this->action( 'cmb2_init_hookup_rank-math-options-general_options', 'add_options', 110 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add options to Image SEO module.
|
||||
*
|
||||
* @param object $cmb CMB object.
|
||||
*/
|
||||
public function add_options( $cmb ) {
|
||||
$field_ids = wp_list_pluck( $cmb->prop( 'fields' ), 'id' );
|
||||
$fields_position = array_search( 'new_window_external_links', array_keys( $field_ids ), true ) + 1;
|
||||
|
||||
$cmb->add_field(
|
||||
[
|
||||
'id' => 'affiliate_link_prefixes',
|
||||
'type' => 'textarea_small',
|
||||
'name' => esc_html__( 'Affiliate Link Prefix', 'rank-math-pro' ),
|
||||
'desc' => wp_kses_post( __( 'Add the URI prefixes you use for affiliate (cloaked) links, which redirect to external sites. These will not count as internal links in the content analysis. Add one per line.', 'rank-math-pro' ) ),
|
||||
'classes' => 'rank-math-advanced-option',
|
||||
'dep' => [
|
||||
[ 'nofollow_external_links', 'on' ],
|
||||
[ 'nofollow_image_links', 'on' ],
|
||||
],
|
||||
'attributes' => [
|
||||
'placeholder' => esc_html__( 'Example: /get/', 'rank-math-pro' ),
|
||||
],
|
||||
],
|
||||
++$fields_position
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make cloaked affiliate links external.
|
||||
*
|
||||
* @param bool $is_external Is external link.
|
||||
* @param array $url_parts URL parts from wp_parse_url().
|
||||
* @return mixed
|
||||
*/
|
||||
public function link_is_external( $is_external, $url_parts ) {
|
||||
if ( empty( $url_parts['path'] ) ) {
|
||||
return $is_external;
|
||||
}
|
||||
|
||||
// Check if internal link.
|
||||
if (
|
||||
! isset( $url_parts['host'] )
|
||||
|| '' === $url_parts['host']
|
||||
|| $url_parts['host'] === $this->base_host
|
||||
) {
|
||||
// Check if path starts with one of the affiliate_link_prefixes.
|
||||
$prefixes = Arr::from_string( Helper::get_settings( 'general.affiliate_link_prefixes' ), "\n" );
|
||||
foreach ( $prefixes as $prefix ) {
|
||||
if ( Str::starts_with( $prefix, $url_parts['path'] ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $is_external;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add JSON.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add_json() {
|
||||
$prefixes = Arr::from_string( Helper::get_settings( 'general.affiliate_link_prefixes' ), "\n" );
|
||||
wp_enqueue_script(
|
||||
'rank-math-pro-links',
|
||||
RANK_MATH_PRO_URL . 'assets/admin/js/links.js',
|
||||
[ 'wp-hooks' ],
|
||||
rank_math_pro()->version
|
||||
);
|
||||
Helper::add_json( 'affiliate_link_prefixes', $prefixes );
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,186 @@
|
||||
<?php
|
||||
/**
|
||||
* Post filters for the manage posts screen.
|
||||
*
|
||||
* @since 1.0
|
||||
* @package RankMathPro
|
||||
* @subpackage RankMathPro\Admin
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Admin;
|
||||
|
||||
use RankMath\Helper;
|
||||
use RankMath\Traits\Hooker;
|
||||
use MyThemeShop\Helpers\Param;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Post filters class.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class Media_Filters {
|
||||
|
||||
use Hooker;
|
||||
|
||||
/**
|
||||
* Register hooks.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->filter( 'ajax_query_attachments_args', 'attachments_query_filter' );
|
||||
|
||||
global $pagenow;
|
||||
if ( 'upload.php' !== $pagenow ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->action( 'wp_enqueue_media', 'enqueue_media', 20 );
|
||||
$this->action( 'restrict_manage_posts', 'add_seo_filter' );
|
||||
$this->action( 'pre_get_posts', 'posts_by_seo_filters' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue assets for Media Library.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function enqueue_media() {
|
||||
wp_enqueue_script( 'media-library-seo-filter', RANK_MATH_PRO_URL . 'assets/admin/js/media.js', [ 'media-editor', 'media-views', 'media-models' ], rank_math_pro()->version ); // phpcs:ignore
|
||||
wp_localize_script(
|
||||
'media-library-seo-filter',
|
||||
'RankMathProMedia',
|
||||
[
|
||||
'filters' => $this->get_filters(),
|
||||
'filter_all' => __( 'Rank Math SEO Filters', 'rank-math-pro' ),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook to add SEO Filters in List View on attachment page..
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add_seo_filter() {
|
||||
$filter = sanitize_title( wp_unslash( isset( $_GET['seo-filter'] ) ? $_GET['seo-filter'] : '' ) ); // phpcs:ignore
|
||||
?>
|
||||
<select id="media-attachment-seo-filter" name="seo-filter" class="attachment-filters">
|
||||
<option value="all"><?php echo esc_html__( 'Rank Math SEO Filters', 'rank-math-pro' ); ?></option>
|
||||
<?php foreach ( $this->get_filters() as $key => $value ) { ?>
|
||||
<option value="<?php echo esc_attr( $key ); ?>" <?php selected( $filter, $key ); ?>>
|
||||
<?php echo esc_html( $value ); ?>
|
||||
</option>
|
||||
<?php } ?>
|
||||
</select>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter attachments in admin by Rank Math's Filter value.
|
||||
*
|
||||
* @param \WP_Query $query The wp_query instance.
|
||||
*/
|
||||
public function posts_by_seo_filters( $query ) {
|
||||
$filter = Param::get( 'seo-filter' );
|
||||
if ( ! $filter ) {
|
||||
return $query;
|
||||
}
|
||||
|
||||
switch ( $filter ) {
|
||||
case 'missing_alt':
|
||||
$query->set( 'meta_key', '_wp_attachment_image_alt' );
|
||||
$query->set( 'meta_compare', 'NOT EXISTS' );
|
||||
break;
|
||||
|
||||
case 'missing_title':
|
||||
$this->filter( 'posts_clauses', 'filter_query_attachment_titles' );
|
||||
break;
|
||||
|
||||
case 'missing_caption':
|
||||
$this->filter( 'posts_clauses', 'filter_query_attachment_captions' );
|
||||
break;
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify media ajax query according to the selected SEO filter.
|
||||
*
|
||||
* @param array $query Query parameters.
|
||||
* @return array New query parameters.
|
||||
*/
|
||||
public function attachments_query_filter( $query ) {
|
||||
if ( empty( $_POST['query']['attachment_seo_filter'] ) ) { // phpcs:ignore
|
||||
return $query;
|
||||
}
|
||||
|
||||
$filter = sanitize_title( wp_unslash( $_POST['query']['attachment_seo_filter'] ) ); // phpcs:ignore
|
||||
switch ( $filter ) {
|
||||
case 'missing_alt':
|
||||
if ( ! isset( $query['meta_query'] ) ) {
|
||||
$query['meta_query'] = [];
|
||||
}
|
||||
$query['meta_query'][] = [
|
||||
'key' => '_wp_attachment_image_alt',
|
||||
'compare' => 'NOT EXISTS',
|
||||
];
|
||||
break;
|
||||
|
||||
case 'missing_title':
|
||||
$this->filter( 'posts_clauses', 'filter_query_attachment_titles' );
|
||||
break;
|
||||
|
||||
case 'missing_caption':
|
||||
$this->filter( 'posts_clauses', 'filter_query_attachment_captions' );
|
||||
break;
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the SQL clauses of an attachment query to match attachments where
|
||||
* the title equals the filename.
|
||||
*
|
||||
* @param string[] $clauses An array including WHERE, GROUP BY, JOIN, ORDER BY,
|
||||
* DISTINCT, fields (SELECT), and LIMITS clauses.
|
||||
* @return string[] The modified array of clauses.
|
||||
*/
|
||||
public function filter_query_attachment_titles( $clauses ) {
|
||||
remove_filter( 'posts_clauses', __FUNCTION__ );
|
||||
$clauses['where'] .= " AND ( post_title = '' OR ( ( post_title LIKE '%.png' OR post_title LIKE '%.jpg' OR post_title LIKE '%.gif' OR post_title LIKE '%.jpeg' ) AND INSTR( guid, post_title ) != 0 ) )";
|
||||
|
||||
return $clauses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the SQL clauses of an attachment query to match attachments where
|
||||
* caption is empty.
|
||||
*
|
||||
* @param string[] $clauses An array including WHERE, GROUP BY, JOIN, ORDER BY,
|
||||
* DISTINCT, fields (SELECT), and LIMITS clauses.
|
||||
* @return string[] The modified array of clauses.
|
||||
*/
|
||||
public function filter_query_attachment_captions( $clauses ) {
|
||||
remove_filter( 'posts_clauses', __FUNCTION__ );
|
||||
$clauses['where'] .= " AND post_excerpt = ''";
|
||||
|
||||
return $clauses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get attachment filters option.
|
||||
*
|
||||
* @return array The filters array.
|
||||
*/
|
||||
private function get_filters() {
|
||||
return [
|
||||
'missing_alt' => __( 'Missing alt tag', 'rank-math-pro' ),
|
||||
'missing_title' => __( 'Missing or default title tag', 'rank-math-pro' ),
|
||||
'missing_caption' => __( 'Missing caption', 'rank-math-pro' ),
|
||||
];
|
||||
}
|
||||
}
|
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
/**
|
||||
* Miscellaneous admin related functionality.
|
||||
*
|
||||
* @since 1.0
|
||||
* @package RankMathPro
|
||||
* @subpackage RankMathPro\Admin
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Admin;
|
||||
|
||||
use RankMath\Helper;
|
||||
use RankMath\Traits\Hooker;
|
||||
use RankMath\Admin\Admin_Helper;
|
||||
use RankMathPro\Admin\Admin_Helper as ProAdminHelper;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Misc admin class.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class Misc {
|
||||
|
||||
use Hooker;
|
||||
|
||||
/**
|
||||
* Register hooks.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->action( 'cmb2_default_filter', 'change_fk_default', 20, 2 );
|
||||
$this->action( 'rank_math/pro_badge', 'header_pro_badge' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add options to Image SEO module.
|
||||
*
|
||||
* @param mixed $default Default value.
|
||||
* @param object $field Field object.
|
||||
*/
|
||||
public function change_fk_default( $default, $field ) {
|
||||
if ( 'rank_math_focus_keyword' !== $field->id() ) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
if ( ! Admin_Helper::is_term_edit() ) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
return $this->get_term();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get term.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_term() {
|
||||
global $tag;
|
||||
if ( isset( $tag->name ) ) {
|
||||
return $tag->name;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check and print the license type as a badge in the header of Rank Math's setting pages.
|
||||
*/
|
||||
public static function header_pro_badge() {
|
||||
$plan = ProAdminHelper::get_plan();
|
||||
echo '<span class="rank-math-pro-badge ' . esc_attr( $plan ) . '">' . esc_html( $plan ) . '</span>';
|
||||
}
|
||||
}
|
@@ -0,0 +1,355 @@
|
||||
<?php
|
||||
/**
|
||||
* Post filters for the manage posts screen.
|
||||
*
|
||||
* @since 1.0
|
||||
* @package RankMathPro
|
||||
* @subpackage RankMathPro\Admin
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Admin;
|
||||
|
||||
use RankMath\Helper;
|
||||
use RankMath\Traits\Hooker;
|
||||
use MyThemeShop\Helpers\Param;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Post filters class.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class Post_Filters {
|
||||
|
||||
use Hooker;
|
||||
|
||||
/**
|
||||
* Register hooks.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->filter( 'rank_math/manage_posts/seo_filter_options', 'add_seo_filters', 10, 1 );
|
||||
$this->filter( 'restrict_manage_posts', 'add_schema_filters', 20, 0 );
|
||||
$this->filter( 'manage_posts_extra_tablenav', 'add_filter_clear_button', 20, 1 );
|
||||
$this->filter( 'pre_get_posts', 'posts_by_seo_filters', 20 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add our custom options to the SEO filter dropdown.
|
||||
*
|
||||
* @param array $options Original options.
|
||||
*
|
||||
* @return array New options.
|
||||
*/
|
||||
public function add_seo_filters( $options ) {
|
||||
$new_options = [
|
||||
'custom_canonical' => __( 'Custom Canonical URL', 'rank-math-pro' ),
|
||||
'custom_title' => __( 'Custom Meta Title', 'rank-math-pro' ),
|
||||
'custom_description' => __( 'Custom Meta Description', 'rank-math-pro' ),
|
||||
'redirected' => __( 'Redirected Posts', 'rank-math-pro' ),
|
||||
'orphan' => __( 'Orphan Posts', 'rank-math-pro' ),
|
||||
];
|
||||
|
||||
if ( Helper::is_module_active( 'rich-snippet' ) ) {
|
||||
$new_options['schema_type'] = __( 'Filter by Schema Type', 'rank-math-pro' );
|
||||
}
|
||||
|
||||
return $options + $new_options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output dropdown to filter by Schema type.
|
||||
*/
|
||||
public function add_schema_filters() {
|
||||
global $post_type;
|
||||
|
||||
if ( 'attachment' === $post_type || ! in_array( $post_type, Helper::get_allowed_post_types(), true ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$options = [
|
||||
'none' => esc_html__( 'Turned Off', 'rank-math-pro' ),
|
||||
'Article' => esc_html__( 'Article', 'rank-math-pro' ),
|
||||
'BlogPosting' => esc_html__( 'Blog Post', 'rank-math-pro' ),
|
||||
'NewsArticle' => esc_html__( 'News Article', 'rank-math-pro' ),
|
||||
'Book' => esc_html__( 'Book', 'rank-math-pro' ),
|
||||
'Course' => esc_html__( 'Course', 'rank-math-pro' ),
|
||||
'Event' => esc_html__( 'Event', 'rank-math-pro' ),
|
||||
'PodcastEpisode' => esc_html__( 'Podcast', 'rank-math-pro' ),
|
||||
'JobPosting' => esc_html__( 'Job Posting', 'rank-math-pro' ),
|
||||
'MusicGroup' => esc_html__( 'Music', 'rank-math-pro' ),
|
||||
'Movie' => esc_html__( 'Movie', 'rank-math-pro' ),
|
||||
'Person' => esc_html__( 'Person', 'rank-math-pro' ),
|
||||
'Product' => esc_html__( 'Product', 'rank-math-pro' ),
|
||||
'Recipe' => esc_html__( 'Recipe', 'rank-math-pro' ),
|
||||
'Restaurant' => esc_html__( 'Restaurant', 'rank-math-pro' ),
|
||||
'Service' => esc_html__( 'Service', 'rank-math-pro' ),
|
||||
'SoftwareApplication' => esc_html__( 'Software', 'rank-math-pro' ),
|
||||
'VideoObject' => esc_html__( 'Video', 'rank-math-pro' ),
|
||||
'Dataset' => esc_html__( 'Dataset', 'rank-math-pro' ),
|
||||
'FAQPage' => esc_html__( 'FAQ', 'rank-math-pro' ),
|
||||
'ClaimReview' => esc_html__( 'FactCheck', 'rank-math-pro' ),
|
||||
'HowTo' => esc_html__( 'How To', 'rank-math-pro' ),
|
||||
];
|
||||
|
||||
$options = $this->do_filter( 'manage_posts/schema_filter_options', $options, $post_type );
|
||||
$selected = Param::get( 'schema-filter' );
|
||||
?>
|
||||
<select name="schema-filter" id="rank-math-schema-filter" class="hidden">
|
||||
<?php foreach ( $options as $val => $option ) : ?>
|
||||
<option value="<?php echo esc_attr( $val ); ?>" <?php selected( $selected, $val, true ); ?>><?php echo esc_html( $option ); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter for pre WP Query on the post list page.
|
||||
*
|
||||
* @param object $query Query object passed by reference.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function posts_by_seo_filters( $query ) {
|
||||
if ( ! $query->is_main_query() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! $this->can_seo_filters() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$meta_query = $query->get( 'meta_query' );
|
||||
$filter = Param::get( 'seo-filter' );
|
||||
$this->set_seo_filters( $meta_query, $filter );
|
||||
if ( ! empty( $meta_query ) ) {
|
||||
$query->set( 'meta_query', $meta_query );
|
||||
}
|
||||
|
||||
if ( 'redirected' === $filter ) {
|
||||
$query->set( 'is_redirected', 1 );
|
||||
$this->filter( 'posts_where', 'posts_where_redirected', 10, 2 );
|
||||
} elseif ( 'orphan' === $filter ) {
|
||||
$query->set( 'is_orphan', 1 );
|
||||
$this->filter( 'posts_where', 'posts_where_orphan', 10, 2 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add SEO filters for the meta_query.
|
||||
*
|
||||
* @param array $query The meta_query array passed by reference.
|
||||
* @param string $filter Input filter.
|
||||
*/
|
||||
public function set_seo_filters( &$query, $filter ) {
|
||||
if ( false === $filter ) {
|
||||
return;
|
||||
} elseif ( 'schema_type' === $filter ) {
|
||||
$schema_filter = Param::get( 'schema-filter' );
|
||||
$this->set_schema_filters( $query, $schema_filter );
|
||||
return;
|
||||
}
|
||||
|
||||
$hash = [
|
||||
'custom_canonical' => [
|
||||
[
|
||||
'key' => 'rank_math_canonical_url',
|
||||
'compare' => 'EXISTS',
|
||||
],
|
||||
[
|
||||
'key' => 'rank_math_canonical_url',
|
||||
'compare' => '!=',
|
||||
'value' => '',
|
||||
],
|
||||
],
|
||||
'custom_title' => [
|
||||
[
|
||||
'key' => 'rank_math_title',
|
||||
'compare' => 'EXISTS',
|
||||
],
|
||||
[
|
||||
'key' => 'rank_math_title',
|
||||
'compare' => '!=',
|
||||
'value' => '',
|
||||
],
|
||||
],
|
||||
'custom_description' => [
|
||||
[
|
||||
'key' => 'rank_math_description',
|
||||
'compare' => 'EXISTS',
|
||||
],
|
||||
[
|
||||
'key' => 'rank_math_description',
|
||||
'compare' => '!=',
|
||||
'value' => '',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
if ( isset( $hash[ $filter ] ) ) {
|
||||
foreach ( $hash[ $filter ] as $query_parts ) {
|
||||
$query[] = $query_parts;
|
||||
}
|
||||
$query[] = $hash[ $filter ];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Schema type filters for the meta_query.
|
||||
*
|
||||
* @param array $query The meta_query array passed by reference.
|
||||
* @param string $filter Input filter.
|
||||
*/
|
||||
public function set_schema_filters( &$query, $filter ) {
|
||||
$post_type = Param::get( 'post_type' );
|
||||
$post_type_default = Helper::get_settings( 'titles.pt_' . $post_type . '_default_rich_snippet' );
|
||||
|
||||
if ( false === $filter ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( 'none' === $filter ) {
|
||||
$query[] = [
|
||||
'key' => 'rank_math_rich_snippet',
|
||||
'value' => 'off',
|
||||
];
|
||||
$this->filter( 'posts_where', 'posts_where_no_schema', 20, 2 );
|
||||
return;
|
||||
}
|
||||
|
||||
switch ( $filter ) {
|
||||
case 'Event':
|
||||
$query['relation'] = 'OR';
|
||||
foreach ( [ 'Event', 'BusinessEvent', 'ChildrensEvent', 'ComedyEvent', 'DanceEvent', 'DeliveryEvent', 'EducationEvent', 'ExhibitionEvent', 'Festival', 'FoodEvent', 'LiteraryEvent', 'MusicEvent', 'PublicationEvent', 'SaleEvent', 'ScreeningEvent', 'SocialEvent', 'SportsEvent', 'TheaterEvent', 'VisualArtsEvent' ] as $type ) {
|
||||
$query[] = [
|
||||
'key' => 'rank_math_schema_' . $type,
|
||||
'compare' => 'LIKE',
|
||||
];
|
||||
}
|
||||
break;
|
||||
case 'Music':
|
||||
$query['relation'] = 'OR';
|
||||
foreach ( [ 'MusicAlbum', 'MusicGroup' ] as $type ) {
|
||||
$query[] = [
|
||||
'key' => 'rank_math_schema_' . $type,
|
||||
'compare' => 'LIKE',
|
||||
];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$query[] = [
|
||||
'key' => 'rank_math_schema_' . $filter,
|
||||
'compare' => 'LIKE',
|
||||
];
|
||||
break;
|
||||
}
|
||||
|
||||
if ( strtolower( $filter ) === $post_type_default ) {
|
||||
// Also get not set because we filter for the default.
|
||||
$query['relation'] = 'OR';
|
||||
$query[] = [
|
||||
'key' => 'rank_math_rich_snippet',
|
||||
'compare' => 'NOT EXISTS',
|
||||
];
|
||||
$this->filter( 'posts_where', 'posts_where_no_schema', 20, 2 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add extra WHERE clause to find posts with no Schema.
|
||||
*
|
||||
* @param string $where Original WHERE clause string.
|
||||
* @param \WP_Query $wp_query WP_Query object.
|
||||
* @return string
|
||||
*/
|
||||
public function posts_where_no_schema( $where, \WP_Query $wp_query ) {
|
||||
global $wpdb;
|
||||
$where .= " AND NOT EXISTS ( SELECT meta_id FROM {$wpdb->postmeta} WHERE post_id = {$wpdb->posts}.ID AND meta_key LIKE 'rank_math_schema_%' )";
|
||||
// Remove this filter for subsequent queries.
|
||||
$this->remove_filter( 'posts_where', 'posts_where_no_schema', 20, 2 );
|
||||
|
||||
return $where;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can apply SEO filters.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function can_seo_filters() {
|
||||
global $pagenow;
|
||||
if ( 'edit.php' !== $pagenow || ! in_array( Param::get( 'post_type' ), Helper::get_allowed_post_types(), true ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add our where clause to the query.
|
||||
*
|
||||
* @param string $where Original where clause.
|
||||
* @param object $query The query object.
|
||||
*
|
||||
* @return string New where clause.
|
||||
*/
|
||||
public function posts_where_redirected( $where, $query ) {
|
||||
if ( ! $query->get( 'is_redirected' ) ) {
|
||||
return $where;
|
||||
}
|
||||
global $wpdb;
|
||||
$redirections_table = $wpdb->prefix . 'rank_math_redirections_cache';
|
||||
|
||||
$where .= " AND ID IN ( SELECT object_id FROM {$redirections_table} WHERE is_redirected = 1 AND object_type = 'post' )";
|
||||
return $where;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add our where clause to the query.
|
||||
*
|
||||
* @param string $where Original where clause.
|
||||
* @param object $query The query object.
|
||||
*
|
||||
* @return string New where clause.
|
||||
*/
|
||||
public function posts_where_orphan( $where, $query ) {
|
||||
if ( ! $query->get( 'is_orphan' ) ) {
|
||||
return $where;
|
||||
}
|
||||
global $wpdb;
|
||||
$linkmeta_table = $wpdb->prefix . 'rank_math_internal_meta';
|
||||
|
||||
$where .= " AND ID IN ( SELECT object_id FROM {$linkmeta_table} WHERE incoming_link_count = 0 )";
|
||||
return $where;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add filter reset button
|
||||
*
|
||||
* @param string $which Where to place.
|
||||
*/
|
||||
public function add_filter_clear_button( $which ) {
|
||||
if ( 'top' !== $which ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$post_type = get_post_type();
|
||||
$clear_label = __( 'Clear Filter', 'rank-math-pro' );
|
||||
$clear_url = add_query_arg( 'post_type', $post_type, admin_url( 'edit.php' ) );
|
||||
$clear_classes = 'clear-tablenav-filter';
|
||||
$filter_params = [ 'm', 'cat', 'seo-filter' ];
|
||||
$filtered = false;
|
||||
|
||||
foreach ( $filter_params as $filter ) {
|
||||
$val = Param::get( $filter );
|
||||
if ( ! empty( $val ) ) {
|
||||
$filtered = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$clear_classes .= $filtered ? '' : ' hidden';
|
||||
|
||||
echo '<a href="' . esc_url( $clear_url ) . '" class="' . esc_attr( $clear_classes ) . '" title="' . esc_attr( $clear_label ) . '"><span class="dashicons dashicons-dismiss"></span> ' . esc_html( $clear_label ) . '</a>';
|
||||
}
|
||||
}
|
@@ -0,0 +1,641 @@
|
||||
<?php
|
||||
/**
|
||||
* Extend the quick edit functionality on the manage posts screen.
|
||||
*
|
||||
* @since 1.0
|
||||
* @package RankMathPro
|
||||
* @subpackage RankMathPro\Admin
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Admin;
|
||||
|
||||
use RankMath\Helper;
|
||||
use RankMath\Traits\Hooker;
|
||||
use RankMath\Admin\Admin_Helper;
|
||||
use RankMathPro\Admin\Admin_Helper as ProAdminHelper;
|
||||
use MyThemeShop\Helpers\Param;
|
||||
use MyThemeShop\Helpers\Arr;
|
||||
use MyThemeShop\Helpers\Conditional;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Quick edit class.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class Quick_Edit {
|
||||
|
||||
use Hooker;
|
||||
|
||||
/**
|
||||
* Register hooks.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->action( 'admin_enqueue_scripts', 'admin_scripts', 20 );
|
||||
$this->action( 'rank_math/post/column/seo_details', 'quick_edit_hidden_fields' );
|
||||
$this->action( 'quick_edit_custom_box', 'quick_edit' );
|
||||
$this->action( 'bulk_edit_custom_box', 'bulk_edit' );
|
||||
$this->action( 'save_post', 'save_post' );
|
||||
$this->action( 'load-edit.php', 'maybe_save_bulk_edit', 20 );
|
||||
|
||||
$taxonomies = Helper::get_accessible_taxonomies();
|
||||
unset( $taxonomies['post_format'] );
|
||||
$taxonomies = wp_list_pluck( $taxonomies, 'label', 'name' );
|
||||
foreach ( $taxonomies as $taxonomy => $label ) {
|
||||
$this->filter( "manage_edit-{$taxonomy}_columns", 'add_tax_seo_column' );
|
||||
$this->filter( "manage_{$taxonomy}_custom_column", 'tax_seo_column_content', 10, 3 );
|
||||
$this->filter( "edited_{$taxonomy}", 'save_tax' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add hidden column for SEO details for the quick edit.
|
||||
*
|
||||
* @param string[] $columns Original columns array.
|
||||
*
|
||||
* @return string[] New columns array.
|
||||
*/
|
||||
public function add_tax_seo_column( $columns ) {
|
||||
$columns['rank_math_tax_seo_details'] = __( 'SEO Details', 'rank-math-pro' );
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the hidden fields in the SEO Details column of the terms listing screen.
|
||||
*
|
||||
* @param string $string Current content.
|
||||
* @param string $column_name Column name.
|
||||
* @param int $term_id Term ID.
|
||||
*
|
||||
* @return string New content.
|
||||
*/
|
||||
public function tax_seo_column_content( $string, $column_name, $term_id ) {
|
||||
if ( 'rank_math_tax_seo_details' !== $column_name ) {
|
||||
return $string;
|
||||
}
|
||||
|
||||
ob_start();
|
||||
$this->quick_edit_hidden_fields( $term_id, 'term' );
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Output hidden fields in the `seo_details` column on the posts and the
|
||||
* terms screen, to use the data in the quick edit form.
|
||||
*
|
||||
* @param int $object_id Post/term ID.
|
||||
* @param object $object_type Object type: post or term.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function quick_edit_hidden_fields( $object_id, $object_type = 'post' ) {
|
||||
if ( ! in_array( $object_type, [ 'post', 'term' ], true ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( 'post' === $object_type && ! $this->can_bulk_edit() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$robots = array_filter( (array) get_metadata( $object_type, $object_id, 'rank_math_robots', true ) );
|
||||
|
||||
if ( empty( $robots ) ) {
|
||||
$robots = Helper::get_robots_defaults();
|
||||
}
|
||||
|
||||
// Maybe product with hidden visibility!
|
||||
if ( Conditional::is_woocommerce_active() && 'product' === get_post_type( $object_id ) && Helper::get_settings( 'general.noindex_hidden_products' ) ) {
|
||||
$product = \wc_get_product( $object_id );
|
||||
|
||||
if ( $product && $product->get_catalog_visibility() === 'hidden' ) {
|
||||
// Preserve other robots values.
|
||||
$robots = array_filter(
|
||||
$robots,
|
||||
function ( $robot ) {
|
||||
return 'index' !== $robot;
|
||||
}
|
||||
);
|
||||
|
||||
$robots = array_merge( $robots, [ 'noindex' ] );
|
||||
}
|
||||
}
|
||||
|
||||
$title = get_metadata( $object_type, $object_id, 'rank_math_title', true );
|
||||
if ( ! $title ) {
|
||||
if ( 'post' === $object_type ) {
|
||||
$post_type = get_post_type( $object_id );
|
||||
$title = Helper::get_settings( "titles.pt_{$post_type}_title" );
|
||||
} elseif ( 'term' === $object_type ) {
|
||||
$term = get_term( $object_id );
|
||||
$taxonomy = $term->taxonomy;
|
||||
$title = Helper::get_settings( "titles.tax_{$taxonomy}_title" );
|
||||
}
|
||||
}
|
||||
|
||||
$description = get_metadata( $object_type, $object_id, 'rank_math_description', true );
|
||||
if ( ! $description ) {
|
||||
if ( 'post' === $object_type ) {
|
||||
$post_type = get_post_type( $object_id );
|
||||
$description = Helper::get_settings( "titles.pt_{$post_type}_description" );
|
||||
} elseif ( 'term' === $object_type ) {
|
||||
$term = get_term( $object_id );
|
||||
$taxonomy = $term->taxonomy;
|
||||
$description = Helper::get_settings( "titles.tax_{$taxonomy}_description" );
|
||||
}
|
||||
}
|
||||
|
||||
$canonical = get_metadata( $object_type, $object_id, 'rank_math_canonical_url', true );
|
||||
$focus_keywords = Arr::from_string( get_metadata( $object_type, $object_id, 'rank_math_focus_keyword', true ) );
|
||||
$primary_keyword = ! empty( $focus_keywords ) ? $focus_keywords[0] : '';
|
||||
|
||||
$canonical_placeholder = '';
|
||||
if ( 'post' === $object_type ) {
|
||||
$canonical_placeholder = get_permalink( $object_id );
|
||||
} elseif ( 'term' === $object_type ) {
|
||||
$canonical_placeholder = get_term_link( $object_id );
|
||||
}
|
||||
?>
|
||||
|
||||
<input type="hidden" class="rank-math-title-value" id="rank-math-title-<?php echo esc_attr( $object_id ); ?>" value="<?php echo esc_attr( $title ); ?>">
|
||||
<input type="hidden" class="rank-math-description-value" id="rank-math-description-<?php echo esc_attr( $object_id ); ?>" value="<?php echo esc_attr( $description ); ?>">
|
||||
<input type="hidden" class="rank-math-robots-meta-value" id="rank-math-robots-meta-<?php echo esc_attr( $object_id ); ?>" value="<?php echo esc_attr( wp_json_encode( $robots ) ); ?>">
|
||||
<input type="hidden" class="rank-math-canonical-url-value" id="rank-math-canonical-url-<?php echo esc_attr( $object_id ); ?>" value="<?php echo esc_attr( $canonical ); ?>">
|
||||
<input type="hidden" class="rank-math-canonical-placeholder-value" id="rank-math-canonical-placeholder-<?php echo esc_attr( $object_id ); ?>" value="<?php echo esc_attr( $canonical_placeholder ); ?>">
|
||||
<input type="hidden" class="rank-math-focus-keywords-value" id="rank-math-focus-keywords-<?php echo esc_attr( $object_id ); ?>" value="<?php echo esc_attr( $primary_keyword ); ?>">
|
||||
<?php if ( 'post' === $object_type ) : ?>
|
||||
<input type="hidden" class="rank-math-primary-term-value" id="rank-math-primary-term-<?php echo esc_attr( $object_id ); ?>" value="<?php echo esc_attr( ProAdminHelper::get_primary_term_id( $object_id ) ); ?>">
|
||||
<?php endif; ?>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue styles and scripts.
|
||||
*/
|
||||
public function admin_scripts() {
|
||||
global $pagenow;
|
||||
if ( Admin_Helper::is_post_list() ) {
|
||||
wp_enqueue_script( 'rank-math-pro-post-list', RANK_MATH_PRO_URL . 'assets/admin/js/post-list.js', [], RANK_MATH_PRO_VERSION, true );
|
||||
wp_enqueue_style( 'rank-math-pro-post-list', RANK_MATH_PRO_URL . 'assets/admin/css/post-list.css', [], RANK_MATH_PRO_VERSION );
|
||||
} elseif ( 'edit-tags.php' === $pagenow ) {
|
||||
wp_enqueue_script( 'rank-math-pro-term-list', RANK_MATH_PRO_URL . 'assets/admin/js/term-list.js', [], RANK_MATH_PRO_VERSION, true );
|
||||
wp_enqueue_style( 'rank-math-pro-term-list', RANK_MATH_PRO_URL . 'assets/admin/css/term-list.css', [], RANK_MATH_PRO_VERSION );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display our custom content on the quick-edit interface. No values can be
|
||||
* pre-populated (all done in JS).
|
||||
*
|
||||
* @param string $column Column name.
|
||||
* @param bool $bulk_edit Is bulk edit row.
|
||||
* @return void
|
||||
*/
|
||||
public function quick_edit( $column, $bulk_edit = false ) {
|
||||
if ( ! $this->can_bulk_edit() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
global $post_type;
|
||||
$ptype = $post_type;
|
||||
if ( is_a( $ptype, 'WP_Post_Type' ) ) {
|
||||
$ptype = $ptype->name;
|
||||
}
|
||||
|
||||
global $pagenow;
|
||||
if ( 'edit-tags.php' === $pagenow ) {
|
||||
global $taxonomy;
|
||||
$ptype = $taxonomy;
|
||||
}
|
||||
|
||||
$columns = get_column_headers( 'edit-' . $ptype );
|
||||
if ( ! isset( $columns['rank_math_seo_details'] ) && ! isset( $columns['rank_math_tax_seo_details'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$robots = [
|
||||
'index' => __( 'Index', 'rank-math-pro' ),
|
||||
'noindex' => __( 'No Index', 'rank-math-pro' ),
|
||||
'nofollow' => __( 'No Follow', 'rank-math-pro' ),
|
||||
'noarchive' => __( 'No Archive', 'rank-math-pro' ),
|
||||
'noimageindex' => __( 'No Image Index', 'rank-math-pro' ),
|
||||
'nosnippet' => __( 'No Snippet', 'rank-math-pro' ),
|
||||
];
|
||||
|
||||
switch ( $column ) {
|
||||
case 'rank_math_seo_details':
|
||||
wp_nonce_field( 'rank-math-quick-edit', 'rank_math_quick_edit_nonce' );
|
||||
?>
|
||||
<div class="rank-math-quick-edit wp-clearfix">
|
||||
<fieldset class="inline-edit-col-left clear">
|
||||
<legend class="inline-edit-legend">
|
||||
<?php esc_html_e( 'SEO Settings', 'rank-math-pro' ); ?>
|
||||
</legend>
|
||||
<div class="inline-edit-col wp-clearfix">
|
||||
<?php
|
||||
break;
|
||||
|
||||
case 'rank_math_title':
|
||||
?>
|
||||
<label>
|
||||
<span class="title"><?php esc_html_e( 'SEO Title', 'rank-math-pro' ); ?></span>
|
||||
<span class="input-text-wrap rank-math-quick-edit-text-wrap">
|
||||
<input type="text" name="rank_math_title" id="rank_math_title" value="">
|
||||
</span>
|
||||
</label>
|
||||
<?php
|
||||
break;
|
||||
|
||||
case 'rank_math_description':
|
||||
?>
|
||||
<label class="inline-edit-seo-description">
|
||||
<span class="title"><?php esc_html_e( 'SEO Description', 'rank-math-pro' ); ?></span>
|
||||
<textarea name="rank_math_description" id="rank_math_description"></textarea>
|
||||
</label>
|
||||
</div></fieldset>
|
||||
|
||||
<fieldset class="inline-edit-col-center inline-edit-robots">
|
||||
<div class="inline-edit-col">
|
||||
<span class="title inline-edit-robots-label"><?php esc_html_e( 'Robots Meta', 'rank-math-pro' ); ?></span>
|
||||
<ul class="cat-checklist category-checklist rank-math-robots-checklist">
|
||||
<?php foreach ( $robots as $val => $option ) : ?>
|
||||
<li id="rank_math_robots_<?php echo esc_attr( $val ); ?>" class="rank_math_robots">
|
||||
<label class="selectit">
|
||||
<input type="checkbox" name="rank_math_robots[]" id="rank_math_robots_<?php echo esc_attr( $val ); ?>_input" value="<?php echo esc_attr( $val ); ?>" checked="">
|
||||
<?php echo esc_html( $option ); ?>
|
||||
</label>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="inline-edit-col-right">
|
||||
<div class="inline-edit-col">
|
||||
<?php if ( ! $bulk_edit ) { ?>
|
||||
<label>
|
||||
<span class="title"><?php esc_html_e( 'Primary Focus Keyword', 'rank-math-pro' ); ?></span>
|
||||
<span class="input-text-wrap rank-math-quick-edit-text-wrap">
|
||||
<input type="text" name="rank_math_focus_keyword" id="rank_math_focus_keyword" value="">
|
||||
</span>
|
||||
</label>
|
||||
<label>
|
||||
<span class="title"><?php esc_html_e( 'Canonical URL', 'rank-math-pro' ); ?></span>
|
||||
<span class="input-text-wrap rank-math-quick-edit-text-wrap">
|
||||
<input type="text" name="rank_math_canonical_url" id="rank_math_canonical_url" value="">
|
||||
</span>
|
||||
</label>
|
||||
<?php
|
||||
if ( false === $this->do_filter( 'admin/disable_primary_term', false ) ) :
|
||||
$taxonomy = ProAdminHelper::get_primary_taxonomy();
|
||||
if ( false !== $taxonomy ) :
|
||||
?>
|
||||
<fieldset class="inline-edit-rank-math-primary-term inline-edit-categories">
|
||||
<?php wp_nonce_field( 'rank-math-edit-primary-term', 'rank_math_bulk_edit_primary_term' ); ?>
|
||||
<label class="rank-math-primary-term">
|
||||
<span class="title">
|
||||
<?php // Translators: placeholder is taxonomy name, e.g. "Category". ?>
|
||||
<?php echo esc_html( sprintf( __( 'Primary %s', 'rank-math-pro' ), $taxonomy['singularLabel'] ) ); ?>
|
||||
</span>
|
||||
<span class="input-text-wrap rank-math-quick-edit-text-wrap">
|
||||
<?php
|
||||
wp_dropdown_categories(
|
||||
[
|
||||
'name' => 'rank_math_primary_term',
|
||||
'id' => 'rank_math_primary_term',
|
||||
'class' => '',
|
||||
'selected' => '0',
|
||||
'orderby' => 'name',
|
||||
'taxonomy' => $taxonomy['name'],
|
||||
'hide_empty' => false,
|
||||
'show_option_all' => false,
|
||||
'show_option_none' => __( '— Not Selected —', 'rank-math-pro' ),
|
||||
'option_none_value' => '0',
|
||||
]
|
||||
);
|
||||
?>
|
||||
</span>
|
||||
</label>
|
||||
</fieldset>
|
||||
<?php
|
||||
endif;
|
||||
endif;
|
||||
?>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
<?php
|
||||
break;
|
||||
|
||||
case 'rank_math_tax_seo_details':
|
||||
wp_nonce_field( 'rank-math-quick-edit', 'rank_math_quick_edit_nonce' );
|
||||
?>
|
||||
<div class="rank-math-quick-edit wp-clearfix inline-edit-row">
|
||||
<fieldset>
|
||||
<legend class="inline-edit-legend">
|
||||
<?php esc_html_e( 'SEO Settings', 'rank-math-pro' ); ?>
|
||||
</legend>
|
||||
<div class="inline-edit-col">
|
||||
<label>
|
||||
<span class="title"><?php esc_html_e( 'SEO Title', 'rank-math-pro' ); ?></span>
|
||||
<span class="input-text-wrap rank-math-quick-edit-text-wrap">
|
||||
<input type="text" name="rank_math_title" id="rank_math_title" value="">
|
||||
</span>
|
||||
</label>
|
||||
<label class="inline-edit-seo-description">
|
||||
<div><?php esc_html_e( 'SEO Description', 'rank-math-pro' ); ?></div>
|
||||
<textarea name="rank_math_description" id="rank_math_description"></textarea>
|
||||
</label>
|
||||
|
||||
<div class="inline-edit-robots-label"><?php esc_html_e( 'Robots Meta', 'rank-math-pro' ); ?></div>
|
||||
<ul class="cat-checklist category-checklist rank-math-robots-checklist">
|
||||
<?php foreach ( $robots as $val => $option ) : ?>
|
||||
<li id="rank_math_robots_<?php echo esc_attr( $val ); ?>" class="rank_math_robots">
|
||||
<label class="selectit">
|
||||
<input type="checkbox" name="rank_math_robots[]" id="rank_math_robots_<?php echo esc_attr( $val ); ?>_input" value="<?php echo esc_attr( $val ); ?>" checked="">
|
||||
<?php echo esc_html( $option ); ?>
|
||||
</label>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
|
||||
<label class="clear">
|
||||
<div class="title"><?php esc_html_e( 'Primary Focus Keyword', 'rank-math-pro' ); ?></div>
|
||||
<div class="rank-math-quick-edit-text-wrap">
|
||||
<input type="text" name="rank_math_focus_keyword" id="rank_math_focus_keyword" value="">
|
||||
</div>
|
||||
</label>
|
||||
<label class="clear">
|
||||
<div class="title"><?php esc_html_e( 'Canonical URL', 'rank-math-pro' ); ?></div>
|
||||
<div class="input-text-wrap rank-math-quick-edit-text-wrap">
|
||||
<input type="text" name="rank_math_canonical_url" id="rank_math_canonical_url" value="">
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
<?php
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add fields for the bulk edit row.
|
||||
* Just a wrapper for the quick_edit() method, since the fields are mostly the same.
|
||||
*
|
||||
* @param string $column Column name.
|
||||
* @return void
|
||||
*/
|
||||
public function bulk_edit( $column ) {
|
||||
$this->quick_edit( $column, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Save bulk edit data if needed.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function maybe_save_bulk_edit() {
|
||||
if ( ! Param::request( 'bulk_edit' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->save_bulk_edit( $_REQUEST ); // phpcs:ignore
|
||||
}
|
||||
|
||||
/**
|
||||
* Save bulk edit data.
|
||||
*
|
||||
* @param array $post_data Post data input.
|
||||
* @return void
|
||||
*/
|
||||
public function save_bulk_edit( $post_data ) {
|
||||
if ( empty( $post_data ) ) {
|
||||
$post_data = &$_POST; // phpcs:ignore
|
||||
}
|
||||
|
||||
if ( isset( $post_data['post_type'] ) ) {
|
||||
$ptype = get_post_type_object( $post_data['post_type'] );
|
||||
} else {
|
||||
$ptype = get_post_type_object( 'post' );
|
||||
}
|
||||
|
||||
if ( ! current_user_can( $ptype->cap->edit_posts ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! Helper::has_cap( 'onpage_general' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! $this->can_bulk_edit( $ptype ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$save_fields = [
|
||||
'title',
|
||||
'description',
|
||||
'robots',
|
||||
'primary_term',
|
||||
];
|
||||
|
||||
$post_ids = array_map( 'intval', (array) $post_data['post'] );
|
||||
foreach ( $post_ids as $post_id ) {
|
||||
foreach ( $save_fields as $field ) {
|
||||
$field_name = 'rank_math_' . $field;
|
||||
$field_value = isset( $post_data[ $field_name ] ) ? $post_data[ $field_name ] : '';
|
||||
if ( is_string( $field_value ) ) {
|
||||
$field_value = trim( $field_value );
|
||||
}
|
||||
|
||||
if ( empty( $field_value ) ) {
|
||||
// Skip if not set.
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( 'robots' === $field ) {
|
||||
$field_value = (array) $field_value;
|
||||
} elseif ( 'primary_term' === $field ) {
|
||||
$taxonomy = ProAdminHelper::get_primary_taxonomy( $post_id );
|
||||
$field_name = 'rank_math_primary_' . $taxonomy['name'];
|
||||
}
|
||||
|
||||
update_post_meta( $post_id, $field_name, $field_value );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save post quick edit.
|
||||
*
|
||||
* @param int $post_id Post ID.
|
||||
* @return mixed
|
||||
*/
|
||||
public function save_post( $post_id ) {
|
||||
if ( wp_is_post_revision( $post_id ) || ! wp_verify_nonce( Param::post( 'rank_math_quick_edit_nonce' ), 'rank-math-quick-edit' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! Helper::has_cap( 'onpage_general' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$post_type = get_post_type( $post_id );
|
||||
if ( ! $this->can_bulk_edit( $post_type ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$taxonomy = ProAdminHelper::get_primary_taxonomy( $post_id );
|
||||
|
||||
$save_fields = [
|
||||
'title',
|
||||
'description',
|
||||
'robots',
|
||||
'focus_keyword',
|
||||
'canonical_url',
|
||||
'primary_term',
|
||||
];
|
||||
|
||||
foreach ( $save_fields as $field ) {
|
||||
$field_name = 'rank_math_' . $field;
|
||||
$flag = [];
|
||||
if ( 'robots' === $field ) {
|
||||
$flag = FILTER_REQUIRE_ARRAY;
|
||||
}
|
||||
|
||||
$field_value = Param::post( $field_name, false, FILTER_DEFAULT, $flag );
|
||||
if ( false === $field_value ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$default_value = '';
|
||||
if ( $post_type ) {
|
||||
$default_value = Helper::get_settings( 'titles.pt_' . $post_type . '_' . $field );
|
||||
}
|
||||
|
||||
if ( 'robots' === $field ) {
|
||||
$field_value = array_filter( $field_value );
|
||||
$field_value = array_unique( $field_value );
|
||||
$field_value = array_intersect( $field_value, [ 'index', 'noindex', 'nofollow', 'noarchive', 'noimageindex', 'nosnippet' ] );
|
||||
} elseif ( 'canonical_url' === $field ) {
|
||||
$field_value = esc_url_raw( $field_value );
|
||||
} elseif ( 'focus_keyword' === $field ) {
|
||||
$current_value = get_post_meta( $post_id, $field_name, true );
|
||||
$current = Arr::from_string( $current_value );
|
||||
$keywords = Arr::from_string( $field_value );
|
||||
$current[0] = ! empty( $keywords ) ? $keywords[0] : '';
|
||||
if ( '' === $current[0] ) {
|
||||
array_shift( $current );
|
||||
}
|
||||
$field_value = join( ', ', $current );
|
||||
} elseif ( 'primary_term' === $field ) {
|
||||
if ( ! $field_value ) {
|
||||
delete_post_meta( $post_id, $field_name );
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( ! has_term( absint( $field_value ), $taxonomy['name'], $post_id ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$field_name = 'rank_math_primary_' . $taxonomy['name'];
|
||||
}
|
||||
|
||||
if ( empty( $field_value ) || $field_value === $default_value ) {
|
||||
delete_post_meta( $post_id, $field_name );
|
||||
continue;
|
||||
}
|
||||
|
||||
update_post_meta( $post_id, $field_name, $field_value );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save taxonomy term quick edit.
|
||||
*
|
||||
* @param int $term_id Term ID.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function save_tax( $term_id ) {
|
||||
$term_id = Param::post( 'tax_ID' );
|
||||
|
||||
if ( ! $term_id ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! wp_verify_nonce( Param::post( 'rank_math_quick_edit_nonce' ), 'rank-math-quick-edit' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! Helper::has_cap( 'onpage_general' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$save_fields = [
|
||||
'title',
|
||||
'description',
|
||||
'robots',
|
||||
'focus_keyword',
|
||||
'canonical_url',
|
||||
];
|
||||
|
||||
foreach ( $save_fields as $field ) {
|
||||
$field_name = 'rank_math_' . $field;
|
||||
$flag = [];
|
||||
if ( 'robots' === $field ) {
|
||||
$flag = FILTER_REQUIRE_ARRAY;
|
||||
}
|
||||
|
||||
$field_value = Param::post( $field_name, false, FILTER_DEFAULT, $flag );
|
||||
if ( false === $field_value ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( 'robots' === $field ) {
|
||||
$field_value = array_filter( $field_value );
|
||||
$field_value = array_unique( $field_value );
|
||||
$field_value = array_intersect( $field_value, [ 'index', 'noindex', 'nofollow', 'noarchive', 'noimageindex', 'nosnippet' ] );
|
||||
} elseif ( 'canonical_url' === $field ) {
|
||||
$field_value = esc_url_raw( $field_value );
|
||||
} elseif ( 'focus_keyword' === $field ) {
|
||||
$current = get_term_meta( $term_id, $field_name, true );
|
||||
$current = Arr::from_string( $current );
|
||||
$keywords = Arr::from_string( $field_value );
|
||||
$current[0] = ! empty( $keywords ) ? $keywords[0] : '';
|
||||
if ( '' === $current[0] ) {
|
||||
array_shift( $current );
|
||||
}
|
||||
$field_value = join( ', ', $current );
|
||||
}
|
||||
update_term_meta( $term_id, $field_name, $field_value );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if bulk editing is enabled for the current post type.
|
||||
*
|
||||
* @param string $ptype Post type name.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function can_bulk_edit( $ptype = null ) {
|
||||
global $post_type;
|
||||
if ( ! $ptype ) {
|
||||
$ptype = $post_type;
|
||||
}
|
||||
|
||||
if ( is_a( $ptype, 'WP_Post_Type' ) ) {
|
||||
$ptype = $ptype->name;
|
||||
}
|
||||
|
||||
$allow_editing = Helper::get_settings( 'titles.pt_' . $ptype . '_bulk_editing', true );
|
||||
if ( ! $allow_editing || 'readonly' === $allow_editing ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,302 @@
|
||||
<?php
|
||||
/**
|
||||
* Setup wizard.
|
||||
*
|
||||
* @since 1.0
|
||||
* @package RankMathPro
|
||||
* @subpackage RankMathPro\Admin
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Admin;
|
||||
|
||||
use RankMath\KB;
|
||||
use RankMath\Helper;
|
||||
use RankMath\Traits\Ajax;
|
||||
use RankMath\Traits\Hooker;
|
||||
use MyThemeShop\Helpers\Param;
|
||||
use MyThemeShop\Helpers\WordPress;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Trends tool class.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class Setup_Wizard {
|
||||
|
||||
use Hooker, Ajax;
|
||||
|
||||
/**
|
||||
* Register hooks.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->action( 'admin_init', 'enqueue', 20 );
|
||||
$this->action( 'rank_math/wizard/settings/compatibility', 'add_sw_custom_mode', 20 );
|
||||
$this->filter( 'rank_math/wizard/steps', 'steps' );
|
||||
|
||||
$this->ajax( 'import_settings', 'ajax_import_settings' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue assets.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function enqueue() {
|
||||
if ( Param::get( 'page' ) !== 'rank-math-wizard' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
wp_enqueue_style(
|
||||
'rank-math-pro-setup-wizard',
|
||||
RANK_MATH_PRO_URL . 'assets/admin/css/setup-wizard.css',
|
||||
null,
|
||||
rank_math_pro()->version
|
||||
);
|
||||
wp_enqueue_script(
|
||||
'rank-math-pro-setup-wizard',
|
||||
RANK_MATH_PRO_URL . 'assets/admin/js/setup-wizard.js',
|
||||
[ 'jquery' ],
|
||||
rank_math_pro()->version,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add custom option in Setup Wizard.
|
||||
*
|
||||
* @param CMB2 $cmb CMB instance.
|
||||
*/
|
||||
public function add_sw_custom_mode( $cmb ) {
|
||||
$field = $cmb->get_field( 'setup_mode' );
|
||||
if ( false !== $field ) {
|
||||
$import_html = '<div id="rank-math-custom-mode-form" class="hidden">';
|
||||
|
||||
$import_html .= '<div id="rank-math-custom-mode-form-initial">';
|
||||
$import_html .= '<input type="file" id="rank-math-custom-mode-file-field" value="" accept=".txt,.json">';
|
||||
$import_html .= '<button type="button" class="button button-primary button-small" id="rank-math-custom-mode-submit">' . __( 'Upload', 'rank-math-pro' ) . '</button>';
|
||||
$import_html .= '<p id="rank-math-custom-mode-import-help">';
|
||||
$import_html .= __( 'Select a Rank Math settings file on your computer and upload it to use the custom settings.', 'rank-math-pro' ) . ' ';
|
||||
// Translators: placeholder is a list of filetypes.
|
||||
$import_html .= sprintf( __( 'Allowed filetypes: %s', 'rank-math-pro' ), '<code>.txt, .json</code>' ) . ' ';
|
||||
$import_html .= '<a href="' . KB::get( 'import-export-settings', 'SW Import Settings Option' ) . '">' . __( 'More information', 'rank-math-pro' ) . '</a> ';
|
||||
$import_html .= '</p>';
|
||||
$import_html .= '</div>';
|
||||
|
||||
$import_html .= '<p id="rank-math-custom-mode-import-progress" class="hidden"><img src="' . esc_url( get_admin_url() . 'images/loading.gif' ) . '" /> ' . __( 'Uploading...', 'rank-math-pro' ) . '</p>';
|
||||
$import_html .= '<p id="rank-math-custom-mode-import-success" class="hidden">' . __( 'Import finished. In the next steps you can review the settings.', 'rank-math-pro' ) . '</p>';
|
||||
$import_html .= '<p id="rank-math-custom-mode-import-fail" class="hidden">' . __( 'Import failed.', 'rank-math-pro' ) . ' <span id="rank-math-custom-mode-import-message"></span></p>';
|
||||
|
||||
$import_html .= '</div>';
|
||||
|
||||
$field->args['options'] = [
|
||||
/* translators: Option Description */
|
||||
'easy' => '<div class="rank-math-mode-title">' . sprintf( __( 'Easy %s', 'rank-math-pro' ), '</div><p>' . __( 'For websites where you only want to change the basics and let Rank Math do most of the heavy lifting. Most settings are set to default as per industry best practices. One just has to set it and forget it.', 'rank-math-pro' ) . '</p>' ),
|
||||
/* translators: Option Description */
|
||||
'advanced' => '<div class="rank-math-mode-title">' . sprintf( __( 'Advanced %s', 'rank-math-pro' ), '</div><p>' . __( 'For the advanced users who want to control every SEO aspect of the website. You are offered options to change everything and have full control over the website’s SEO.', 'rank-math-pro' ) . '</p>' ),
|
||||
/* translators: Option Description */
|
||||
'custom' => '<div class="rank-math-mode-title">' . sprintf( __( 'Custom Mode %s', 'rank-math-pro' ), '</div><p class="rank-math-mode-description">' . __( 'Select this if you have a custom Rank Math settings file you want to use.', 'rank-math-pro' ) . '</p>' ) . $import_html,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax import settings.
|
||||
*/
|
||||
public function ajax_import_settings() {
|
||||
$this->verify_nonce( 'rank-math-ajax-nonce' );
|
||||
$this->has_cap_ajax( 'general' );
|
||||
|
||||
$file = $this->has_valid_import_file();
|
||||
if ( false === $file ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Parse Options.
|
||||
$wp_filesystem = WordPress::get_filesystem();
|
||||
if ( is_null( $wp_filesystem ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$settings = $wp_filesystem->get_contents( $file['file'] );
|
||||
$settings = json_decode( $settings, true );
|
||||
|
||||
\unlink( $file['file'] );
|
||||
|
||||
if ( is_array( $settings ) && $this->do_import_data( $settings ) ) {
|
||||
$this->success( __( 'Import successful.', 'rank-math-pro' ) );
|
||||
exit();
|
||||
}
|
||||
|
||||
$this->error( __( 'No settings found to be imported.', 'rank-math-pro' ) );
|
||||
exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add News/Video Sitemap in Setup Wizard.
|
||||
*
|
||||
* @param array $steps Wizard Steps.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function steps( $steps ) {
|
||||
if ( isset( $steps['sitemaps'] ) ) {
|
||||
$steps['sitemaps']['class'] = '\\RankMathPro\\Wizard\\Sitemap';
|
||||
}
|
||||
|
||||
return $steps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Import has valid file.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
private function has_valid_import_file() {
|
||||
if ( empty( $_FILES['import-me'] ) ) {
|
||||
$this->error( __( 'No file selected.', 'rank-math-pro' ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->filter( 'upload_mimes', 'allow_txt_upload' );
|
||||
$file = wp_handle_upload( $_FILES['import-me'], [ 'test_form' => false ] );
|
||||
$this->remove_filter( 'upload_mimes', 'allow_txt_upload', 10 );
|
||||
|
||||
if ( is_wp_error( $file ) ) {
|
||||
$this->error( __( 'Settings file could not be imported:', 'rank-math-pro' ) . ' ' . $file->get_error_message() );
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( isset( $file['error'] ) ) {
|
||||
$this->error( __( 'Settings could not be imported:', 'rank-math-pro' ) . ' ' . $file['error'] );
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $file['file'] ) ) {
|
||||
$this->error( __( 'Settings could not be imported: Upload failed.', 'rank-math-pro' ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow txt & json file upload.
|
||||
*
|
||||
* @param array $types Mime types keyed by the file extension regex corresponding to those types.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function allow_txt_upload( $types ) {
|
||||
$types['txt'] = 'text/plain';
|
||||
$types['json'] = 'application/json';
|
||||
|
||||
return $types;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does import data.
|
||||
*
|
||||
* @param array $data Import data.
|
||||
* @param bool $suppress_hooks Suppress hooks or not.
|
||||
* @return bool
|
||||
*/
|
||||
private function do_import_data( array $data, $suppress_hooks = false ) {
|
||||
$this->run_import_hooks( 'pre_import', $data, $suppress_hooks );
|
||||
|
||||
// Import options.
|
||||
$down = $this->import_set_options( $data );
|
||||
|
||||
// Import capabilities.
|
||||
if ( ! empty( $data['role-manager'] ) ) {
|
||||
$down = true;
|
||||
Helper::set_capabilities( $data['role-manager'] );
|
||||
}
|
||||
|
||||
// Import redirections.
|
||||
if ( ! empty( $data['redirections'] ) ) {
|
||||
$down = true;
|
||||
$this->import_set_redirections( $data['redirections'] );
|
||||
}
|
||||
|
||||
$this->run_import_hooks( 'after_import', $data, $suppress_hooks );
|
||||
|
||||
return $down;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set options from data.
|
||||
*
|
||||
* @param array $data An array of data.
|
||||
*/
|
||||
private function import_set_options( $data ) {
|
||||
$set = false;
|
||||
$hash = [
|
||||
'modules' => 'rank_math_modules',
|
||||
'general' => 'rank-math-options-general',
|
||||
'titles' => 'rank-math-options-titles',
|
||||
'sitemap' => 'rank-math-options-sitemap',
|
||||
];
|
||||
|
||||
foreach ( $hash as $key => $option_key ) {
|
||||
if ( ! empty( $data[ $key ] ) ) {
|
||||
$set = true;
|
||||
update_option( $option_key, $data[ $key ] );
|
||||
}
|
||||
}
|
||||
|
||||
return $set;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set redirections.
|
||||
*
|
||||
* @param array $redirections An array of redirections to import.
|
||||
*/
|
||||
private function import_set_redirections( $redirections ) {
|
||||
foreach ( $redirections as $key => $redirection ) {
|
||||
$matched = \RankMath\Redirections\DB::match_redirections_source( $redirection['sources'] );
|
||||
if ( ! empty( $matched ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$sources = maybe_unserialize( $redirection['sources'] );
|
||||
if ( ! is_array( $sources ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
\RankMath\Redirections\DB::add(
|
||||
[
|
||||
'url_to' => $redirection['url_to'],
|
||||
'sources' => $sources,
|
||||
'header_code' => $redirection['header_code'],
|
||||
'hits' => $redirection['hits'],
|
||||
'created' => $redirection['created'],
|
||||
'updated' => $redirection['updated'],
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run import hooks
|
||||
*
|
||||
* @param string $hook Hook to fire.
|
||||
* @param array $data Import data.
|
||||
* @param bool $suppress Suppress hooks or not.
|
||||
*/
|
||||
private function run_import_hooks( $hook, $data, $suppress ) {
|
||||
if ( ! $suppress ) {
|
||||
/**
|
||||
* Fires while importing settings.
|
||||
*
|
||||
* @since 0.9.0
|
||||
*
|
||||
* @param array $data Import data.
|
||||
*/
|
||||
$this->do_action( 'import/settings/' . $hook, $data );
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/**
|
||||
* Google Trends tool for the post editor.
|
||||
*
|
||||
* @since 1.0
|
||||
* @package RankMathPro
|
||||
* @subpackage RankMathPro\Admin
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Admin;
|
||||
|
||||
use RankMath\Helper;
|
||||
use RankMath\Traits\Hooker;
|
||||
use RankMath\Admin\Admin_Helper;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Trends tool class.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class Trends_Tool {
|
||||
|
||||
use Hooker;
|
||||
|
||||
/**
|
||||
* Register hooks.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->action( 'rank_math/admin/editor_scripts', 'editor_scripts', 20 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue assets for post/term/user editors.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function editor_scripts() {
|
||||
global $pagenow;
|
||||
if ( ! Admin_Helper::is_post_edit() && 'term.php' !== $pagenow && ! Admin_Helper::is_user_edit() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! wp_script_is( 'rank-math-editor' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
wp_enqueue_script(
|
||||
'rank-math-pro-editor',
|
||||
RANK_MATH_PRO_URL . 'assets/admin/js/gutenberg.js',
|
||||
[
|
||||
'jquery-ui-autocomplete',
|
||||
'rank-math-editor',
|
||||
],
|
||||
RANK_MATH_PRO_VERSION,
|
||||
true
|
||||
);
|
||||
wp_enqueue_style( 'rank-math-pro-editor', RANK_MATH_PRO_URL . 'assets/admin/css/gutenberg.css', [], RANK_MATH_PRO_VERSION );
|
||||
}
|
||||
}
|
@@ -0,0 +1,421 @@
|
||||
<?php
|
||||
/**
|
||||
* The admin-specific functionality of the plugin.
|
||||
*
|
||||
* @since 1.0
|
||||
* @package RankMathPro
|
||||
* @subpackage RankMathPro\Admin
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Admin\CSV_Import_Export;
|
||||
|
||||
use RankMath\Helper;
|
||||
use RankMath\Traits\Hooker;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* CSV Import Export class.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class CSV_Import_Export {
|
||||
|
||||
use Hooker;
|
||||
|
||||
/**
|
||||
* Register hooks.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->filter( 'rank_math/admin/import_export_panels', 'add_panel', 15 );
|
||||
$this->action( 'admin_enqueue_scripts', 'enqueue' );
|
||||
|
||||
$this->action( 'admin_init', 'maybe_do_import', 99 );
|
||||
$this->action( 'admin_init', 'maybe_do_export', 110 );
|
||||
$this->action( 'admin_init', 'maybe_cancel_import', 120 );
|
||||
|
||||
$this->action( 'wp_ajax_csv_import_progress', 'csv_import_progress' );
|
||||
|
||||
Import_Background_Process::get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add CSV import/export panel.
|
||||
*
|
||||
* @param array $panels Panels array.
|
||||
* @return array
|
||||
*/
|
||||
public function add_panel( $panels ) {
|
||||
// Insert after "import".
|
||||
$position = array_search( 'import', array_keys( $panels ), true ) + 1;
|
||||
$new = array_slice( $panels, 0, $position );
|
||||
$new['csv'] = [
|
||||
'view' => RANK_MATH_PRO_PATH . 'includes/views/csv-import-export-panel.php',
|
||||
'class' => 'import-export-csv',
|
||||
];
|
||||
$end = array_slice( $panels, $position );
|
||||
$result = array_merge( $new, $end );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if current screen is Status & Tools > Import / Export.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_import_export_screen() {
|
||||
return is_admin() && ! wp_doing_ajax() && isset( $_GET['page'] ) && 'rank-math-status' === $_GET['page'] && isset( $_GET['view'] ) && 'import_export' === $_GET['view']; // phpcs:ignore
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue styles.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function enqueue() {
|
||||
if ( ! $this->is_import_export_screen() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
Helper::add_json( 'confirmCsvImport', __( 'Are you sure you want to import meta data from this CSV file?', 'rank-math-pro' ) );
|
||||
Helper::add_json( 'confirmCsvCancel', __( 'Are you sure you want to stop the import process?', 'rank-math-pro' ) );
|
||||
Helper::add_json( 'csvProgressNonce', wp_create_nonce( 'rank_math_csv_progress' ) );
|
||||
|
||||
wp_enqueue_style( 'rank-math-pro-csv-import-export', RANK_MATH_PRO_URL . 'assets/admin/css/import-export.css', [], RANK_MATH_PRO_VERSION );
|
||||
wp_enqueue_script( 'rank-math-pro-csv-import-export', RANK_MATH_PRO_URL . 'assets/admin/js/import-export.js', [], RANK_MATH_PRO_VERSION, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add notice after import is started.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add_notice() {
|
||||
if ( ! $this->is_import_export_screen() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
Helper::add_notification( esc_html__( 'CSV import is in progress...', 'rank-math-pro' ), [ 'type' => 'success' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Start export if requested and allowed.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function maybe_do_export() {
|
||||
if ( ! is_admin() || empty( $_POST['rank_math_pro_csv_export'] ) ) {
|
||||
return;
|
||||
}
|
||||
if ( empty( $_POST['object_types'] ) || ! is_array( $_POST['object_types'] ) ) {
|
||||
wp_die( esc_html__( 'Please select at least one object type to export.', 'rank-math-pro' ) );
|
||||
}
|
||||
if ( ! wp_verify_nonce( isset( $_REQUEST['_wpnonce'] ) ? $_REQUEST['_wpnonce'] : '', 'rank_math_pro_csv_export' ) ) {
|
||||
wp_die( esc_html__( 'Invalid nonce.', 'rank-math-pro' ) );
|
||||
}
|
||||
if ( ! current_user_can( 'export' ) ) {
|
||||
wp_die( esc_html__( 'Sorry, you are not allowed to export the content of this site.', 'rank-math-pro' ) );
|
||||
}
|
||||
|
||||
$use_advanced_options = ! empty( $_POST['use_advanced_options'] );
|
||||
$advanced_options = [
|
||||
'post_types' => isset( $_POST['post_types'] ) && is_array( $_POST['post_types'] ) ? array_map( 'sanitize_title', wp_unslash( $_POST['post_types'] ) ) : [],
|
||||
'taxonomies' => isset( $_POST['taxonomies'] ) && is_array( $_POST['taxonomies'] ) ? array_map( 'sanitize_title', wp_unslash( $_POST['taxonomies'] ) ) : [],
|
||||
'roles' => isset( $_POST['roles'] ) && is_array( $_POST['roles'] ) ? array_map( 'sanitize_title', wp_unslash( $_POST['roles'] ) ) : [],
|
||||
'readonly_columns' => ! empty( $_POST['readonly_columns'] ),
|
||||
];
|
||||
|
||||
$exporter = new Exporter( array_map( 'sanitize_title', wp_unslash( $_POST['object_types'] ) ), $use_advanced_options ? $advanced_options : false );
|
||||
$exporter->process_export();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start import if requested and allowed.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function maybe_do_import() {
|
||||
if ( ! is_admin() || empty( $_POST['object_id'] ) || 'csv-import-plz' !== $_POST['object_id'] ) {
|
||||
return;
|
||||
}
|
||||
if ( empty( $_FILES['csv-import-me'] ) || empty( $_FILES['csv-import-me']['name'] ) ) {
|
||||
wp_die( esc_html__( 'Please select a file to import.', 'rank-math-pro' ) );
|
||||
}
|
||||
if ( ! wp_verify_nonce( isset( $_REQUEST['_wpnonce'] ) ? $_REQUEST['_wpnonce'] : '', 'rank_math_pro_csv_import' ) ) {
|
||||
wp_die( esc_html__( 'Invalid nonce.', 'rank-math-pro' ) );
|
||||
}
|
||||
if ( ! current_user_can( 'import' ) ) {
|
||||
wp_die( esc_html__( 'Sorry, you are not allowed to import contents to this site.', 'rank-math-pro' ) );
|
||||
}
|
||||
|
||||
// Rename file.
|
||||
$info = pathinfo( $_FILES['csv-import-me']['name'] );
|
||||
$_FILES['csv-import-me']['name'] = uniqid( 'rm-csv-' ) . ( ! empty( $info['extension'] ) ? '.' . $info['extension'] : '' );
|
||||
|
||||
// Handle file.
|
||||
$this->filter( 'upload_mimes', 'allow_csv_upload' );
|
||||
$file = wp_handle_upload( $_FILES['csv-import-me'], [ 'test_form' => false ] );
|
||||
$this->remove_filter( 'upload_mimes', 'allow_csv_upload', 10 );
|
||||
if ( ! $this->validate_file( $file ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$settings = [
|
||||
'no_overwrite' => ! empty( $_POST['no_overwrite'] ),
|
||||
];
|
||||
|
||||
$importer = new Importer();
|
||||
$importer->start( $file['file'], $settings );
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow CSV file upload.
|
||||
*
|
||||
* @param array $types Mime types keyed by the file extension regex corresponding to those types.
|
||||
* @return array
|
||||
*/
|
||||
public function allow_csv_upload( $types ) {
|
||||
$types['csv'] = 'text/csv';
|
||||
|
||||
return $types;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate file.
|
||||
*
|
||||
* @param mixed $file File array or object.
|
||||
* @return bool
|
||||
*/
|
||||
public function validate_file( $file ) {
|
||||
if ( is_wp_error( $file ) ) {
|
||||
Helper::add_notification( esc_html__( 'CSV could not be imported:', 'rank-math-pro' ) . ' ' . $file->get_error_message(), [ 'type' => 'error' ] );
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( isset( $file['error'] ) ) {
|
||||
Helper::add_notification( esc_html__( 'CSV could not be imported:', 'rank-math-pro' ) . ' ' . $file['error'], [ 'type' => 'error' ] );
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $file['file'] ) ) {
|
||||
Helper::add_notification( esc_html__( 'CSV could not be imported: Upload failed.', 'rank-math-pro' ), [ 'type' => 'error' ] );
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $file['type'] ) || 'text/csv' !== $file['type'] ) {
|
||||
\unlink( $file['file'] );
|
||||
Helper::add_notification( esc_html__( 'CSV could not be imported: File type error.', 'rank-math-pro' ), [ 'type' => 'error' ] );
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get import/export CSV columns.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_columns() {
|
||||
$columns = [
|
||||
'id',
|
||||
'object_type',
|
||||
'slug',
|
||||
'seo_title',
|
||||
'seo_description',
|
||||
'is_pillar_content',
|
||||
'focus_keyword',
|
||||
'seo_score',
|
||||
'robots',
|
||||
'advanced_robots',
|
||||
'canonical_url',
|
||||
'primary_term',
|
||||
'schema_data',
|
||||
'social_facebook_thumbnail',
|
||||
'social_facebook_title',
|
||||
'social_facebook_description',
|
||||
'social_twitter_thumbnail',
|
||||
'social_twitter_title',
|
||||
'social_twitter_description',
|
||||
];
|
||||
|
||||
if ( Helper::is_module_active( 'redirections' ) ) {
|
||||
$columns[] = 'redirect_to';
|
||||
$columns[] = 'redirect_type';
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter columns array.
|
||||
*/
|
||||
return apply_filters( 'rank_math/admin/csv_export_columns', $columns );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get object types.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_possible_object_types() {
|
||||
$object_types = [
|
||||
'post' => __( 'Posts', 'rank-math-pro' ),
|
||||
'term' => __( 'Terms', 'rank-math-pro' ),
|
||||
'user' => __( 'Users', 'rank-math-pro' ),
|
||||
];
|
||||
|
||||
/**
|
||||
* Filter object types array.
|
||||
*/
|
||||
return apply_filters( 'rank_math/admin/csv_export_object_types', $object_types );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if cancel request is valid.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function maybe_cancel_import() {
|
||||
if ( ! is_admin() || empty( $_GET['rank_math_cancel_csv_import'] ) ) {
|
||||
return;
|
||||
}
|
||||
if ( ! wp_verify_nonce( isset( $_REQUEST['_wpnonce'] ) ? $_REQUEST['_wpnonce'] : '', 'rank_math_pro_cancel_csv_import' ) ) {
|
||||
Helper::add_notification( esc_html__( 'Import could not be canceled: invalid nonce. Please try again.', 'rank-math-pro' ), [ 'type' => 'error' ] );
|
||||
wp_safe_redirect( remove_query_arg( 'rank_math_cancel_csv_import' ) );
|
||||
exit;
|
||||
}
|
||||
if ( ! current_user_can( 'import' ) ) {
|
||||
Helper::add_notification( esc_html__( 'Import could not be canceled: you are not allowed to import content to this site.', 'rank-math-pro' ), [ 'type' => 'error' ] );
|
||||
wp_safe_redirect( remove_query_arg( 'rank_math_cancel_csv_import' ) );
|
||||
exit;
|
||||
}
|
||||
|
||||
self::cancel_import();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel import.
|
||||
*
|
||||
* @param bool $silent Cancel silently.
|
||||
* @return void
|
||||
*/
|
||||
public static function cancel_import( $silent = false ) {
|
||||
$file_path = get_option( 'rank_math_csv_import' );
|
||||
|
||||
delete_option( 'rank_math_csv_import' );
|
||||
delete_option( 'rank_math_csv_import_total' );
|
||||
delete_option( 'rank_math_csv_import_status' );
|
||||
delete_option( 'rank_math_csv_import_settings' );
|
||||
Import_Background_Process::get()->cancel_process();
|
||||
|
||||
if ( ! $file_path ) {
|
||||
if ( ! $silent ) {
|
||||
Helper::add_notification( esc_html__( 'Import could not be canceled.', 'rank-math-pro' ), [ 'type' => 'error' ] );
|
||||
}
|
||||
|
||||
wp_safe_redirect( remove_query_arg( 'rank_math_cancel_csv_import' ) );
|
||||
exit;
|
||||
}
|
||||
|
||||
unlink( $file_path );
|
||||
if ( ! $silent ) {
|
||||
Helper::add_notification(
|
||||
__( 'CSV import canceled.', 'rank-math-pro' ),
|
||||
[
|
||||
'type' => 'success',
|
||||
'classes' => 'is-dismissible',
|
||||
]
|
||||
);
|
||||
}
|
||||
wp_safe_redirect( remove_query_arg( 'rank_math_cancel_csv_import' ) );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show import progress via AJAX.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function csv_import_progress() {
|
||||
check_ajax_referer( 'rank_math_csv_progress' );
|
||||
if ( ! current_user_can( 'import' ) ) {
|
||||
exit( '0' );
|
||||
}
|
||||
|
||||
self::import_progress_details();
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output import progress details.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function import_progress_details() {
|
||||
$import_in_progress = (bool) get_option( 'rank_math_csv_import' );
|
||||
if ( $import_in_progress ) {
|
||||
$total_lines = (int) get_option( 'rank_math_csv_import_total' );
|
||||
$remaining_items = Import_Background_Process::get()->count_remaining_items();
|
||||
$progress = $total_lines ? ( $total_lines - $remaining_items + 1 ) / $total_lines * 100 : 0;
|
||||
?>
|
||||
<p><?php esc_html_e( 'Import in progress...', 'rank-math-pro' ); ?></p>
|
||||
<p class="csv-import-status">
|
||||
<?php // Translators: placeholders represent count like 15/36. ?>
|
||||
<?php printf( esc_html__( 'Items processed: %1$s/%2$s', 'rank-math-pro' ), absint( min( $total_lines, $total_lines - $remaining_items + 1 ) ), absint( $total_lines ) ); ?>
|
||||
</p>
|
||||
<div id="csv-import-progress-bar">
|
||||
<div class="total">
|
||||
<div class="progress-bar" style="width: <?php echo absint( $progress ); ?>%;"></div>
|
||||
</div>
|
||||
<input type="hidden" id="csv-import-progress-value" value="<?php echo absint( $progress ); ?>">
|
||||
</div>
|
||||
<?php
|
||||
} else {
|
||||
$status = (array) get_option( 'rank_math_csv_import_status', [] );
|
||||
|
||||
$classes = 'import-finished';
|
||||
if ( ! empty( $status['errors'] ) ) {
|
||||
$classes .= ' import-errors';
|
||||
}
|
||||
|
||||
$message = self::get_import_complete_message();
|
||||
?>
|
||||
<p class="<?php echo esc_attr( $classes ); ?>"><?php echo wp_kses_post( $message ); ?></p>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get status message after import is complete.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_import_complete_message() {
|
||||
$status = (array) get_option( 'rank_math_csv_import_status', [] );
|
||||
$message = sprintf(
|
||||
// Translators: placeholder is the number of rows imported.
|
||||
__( 'CSV import completed. Successfully imported %d rows.', 'rank-math-pro' ),
|
||||
count( $status['imported_rows'] )
|
||||
);
|
||||
|
||||
if ( ! empty( $status['errors'] ) ) {
|
||||
$message = __( 'CSV import completed.', 'rank-math-pro' ) . ' ';
|
||||
$message .= sprintf(
|
||||
// Translators: placeholder is the number of rows imported.
|
||||
__( 'Imported %d rows.', 'rank-math-pro' ) . ' ',
|
||||
count( $status['imported_rows'] )
|
||||
);
|
||||
|
||||
if ( ! empty( $status['errors'] ) ) {
|
||||
$message .= __( 'One or more errors occured while importing: ', 'rank-math-pro' ) . '<br>';
|
||||
$message .= join( '<br>', $status['errors'] ) . '<br>';
|
||||
}
|
||||
if ( ! empty( $status['failed_rows'] ) ) {
|
||||
$message .= __( 'The following lines could not be imported: ', 'rank-math-pro' ) . '<br>';
|
||||
$message .= join( ', ', $status['failed_rows'] );
|
||||
}
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
}
|
@@ -0,0 +1,672 @@
|
||||
<?php
|
||||
/**
|
||||
* The CSV Export class.
|
||||
*
|
||||
* @since 1.0
|
||||
* @package RankMathPro
|
||||
* @subpackage RankMathPro\Admin
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Admin\CSV_Import_Export;
|
||||
|
||||
use RankMath\Helper;
|
||||
use RankMath\Traits\Hooker;
|
||||
use RankMath\Redirections\DB;
|
||||
use RankMath\Redirections\Cache;
|
||||
use RankMathPro\Admin\CSV;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* CSV Export.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class Exporter extends CSV {
|
||||
|
||||
use Hooker;
|
||||
|
||||
/**
|
||||
* Data
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $data = [];
|
||||
|
||||
/**
|
||||
* Term ID => slug cache.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $term_slugs = [];
|
||||
|
||||
/**
|
||||
* Not applicable placeholder.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $not_applicable_value = 'n/a';
|
||||
|
||||
/**
|
||||
* Object types we want to export.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $object_types = [];
|
||||
|
||||
/**
|
||||
* Use advanced options for export.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $use_advanced_options = false;
|
||||
|
||||
/**
|
||||
* Advanced options.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $advanced_options = [];
|
||||
|
||||
/**
|
||||
* Redirection cache.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $redirection = [];
|
||||
|
||||
/**
|
||||
* Columns.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $columns = [];
|
||||
|
||||
/**
|
||||
* Whether we need link counts.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $needs_link_count = false;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param mixed $object_types Object types to export.
|
||||
* @param mixed $advanced_options Options.
|
||||
* @return void
|
||||
*/
|
||||
public function __construct( $object_types, $advanced_options ) {
|
||||
$this->object_types = array_intersect( array_keys( CSV_Import_Export::get_possible_object_types() ), $object_types );
|
||||
$this->use_advanced_options = ! empty( $advanced_options );
|
||||
$this->advanced_options = $advanced_options;
|
||||
|
||||
if ( empty( $this->object_types ) ) {
|
||||
wp_die( esc_html__( 'Please select at least one object type to export.', 'rank-math-pro' ) );
|
||||
}
|
||||
|
||||
$this->not_applicable_value = apply_filters( 'rank_math/admin/csv_export_not_applicable', $this->not_applicable_value );
|
||||
|
||||
$this->needs_link_count = false;
|
||||
if ( $this->use_advanced_options && ! empty( $this->advanced_options['readonly_columns'] ) ) {
|
||||
if ( Helper::is_module_active( 'link-counter' ) ) {
|
||||
$this->needs_link_count = true;
|
||||
}
|
||||
|
||||
$this->filter( 'rank_math/admin/csv_export_columns', 'add_readonly_columns' );
|
||||
}
|
||||
|
||||
$this->columns = CSV_Import_Export::get_columns();
|
||||
}
|
||||
|
||||
/**
|
||||
* Do export.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function process_export() {
|
||||
$this->export(
|
||||
[
|
||||
'filename' => 'rank-math',
|
||||
'columns' => $this->columns,
|
||||
'items' => $this->get_items(),
|
||||
]
|
||||
);
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output column contents.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_items() {
|
||||
foreach ( $this->object_types as $object_type ) {
|
||||
$this->get_objects( $object_type );
|
||||
}
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get value for given column.
|
||||
*
|
||||
* @param string $column Column name.
|
||||
* @param object $object WP_Post, WP_Term or WP_User.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_column_value( $column, $object ) {
|
||||
global $wpdb;
|
||||
|
||||
$value = '';
|
||||
$object_type = 'post';
|
||||
if ( ! empty( $object->term_id ) ) {
|
||||
$object_type = 'term';
|
||||
} elseif ( ! empty( $object->user_login ) ) {
|
||||
$object_type = 'user';
|
||||
}
|
||||
|
||||
$table = "{$object_type}meta";
|
||||
$primary_column = "{$object_type}_id";
|
||||
$object_id = isset( $object->ID ) ? $object->ID : $object->$primary_column;
|
||||
|
||||
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
||||
$meta_rows = $wpdb->get_results(
|
||||
$wpdb->prepare(
|
||||
/* translators: %d: object id, %s: table name */
|
||||
"SELECT * FROM {$wpdb->$table} WHERE {$primary_column} = %d AND meta_key LIKE %s",
|
||||
$object_id,
|
||||
$wpdb->esc_like( 'rank_math_' ) . '%'
|
||||
)
|
||||
);
|
||||
// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
||||
$meta = $this->process_meta_rows( $meta_rows );
|
||||
|
||||
$internal_meta = (object) [];
|
||||
if ( 'post' === $object_type && $this->needs_link_count ) {
|
||||
$internal_meta = $this->get_link_counts( $object_id );
|
||||
}
|
||||
|
||||
if ( 'user' !== $object_type && in_array( $column, [ 'redirect_to', 'redirect_type' ], true ) ) {
|
||||
$redirection = $this->get_redirection( $object_type, $object_id );
|
||||
}
|
||||
|
||||
switch ( $column ) {
|
||||
case 'id':
|
||||
$value = $object_id;
|
||||
break;
|
||||
|
||||
case 'object_type':
|
||||
$value = $object_type;
|
||||
break;
|
||||
|
||||
case 'slug':
|
||||
$slug = '';
|
||||
if ( 'user' === $object_type ) {
|
||||
$slug = $object->user_nicename;
|
||||
} elseif ( 'post' === $object_type ) {
|
||||
$slug = $object->post_name;
|
||||
} elseif ( 'term' === $object_type ) {
|
||||
$slug = $object->slug;
|
||||
}
|
||||
$value = urldecode( $slug );
|
||||
break;
|
||||
|
||||
case 'seo_title':
|
||||
if ( isset( $meta['rank_math_title'] ) ) {
|
||||
$value = $meta['rank_math_title'];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'seo_description':
|
||||
if ( isset( $meta['rank_math_description'] ) ) {
|
||||
$value = $meta['rank_math_description'];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'is_pillar_content':
|
||||
$value = 'no';
|
||||
if ( in_array( $object_type, [ 'term', 'user' ], true ) ) {
|
||||
$value = $this->not_applicable_value;
|
||||
break;
|
||||
}
|
||||
if ( ! empty( $meta['rank_math_pillar_content'] ) ) {
|
||||
$value = 'yes';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'focus_keyword':
|
||||
if ( isset( $meta['rank_math_focus_keyword'] ) ) {
|
||||
$value = $meta['rank_math_focus_keyword'];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'seo_score':
|
||||
if ( isset( $meta['rank_math_seo_score'] ) ) {
|
||||
$value = $meta['rank_math_seo_score'];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'robots':
|
||||
if ( isset( $meta['rank_math_robots'] ) ) {
|
||||
$value = $this->process_robots( $meta['rank_math_robots'] );
|
||||
}
|
||||
break;
|
||||
|
||||
case 'advanced_robots':
|
||||
if ( isset( $meta['rank_math_advanced_robots'] ) ) {
|
||||
$value = $this->process_advanced_robots( $meta['rank_math_advanced_robots'] );
|
||||
}
|
||||
break;
|
||||
|
||||
case 'canonical_url':
|
||||
if ( isset( $meta['rank_math_canonical_url'] ) ) {
|
||||
$value = $meta['rank_math_canonical_url'];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'primary_term':
|
||||
if ( in_array( $object_type, [ 'term', 'user' ], true ) ) {
|
||||
$value = $this->not_applicable_value;
|
||||
break;
|
||||
}
|
||||
$value = $this->get_primary_term( $meta );
|
||||
break;
|
||||
|
||||
case 'schema_data':
|
||||
if ( in_array( $object_type, [ 'term', 'user' ], true ) ) {
|
||||
$value = $this->not_applicable_value;
|
||||
break;
|
||||
}
|
||||
$value = $this->process_schema_data( $meta );
|
||||
break;
|
||||
|
||||
case 'social_facebook_thumbnail':
|
||||
if ( isset( $meta['rank_math_facebook_image'] ) ) {
|
||||
$value = $meta['rank_math_facebook_image'];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'social_facebook_title':
|
||||
if ( isset( $meta['rank_math_facebook_title'] ) ) {
|
||||
$value = $meta['rank_math_facebook_title'];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'social_facebook_description':
|
||||
if ( isset( $meta['rank_math_facebook_description'] ) ) {
|
||||
$value = $meta['rank_math_facebook_description'];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'social_twitter_thumbnail':
|
||||
if ( empty( $meta['rank_math_twitter_use_facebook'] ) || 'on' !== $meta['rank_math_twitter_use_facebook'] ) {
|
||||
break;
|
||||
}
|
||||
if ( isset( $meta['rank_math_twitter_image'] ) ) {
|
||||
$value = $meta['rank_math_twitter_image'];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'social_twitter_title':
|
||||
if ( ! isset( $meta['rank_math_twitter_use_facebook'] ) || 'on' !== $meta['rank_math_twitter_use_facebook'] ) {
|
||||
break;
|
||||
}
|
||||
if ( isset( $meta['rank_math_twitter_title'] ) ) {
|
||||
$value = $meta['rank_math_twitter_title'];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'social_twitter_description':
|
||||
if ( ! isset( $meta['rank_math_twitter_use_facebook'] ) || 'on' !== $meta['rank_math_twitter_use_facebook'] ) {
|
||||
break;
|
||||
}
|
||||
if ( isset( $meta['rank_math_twitter_description'] ) ) {
|
||||
$value = $meta['rank_math_twitter_description'];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'redirect_to':
|
||||
if ( 'user' === $object_type ) {
|
||||
$value = $this->not_applicable_value;
|
||||
break;
|
||||
}
|
||||
if ( empty( $redirection['id'] ) ) {
|
||||
break;
|
||||
}
|
||||
$value = $redirection['url_to'];
|
||||
break;
|
||||
|
||||
case 'redirect_type':
|
||||
if ( 'user' === $object_type ) {
|
||||
$value = $this->not_applicable_value;
|
||||
break;
|
||||
}
|
||||
if ( empty( $redirection['id'] ) ) {
|
||||
break;
|
||||
}
|
||||
$value = $redirection['header_code'];
|
||||
break;
|
||||
|
||||
case 'internal_link_count':
|
||||
case 'external_link_count':
|
||||
case 'incoming_link_count':
|
||||
$value = $this->not_applicable_value;
|
||||
if ( isset( $internal_meta->$column ) ) {
|
||||
$value = $internal_meta->$column;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return $this->escape_csv( apply_filters( "rank_math/admin/csv_export_column_{$column}", $value, $object ) ); //phpcs:ignore
|
||||
}
|
||||
|
||||
/**
|
||||
* Get redirection for object.
|
||||
*
|
||||
* @param string $object_type Object type (post/term).
|
||||
* @param int $object_id Object ID.
|
||||
* @return array
|
||||
*/
|
||||
public function get_redirection( $object_type, $object_id ) {
|
||||
if ( isset( $this->redirection[ $object_id ] ) ) {
|
||||
return $this->redirection[ $object_id ];
|
||||
}
|
||||
$url = 'term' === $object_type ? get_term_link( (int) $object_id ) : get_permalink( $object_id );
|
||||
$url = wp_parse_url( $url, PHP_URL_PATH );
|
||||
$url = trim( $url, '/' );
|
||||
|
||||
$redirection = Cache::get_by_object_id( $object_id, $object_type );
|
||||
$redirection = $redirection ? DB::get_redirection_by_id( $redirection->redirection_id, 'active' ) : [
|
||||
'id' => '',
|
||||
'url_to' => '',
|
||||
'header_code' => Helper::get_settings( 'general.redirections_header_code' ),
|
||||
];
|
||||
|
||||
$this->redirection = [ $object_id => $redirection ];
|
||||
|
||||
return $redirection;
|
||||
}
|
||||
|
||||
/**
|
||||
* From DB format to key => value.
|
||||
*
|
||||
* @param array $rows Meta data rows from DB.
|
||||
* @return array
|
||||
*/
|
||||
public function process_meta_rows( $rows ) {
|
||||
$out = [];
|
||||
foreach ( $rows as $meta ) {
|
||||
$out[ $meta->meta_key ] = $meta->meta_value;
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* From DB format to CSV compatible.
|
||||
*
|
||||
* @param array $meta Robots meta value from DB.
|
||||
* @return string
|
||||
*/
|
||||
public function process_robots( $meta ) {
|
||||
$meta = maybe_unserialize( $meta );
|
||||
|
||||
return join( ',', $meta );
|
||||
}
|
||||
|
||||
/**
|
||||
* From DB format to CSV compatible.
|
||||
*
|
||||
* @param array $meta Robots meta value from DB.
|
||||
* @return string
|
||||
*/
|
||||
public function process_advanced_robots( $meta ) {
|
||||
$meta = maybe_unserialize( $meta );
|
||||
|
||||
return http_build_query( $meta, '', ', ' );
|
||||
}
|
||||
|
||||
/**
|
||||
* From DB format to JSON-encoded.
|
||||
*
|
||||
* @param array $metadata Schema data meta value from DB.
|
||||
* @return string
|
||||
*/
|
||||
public function process_schema_data( $metadata ) {
|
||||
$output = [];
|
||||
$schema_data = $this->filter_schema_meta( $metadata );
|
||||
|
||||
if ( empty( $schema_data ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
foreach ( $schema_data as $meta_key => $meta_value ) {
|
||||
$name = substr( $meta_key, 17 );
|
||||
$meta_value = maybe_unserialize( $meta_value );
|
||||
|
||||
if ( $name ) {
|
||||
$output[ $name ] = $meta_value;
|
||||
}
|
||||
}
|
||||
|
||||
return wp_json_encode( $output, JSON_UNESCAPED_SLASHES );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the rank_math_schema_* post meta values from all the values.
|
||||
*
|
||||
* @param array $metadata Schema data meta value from DB.
|
||||
* @return array
|
||||
*/
|
||||
private function filter_schema_meta( $metadata ) {
|
||||
$found = [];
|
||||
foreach ( $metadata as $meta_key => $meta_value ) {
|
||||
if ( substr( $meta_key, 0, 17 ) === 'rank_math_schema_' ) {
|
||||
$found[ $meta_key ] = $meta_value;
|
||||
}
|
||||
}
|
||||
return $found;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get primary term for given object.
|
||||
*
|
||||
* @param mixed $meta Processed meta data.
|
||||
* @return string
|
||||
*/
|
||||
public function get_primary_term( $meta ) {
|
||||
if ( empty( $meta['rank_math_primary_category'] ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $this->get_term_slug( $meta['rank_math_primary_category'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all post IDs.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_post_ids() {
|
||||
global $wpdb;
|
||||
|
||||
$where = $this->get_posts_where();
|
||||
|
||||
$post_ids = $wpdb->get_col( "SELECT ID FROM {$wpdb->posts} WHERE $where" ); // phpcs:ignore
|
||||
return $post_ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all term IDs.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_term_ids() {
|
||||
global $wpdb;
|
||||
$taxonomies = Helper::get_allowed_taxonomies();
|
||||
|
||||
if ( $this->use_advanced_options ) {
|
||||
if ( empty( $this->advanced_options['taxonomies'] ) ) {
|
||||
return [];
|
||||
}
|
||||
$taxonomies = $this->advanced_options['taxonomies'];
|
||||
}
|
||||
|
||||
$term_ids = get_terms(
|
||||
[
|
||||
'taxonomy' => $taxonomies,
|
||||
'fields' => 'ids',
|
||||
'hide_empty' => false,
|
||||
]
|
||||
);
|
||||
|
||||
return $term_ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all user IDs.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_user_ids() {
|
||||
$args = [ 'fields' => [ 'ID' ] ];
|
||||
if ( $this->use_advanced_options ) {
|
||||
if ( empty( $this->advanced_options['roles'] ) ) {
|
||||
return [];
|
||||
}
|
||||
$args['role__in'] = $this->advanced_options['roles'];
|
||||
}
|
||||
|
||||
$user_ids = get_users( $args );
|
||||
return wp_list_pluck( $user_ids, 'ID' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Export all items of specified object type. Output column values.
|
||||
*
|
||||
* @param string $object_type Object type to export.
|
||||
* @return array
|
||||
*/
|
||||
public function get_objects( $object_type ) {
|
||||
global $wpdb;
|
||||
$object_type_plural = $object_type . 's';
|
||||
// get_post_ids, get_term_ids, get_user_ids.
|
||||
$method = "get_{$object_type}_ids";
|
||||
$ids = $this->$method();
|
||||
if ( ! $ids ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$primary_column = 'ID';
|
||||
if ( 'term' === $object_type ) {
|
||||
$primary_column = "{$object_type}_id";
|
||||
}
|
||||
|
||||
$cols = $this->columns;
|
||||
|
||||
// Fetch 50 at a time rather than loading the entire table into memory.
|
||||
while ( $next_batch = array_splice( $ids, 0, 50 ) ) { // phpcs:ignore
|
||||
$where = 'WHERE ' . $primary_column . ' IN (' . join( ',', $next_batch ) . ')';
|
||||
|
||||
$objects = $wpdb->get_results( "SELECT * FROM {$wpdb->$object_type_plural} $where" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
||||
$current_object = 0;
|
||||
|
||||
// Begin Loop.
|
||||
foreach ( $objects as $object ) {
|
||||
$current_object++;
|
||||
$current_col = 0;
|
||||
$columns = [];
|
||||
foreach ( $cols as $column ) {
|
||||
$current_col++;
|
||||
$columns[] = $this->get_column_value( $column, $object ); // phpcs:ignore
|
||||
}
|
||||
$this->data[] = $columns;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get WHERE for post types.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function get_posts_where() {
|
||||
global $wpdb;
|
||||
|
||||
$post_types = Helper::get_allowed_post_types();
|
||||
if ( $this->use_advanced_options ) {
|
||||
if ( empty( $this->advanced_options['post_types'] ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$post_types = $this->advanced_options['post_types'];
|
||||
}
|
||||
|
||||
$esses = array_fill( 0, count( $post_types ), '%s' );
|
||||
|
||||
$where = $wpdb->prepare( "{$wpdb->posts}.post_type IN (" . implode( ',', $esses ) . ')', $post_types ); // phpcs:ignore
|
||||
|
||||
$where .= " AND {$wpdb->posts}.post_status != 'auto-draft'";
|
||||
|
||||
return $where;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get slug from term ID.
|
||||
*
|
||||
* @param int $term_id Term ID.
|
||||
* @return string
|
||||
*/
|
||||
public function get_term_slug( $term_id ) {
|
||||
if ( isset( $this->term_slugs[ $term_id ] ) ) {
|
||||
return $this->term_slugs[ $term_id ];
|
||||
}
|
||||
global $wpdb;
|
||||
$where = 'term_id = ' . absint( $term_id ) . '';
|
||||
$this->term_slugs[ $term_id ] = $wpdb->get_var( "SELECT slug FROM {$wpdb->terms} WHERE $where" ); // phpcs:ignore
|
||||
|
||||
return $this->term_slugs[ $term_id ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Add read-only columns.
|
||||
*
|
||||
* @param array $columns Columns.
|
||||
* @return array
|
||||
*/
|
||||
public function add_readonly_columns( $columns ) {
|
||||
$columns[] = 'seo_score';
|
||||
if ( $this->needs_link_count ) {
|
||||
$columns[] = 'internal_link_count';
|
||||
$columns[] = 'external_link_count';
|
||||
$columns[] = 'incoming_link_count';
|
||||
}
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get post link counts.
|
||||
*
|
||||
* @param int $post_id Post ID.
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public function get_link_counts( $post_id ) {
|
||||
global $wpdb;
|
||||
|
||||
$counts = $wpdb->get_row( "SELECT * FROM {$wpdb->prefix}rank_math_internal_meta WHERE object_id = {$post_id}" ); // phpcs:ignore
|
||||
$counts = ! empty( $counts ) ? $counts : (object) [
|
||||
'internal_link_count' => '',
|
||||
'external_link_count' => '',
|
||||
'incoming_link_count' => '',
|
||||
];
|
||||
|
||||
return $counts;
|
||||
}
|
||||
}
|
@@ -0,0 +1,170 @@
|
||||
<?php
|
||||
/**
|
||||
* The CSV Import class.
|
||||
*
|
||||
* @since 1.0
|
||||
* @package RankMathPro
|
||||
* @subpackage RankMathPro\Admin
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Admin\CSV_Import_Export;
|
||||
|
||||
use RankMath\Helper;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* CSV Import Export class.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class Import_Background_Process extends \WP_Background_Process {
|
||||
|
||||
/**
|
||||
* Prefix.
|
||||
*
|
||||
* (default value: 'wp')
|
||||
*
|
||||
* @var string
|
||||
* @access protected
|
||||
*/
|
||||
protected $prefix = 'rank_math';
|
||||
|
||||
/**
|
||||
* Action.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $action = 'csv_import';
|
||||
|
||||
/**
|
||||
* Importer instance.
|
||||
*
|
||||
* @var Importer
|
||||
*/
|
||||
private $importer;
|
||||
|
||||
/**
|
||||
* Main instance.
|
||||
*
|
||||
* Ensure only one instance is loaded or can be loaded.
|
||||
*
|
||||
* @return Import_Background_Process
|
||||
*/
|
||||
public static function get() {
|
||||
static $instance;
|
||||
|
||||
if ( is_null( $instance ) || ! ( $instance instanceof Import_Background_Process ) ) {
|
||||
$instance = new Import_Background_Process();
|
||||
}
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start creating batches.
|
||||
*
|
||||
* @param [type] $posts [description].
|
||||
*/
|
||||
public function start( $lines_number ) {
|
||||
$chunks = array_chunk( range( 0, $lines_number ), apply_filters( 'rank_math/admin/csv_import_chunk_size', 100 ) );
|
||||
foreach ( $chunks as $chunk ) {
|
||||
$this->push_to_queue( $chunk );
|
||||
}
|
||||
|
||||
Helper::add_notification(
|
||||
sprintf(
|
||||
// Translators: placeholders are opening and closing tags for link.
|
||||
__( 'CSV import in progress. You can see its progress and cancel it in the %1$sImport & Export panel%2$s.', 'rank-math-pro' ),
|
||||
'<a href="' . esc_url( Helper::get_admin_url( 'status', [ 'view' => 'import_export' ] ) ) . '">',
|
||||
'</a>'
|
||||
),
|
||||
[
|
||||
'type' => 'success',
|
||||
'classes' => 'is-dismissible',
|
||||
]
|
||||
);
|
||||
|
||||
$this->save()->dispatch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Task.
|
||||
*
|
||||
* Override this method to perform any actions required on each
|
||||
* queue item. Return the modified item for further processing
|
||||
* in the next pass through. Or, return false to remove the
|
||||
* item from the queue.
|
||||
*
|
||||
* @param mixed $item Queue item to iterate over.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function task( $item ) {
|
||||
try {
|
||||
$this->importer = new Importer();
|
||||
foreach ( $item as $row ) {
|
||||
$this->importer->import_line( $row );
|
||||
}
|
||||
$this->importer->batch_done( $item );
|
||||
return false;
|
||||
} catch ( \Exception $error ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Import complete. Clear options & add notification.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function complete() {
|
||||
unlink( get_option( 'rank_math_csv_import' ) );
|
||||
delete_option( 'rank_math_csv_import' );
|
||||
delete_option( 'rank_math_csv_import_total' );
|
||||
delete_option( 'rank_math_csv_import_settings' );
|
||||
|
||||
$status = (array) get_option( 'rank_math_csv_import_status', [] );
|
||||
|
||||
$notification_args = [
|
||||
'type' => 'success',
|
||||
'classes' => 'is-dismissible',
|
||||
];
|
||||
|
||||
if ( ! empty( $status['errors'] ) ) {
|
||||
$notification_args = [
|
||||
'type' => 'error',
|
||||
'classes' => 'is-dismissible',
|
||||
];
|
||||
}
|
||||
|
||||
Helper::add_notification(
|
||||
CSV_Import_Export::get_import_complete_message(),
|
||||
$notification_args
|
||||
);
|
||||
|
||||
parent::complete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Count remaining items in batch.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function count_remaining_items() {
|
||||
if ( $this->is_queue_empty() ) {
|
||||
// This fixes an issue where get_batch() runs too early and results in a PHP notice.
|
||||
return get_option( 'rank_math_csv_import_total' );
|
||||
}
|
||||
$batch = $this->get_batch();
|
||||
$count = 0;
|
||||
if ( ! empty( $batch->data ) && is_array( $batch->data ) ) {
|
||||
foreach ( $batch->data as $items ) {
|
||||
$count += count( $items );
|
||||
}
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
}
|
@@ -0,0 +1,777 @@
|
||||
<?php
|
||||
/**
|
||||
* The CSV Import class.
|
||||
*
|
||||
* @since 1.0
|
||||
* @package RankMathPro
|
||||
* @subpackage RankMathPro\Admin
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Admin\CSV_Import_Export;
|
||||
|
||||
use RankMath\Helper;
|
||||
use RankMath\Redirections\DB;
|
||||
use RankMath\Redirections\Cache;
|
||||
use RankMath\Redirections\Redirection;
|
||||
use MyThemeShop\Helpers\Arr;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* CSV Importer class.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class Import_Row {
|
||||
|
||||
/**
|
||||
* Row data.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $data = [];
|
||||
|
||||
/**
|
||||
* Import settings.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $settings = [];
|
||||
|
||||
/**
|
||||
* Columns.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $columns = [];
|
||||
|
||||
/**
|
||||
* Redirection.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $redirection = [];
|
||||
|
||||
/**
|
||||
* Object URI.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $object_uri = '';
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $data Row data.
|
||||
* @param array $settings Import settings.
|
||||
* @return void
|
||||
*/
|
||||
public function __construct( $data, $settings ) {
|
||||
$this->data = $data;
|
||||
$this->settings = $settings;
|
||||
|
||||
foreach ( $this->data as $key => $value ) {
|
||||
// Skip empty or n/a.
|
||||
if ( empty( $value ) || $this->is_not_applicable( $value ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$clear_method = "clear_{$key}";
|
||||
if ( $this->is_clear_command( $value ) && method_exists( $this, $clear_method ) ) {
|
||||
$this->$clear_method();
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( $this->settings['no_overwrite'] ) {
|
||||
$is_empty_method = "is_empty_{$key}";
|
||||
if ( ! method_exists( $this, $is_empty_method ) || ! $this->$is_empty_method() ) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$import_method = "import_{$key}";
|
||||
if ( method_exists( $this, $import_method ) ) {
|
||||
$this->$import_method( $value );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Do custom action after importing a row.
|
||||
*/
|
||||
do_action( 'rank_math/admin/csv_import_row', $data, $settings, $this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if given column value is empty or not applicable.
|
||||
*
|
||||
* @param mixed $value Column value.
|
||||
* @return bool
|
||||
*/
|
||||
public function is_not_applicable( $value ) {
|
||||
return $value === $this->settings['not_applicable_value'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if given column value is the delete command.
|
||||
*
|
||||
* @param mixed $value Column value.
|
||||
* @return bool
|
||||
*/
|
||||
public function is_clear_command( $value ) {
|
||||
return $value === $this->settings['clear_command'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic getter.
|
||||
*
|
||||
* Return column value if is set and column name is in allowed columns list.
|
||||
*
|
||||
* @param string $property Property we want to get.
|
||||
* @return string
|
||||
*/
|
||||
public function __get( $property ) {
|
||||
if ( in_array( $property, $this->get_columns(), true ) && isset( $this->data[ $property ] ) ) {
|
||||
return $this->data[ $property ];
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get CSV columns.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_columns() {
|
||||
if ( ! empty( $this->columns ) ) {
|
||||
return $this->columns;
|
||||
}
|
||||
$this->columns = CSV_Import_Export::get_columns();
|
||||
|
||||
return $this->columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear SEO Title column.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clear_seo_title() {
|
||||
$this->delete_meta( 'title' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear SEO Description column.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clear_seo_description() {
|
||||
$this->delete_meta( 'description' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear Focus Keyword column.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clear_focus_keyword() {
|
||||
$this->delete_meta( 'focus_keyword' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear Robots column.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clear_robots() {
|
||||
$this->delete_meta( 'robots' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear Advanced Robots column.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clear_advanced_robots() {
|
||||
$this->delete_meta( 'advanced_robots' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear Canonical URL column.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clear_canonical_url() {
|
||||
$this->delete_meta( 'canonical_url' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear Primary Term column.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clear_primary_term() {
|
||||
$this->delete_meta( 'primary_category' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear Schema Data column. Schema data must be valid JSON.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clear_schema_data() {
|
||||
$current_meta = $this->get_meta();
|
||||
foreach ( $current_meta as $key => $value ) {
|
||||
if ( substr( $key, 0, 17 ) === 'rank_math_schema_' ) {
|
||||
// Cut off "rank_math_" prefix.
|
||||
$this->delete_meta( substr( $key, 10 ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear FB Thumbnail column.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clear_social_facebook_thumbnail() {
|
||||
$this->delete_meta( 'facebook_image' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear FB Title column.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clear_social_facebook_title() {
|
||||
$this->delete_meta( 'facebook_title' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear FB Description column.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clear_social_facebook_description() {
|
||||
$this->delete_meta( 'facebook_description' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear Twitter Thumbnail column.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clear_social_twitter_thumbnail() {
|
||||
$this->delete_meta( 'twitter_image' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear Twitter Title column.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clear_social_twitter_title() {
|
||||
$this->delete_meta( 'twitter_title' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear Twitter Description column.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clear_social_twitter_description() {
|
||||
$this->delete_meta( 'twitter_description' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear Redirection URL column. Only if 'redirect_type' column is set, too.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clear_redirect_to() {
|
||||
if ( ! $this->is_empty_redirect_to() ) {
|
||||
DB::delete( $this->get_redirection()['id'] );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Import slug column.
|
||||
*
|
||||
* @param string $value Column value.
|
||||
* @return void
|
||||
*/
|
||||
public function import_slug( $value ) {
|
||||
switch ( $this->object_type ) {
|
||||
case 'post':
|
||||
wp_update_post(
|
||||
[
|
||||
'ID' => $this->id,
|
||||
'post_name' => $value,
|
||||
]
|
||||
);
|
||||
break;
|
||||
|
||||
case 'term':
|
||||
global $wpdb;
|
||||
$wpdb->update(
|
||||
$wpdb->terms,
|
||||
[ 'slug' => sanitize_title( $value ) ], // Update.
|
||||
[ 'term_id' => sanitize_title( $value ) ], // Where.
|
||||
[ '%s' ], // Format.
|
||||
[ '%d' ] // Where format.
|
||||
);
|
||||
break;
|
||||
|
||||
case 'user':
|
||||
update_user_meta( $this->id, 'rank_math_permalink', $value );
|
||||
break;
|
||||
}
|
||||
|
||||
// Refresh URI.
|
||||
$this->get_object_uri( true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Import SEO Title column.
|
||||
*
|
||||
* @param string $value Column value.
|
||||
* @return void
|
||||
*/
|
||||
public function import_seo_title( $value ) {
|
||||
$this->update_meta( 'title', $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Import SEO Description column.
|
||||
*
|
||||
* @param string $value Column value.
|
||||
* @return void
|
||||
*/
|
||||
public function import_seo_description( $value ) {
|
||||
$this->update_meta( 'description', $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Import Is Pillar Content column.
|
||||
*
|
||||
* @param string $value Column value.
|
||||
* @return void
|
||||
*/
|
||||
public function import_is_pillar_content( $value ) {
|
||||
$lcvalue = strtolower( $value );
|
||||
if ( 'yes' === $lcvalue ) {
|
||||
$this->update_meta( 'pillar_content', 'on' );
|
||||
} elseif ( 'no' === $lcvalue ) {
|
||||
$this->delete_meta( 'pillar_content' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Import Focus Keyword column.
|
||||
*
|
||||
* @param string $value Column value.
|
||||
* @return void
|
||||
*/
|
||||
public function import_focus_keyword( $value ) {
|
||||
$this->update_meta( 'focus_keyword', $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Import Robots column.
|
||||
*
|
||||
* @param string $value Column value.
|
||||
* @return void
|
||||
*/
|
||||
public function import_robots( $value ) {
|
||||
$this->update_meta( 'robots', Arr::from_string( $value ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Import Advanced Robots column.
|
||||
*
|
||||
* @param string $value Column value.
|
||||
* @return void
|
||||
*/
|
||||
public function import_advanced_robots( $value ) {
|
||||
$robots = [];
|
||||
$robots_rules = Arr::from_string( $value );
|
||||
foreach ( $robots_rules as $robots_rule ) {
|
||||
$parts = Arr::from_string( $robots_rule, '=' );
|
||||
if ( count( $parts ) === 2 ) {
|
||||
$robots[ $parts[0] ] = $parts[1];
|
||||
}
|
||||
}
|
||||
|
||||
$this->update_meta( 'advanced_robots', $robots );
|
||||
}
|
||||
|
||||
/**
|
||||
* Import Canonical URL column.
|
||||
*
|
||||
* @param string $value Column value.
|
||||
* @return void
|
||||
*/
|
||||
public function import_canonical_url( $value ) {
|
||||
$this->update_meta( 'canonical_url', $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Import Primary Term column.
|
||||
*
|
||||
* @param string $value Column value.
|
||||
* @return void
|
||||
*/
|
||||
public function import_primary_term( $value ) {
|
||||
$term_id = Importer::get_term_id( $value );
|
||||
if ( ! $term_id ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->update_meta( 'primary_category', $term_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Import Schema Data column. Schema data must be valid JSON.
|
||||
*
|
||||
* @param string $value Column value.
|
||||
* @return void
|
||||
*/
|
||||
public function import_schema_data( $value ) {
|
||||
$value = json_decode( $value, true );
|
||||
if ( ! $value ) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( $value as $key => $value ) {
|
||||
$meta_key = 'schema_' . $key;
|
||||
$this->update_meta( $meta_key, $value );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Import FB Thumbnail column.
|
||||
*
|
||||
* @param string $value Column value.
|
||||
* @return void
|
||||
*/
|
||||
public function import_social_facebook_thumbnail( $value ) {
|
||||
$this->update_meta( 'facebook_image', $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Import FB Title column.
|
||||
*
|
||||
* @param string $value Column value.
|
||||
* @return void
|
||||
*/
|
||||
public function import_social_facebook_title( $value ) {
|
||||
$this->update_meta( 'facebook_title', $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Import FB Description column.
|
||||
*
|
||||
* @param string $value Column value.
|
||||
* @return void
|
||||
*/
|
||||
public function import_social_facebook_description( $value ) {
|
||||
$this->update_meta( 'facebook_description', $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Import Twitter Thumbnail column.
|
||||
*
|
||||
* @param string $value Column value.
|
||||
* @return void
|
||||
*/
|
||||
public function import_social_twitter_thumbnail( $value ) {
|
||||
$this->update_meta( 'twitter_image', $value );
|
||||
$this->update_meta( 'twitter_use_facebook', 'off' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Import Twitter Title column.
|
||||
*
|
||||
* @param string $value Column value.
|
||||
* @return void
|
||||
*/
|
||||
public function import_social_twitter_title( $value ) {
|
||||
$this->update_meta( 'twitter_title', $value );
|
||||
$this->update_meta( 'twitter_use_facebook', 'off' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Import Twitter Description column.
|
||||
*
|
||||
* @param string $value Column value.
|
||||
* @return void
|
||||
*/
|
||||
public function import_social_twitter_description( $value ) {
|
||||
$this->update_meta( 'twitter_description', $value );
|
||||
$this->update_meta( 'twitter_use_facebook', 'off' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Import Redirection URL column. Only if 'redirect_type' column is set, too.
|
||||
*
|
||||
* @param string $value Column value.
|
||||
* @return void
|
||||
*/
|
||||
public function import_redirect_to( $value ) {
|
||||
if ( empty( $this->data['redirect_type'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! $this->is_empty_redirect_to() ) {
|
||||
DB::delete( $this->get_redirection()['id'] );
|
||||
}
|
||||
|
||||
$redirection = Redirection::from(
|
||||
[
|
||||
'id' => '',
|
||||
'url_to' => $this->redirect_to,
|
||||
'sources' => [
|
||||
[
|
||||
'pattern' => $this->get_object_uri(),
|
||||
'comparison' => 'exact',
|
||||
],
|
||||
],
|
||||
'header_code' => $this->redirect_type,
|
||||
]
|
||||
);
|
||||
$redirection->set_nocache( true );
|
||||
$redirection->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if empty: SEO Title
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_empty_seo_title() {
|
||||
return ! $this->get_meta( 'title' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if empty: SEO Description
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_empty_seo_description() {
|
||||
return ! $this->get_meta( 'description' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if empty: Is Pillar Content column.
|
||||
* We return true so this will always be overwritten.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_empty_is_pillar_content() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if empty: Focus Keyword column.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_empty_focus_keyword() {
|
||||
return ! $this->get_meta( 'focus_keyword' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if empty: Robots column.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_empty_robots() {
|
||||
return empty( $this->get_meta( 'robots' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if empty: Advanced Robots column.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_empty_advanced_robots() {
|
||||
return empty( $this->get_meta( 'advanced_robots' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if empty: Canonical URL column.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_empty_canonical_url() {
|
||||
return ! $this->get_meta( 'canonical_url' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if empty: Primary Term column.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_empty_primary_term() {
|
||||
return empty( $this->get_meta( 'primary_category' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if empty: Schema Data column.
|
||||
* We return true so this will always be overwritten.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_empty_schema_data() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if empty: FB Thumbnail column.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_empty_social_facebook_thumbnail() {
|
||||
return ! $this->get_meta( 'facebook_image' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if empty: FB Title column.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_empty_social_facebook_title() {
|
||||
return ! $this->get_meta( 'facebook_title' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if empty: FB Description column.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_empty_social_facebook_description() {
|
||||
return ! $this->get_meta( 'facebook_description' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if empty: Twitter Thumbnail column.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_empty_social_twitter_thumbnail() {
|
||||
return ! $this->get_meta( 'twitter_image' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if empty: Twitter Title column.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_empty_social_twitter_title() {
|
||||
return ! $this->get_meta( 'twitter_title' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if empty: Twitter Description column.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_empty_social_twitter_description() {
|
||||
return ! $this->get_meta( 'twitter_description' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if empty: Redirect URL.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_empty_redirect_to() {
|
||||
return ! (bool) $this->get_redirection()['id'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get redirection for object.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function get_redirection() {
|
||||
if ( isset( $this->redirection ) ) {
|
||||
return $this->redirection;
|
||||
}
|
||||
$object_type = $this->object_type;
|
||||
$object_id = $this->id;
|
||||
|
||||
$this->get_object_uri();
|
||||
|
||||
$redirection = Cache::get_by_object_id( $object_id, $object_type );
|
||||
$redirection = $redirection ? DB::get_redirection_by_id( $redirection->redirection_id, 'active' ) : [
|
||||
'id' => '',
|
||||
'url_to' => '',
|
||||
'header_code' => Helper::get_settings( 'general.redirections_header_code' ),
|
||||
];
|
||||
|
||||
$this->redirection = $redirection;
|
||||
|
||||
return $redirection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get object URI.
|
||||
*
|
||||
* @param bool $refresh Force refresh.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_object_uri( $refresh = false ) {
|
||||
if ( isset( $this->object_uri ) && ! $refresh ) {
|
||||
return $this->object_uri;
|
||||
}
|
||||
|
||||
$url = 'term' === $this->object_type ? get_term_link( (int) $this->id ) : get_permalink( $this->id );
|
||||
if ( empty( $url ) || is_wp_error( $url ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$url = wp_parse_url( $url, PHP_URL_PATH );
|
||||
|
||||
$this->object_uri = trim( $url, '/' );
|
||||
|
||||
return $this->object_uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update object meta.
|
||||
*
|
||||
* @param string $key Meta key.
|
||||
* @param mixed $value Meta value.
|
||||
* @return void
|
||||
*/
|
||||
public function update_meta( $key, $value ) {
|
||||
$update_meta = "update_{$this->object_type}_meta";
|
||||
$update_meta( $this->id, 'rank_math_' . $key, $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get object meta.
|
||||
*
|
||||
* @param string $key Meta key.
|
||||
* @return bool
|
||||
*/
|
||||
public function get_meta( $key = '' ) {
|
||||
$get_meta = "get_{$this->object_type}_meta";
|
||||
return $get_meta( $this->id, $key ? 'rank_math_' . $key : '', (bool) $key );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete object meta.
|
||||
*
|
||||
* @param string $key Meta key.
|
||||
* @return void
|
||||
*/
|
||||
public function delete_meta( $key ) {
|
||||
$delete_meta = "delete_{$this->object_type}_meta";
|
||||
$delete_meta( $this->id, 'rank_math_' . $key );
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,358 @@
|
||||
<?php
|
||||
/**
|
||||
* The CSV Import class.
|
||||
*
|
||||
* @since 1.0
|
||||
* @package RankMathPro
|
||||
* @subpackage RankMathPro\Admin
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Admin\CSV_Import_Export;
|
||||
|
||||
use MyThemeShop\Helpers\Arr;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* CSV Importer class.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class Importer {
|
||||
|
||||
/**
|
||||
* Term slug => ID cache.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $term_ids = [];
|
||||
|
||||
/**
|
||||
* Settings array. Default values.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $settings = [
|
||||
'not_applicable_value' => 'n/a',
|
||||
'clear_command' => 'DELETE',
|
||||
'no_overwrite' => true,
|
||||
];
|
||||
|
||||
/**
|
||||
* Lines in the CSV that could not be imported for any reason.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $failed_rows = [];
|
||||
|
||||
/**
|
||||
* Lines in the CSV that could be imported successfully.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $imported_rows = [];
|
||||
|
||||
/**
|
||||
* Error messages.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $errors = [];
|
||||
|
||||
/**
|
||||
* SplFileObject instance.
|
||||
*
|
||||
* @var \SplFileObject
|
||||
*/
|
||||
private $spl;
|
||||
|
||||
/**
|
||||
* Column headers.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $column_headers = [];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->load_settings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load settings.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function load_settings() {
|
||||
$this->settings = apply_filters( 'rank_math/admin/csv_import_settings', wp_parse_args( get_option( 'rank_math_csv_import_settings', [] ), $this->settings ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Start import from file.
|
||||
*
|
||||
* @param string $file Path to temporary CSV file.
|
||||
* @param string $settings Import settings.
|
||||
* @return void
|
||||
*/
|
||||
public function start( $file, $settings = [] ) {
|
||||
update_option( 'rank_math_csv_import', $file );
|
||||
update_option( 'rank_math_csv_import_settings', $settings );
|
||||
delete_option( 'rank_math_csv_import_status' );
|
||||
$this->load_settings();
|
||||
$lines = $this->count_lines( $file );
|
||||
update_option( 'rank_math_csv_import_total', $lines );
|
||||
Import_Background_Process::get()->start( $lines );
|
||||
}
|
||||
|
||||
/**
|
||||
* Count all lines in CSV file.
|
||||
*
|
||||
* @param mixed $file Path to CSV.
|
||||
* @return int
|
||||
*/
|
||||
public function count_lines( $file ) {
|
||||
$file = new \SplFileObject( $file );
|
||||
while ( $file->valid() ) {
|
||||
$file->fgets();
|
||||
}
|
||||
|
||||
$count = $file->key();
|
||||
|
||||
// Check if last line is empty.
|
||||
$file->seek( $count );
|
||||
$contents = $file->current();
|
||||
if ( empty( trim( $contents ) ) ) {
|
||||
$count--;
|
||||
}
|
||||
|
||||
// Unlock file.
|
||||
$file = null;
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get specified line from CSV.
|
||||
*
|
||||
* @param string $file Path to file.
|
||||
* @param int $line Line number.
|
||||
* @return string
|
||||
*/
|
||||
public function get_line( $file, $line ) {
|
||||
if ( empty( $this->spl ) ) {
|
||||
$this->spl = new \SplFileObject( $file );
|
||||
}
|
||||
|
||||
if ( ! $this->spl->eof() ) {
|
||||
$this->spl->seek( $line );
|
||||
$contents = $this->spl->current();
|
||||
}
|
||||
|
||||
return $contents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse and return column headers (first line in CSV).
|
||||
*
|
||||
* @param string $file Path to file.
|
||||
* @return array
|
||||
*/
|
||||
public function get_column_headers( $file ) {
|
||||
if ( ! empty( $this->column_headers ) ) {
|
||||
return $this->column_headers;
|
||||
}
|
||||
|
||||
if ( empty( $this->spl ) ) {
|
||||
$this->spl = new \SplFileObject( $file );
|
||||
}
|
||||
|
||||
if ( ! $this->spl->eof() ) {
|
||||
$this->spl->seek( 0 );
|
||||
$contents = $this->spl->current();
|
||||
}
|
||||
|
||||
if ( empty( $contents ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$this->column_headers = Arr::from_string( $contents, apply_filters( 'rank_math/csv_import/separator', ',' ) );
|
||||
return $this->column_headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Import specified line.
|
||||
*
|
||||
* @param int $line_number Selected line number.
|
||||
* @return void
|
||||
*/
|
||||
public function import_line( $line_number ) {
|
||||
// Skip headers.
|
||||
if ( 0 === $line_number ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$file = get_option( 'rank_math_csv_import' );
|
||||
if ( ! $file ) {
|
||||
$this->add_error( esc_html__( 'Missing import file.', 'rank-math-pro' ), 'missing_file' );
|
||||
CSV_Import_Export::cancel_import( true );
|
||||
return;
|
||||
}
|
||||
|
||||
$headers = $this->get_column_headers( $file );
|
||||
if ( empty( $headers ) ) {
|
||||
$this->add_error( esc_html__( 'Missing CSV headers.', 'rank-math-pro' ), 'missing_headers' );
|
||||
return;
|
||||
}
|
||||
|
||||
$required_columns = [ 'id', 'object_type', 'slug' ];
|
||||
if ( count( array_intersect( $headers, $required_columns ) ) !== count( $required_columns ) ) {
|
||||
$this->add_error( esc_html__( 'Missing one or more required columns.', 'rank-math-pro' ), 'missing_required_columns' );
|
||||
return;
|
||||
}
|
||||
|
||||
$raw_data = $this->get_line( $file, $line_number );
|
||||
if ( empty( $raw_data ) ) {
|
||||
$total_lines = (int) get_option( 'rank_math_csv_import_total' );
|
||||
|
||||
// Last line can be empty, that is not an error.
|
||||
if ( $line_number !== $total_lines ) {
|
||||
$this->add_error( esc_html__( 'Empty column data.', 'rank-math-pro' ), 'missing_data' );
|
||||
$this->row_failed( $line_number );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$csv_separator = apply_filters( 'rank_math/csv_import/separator', ',' );
|
||||
$decoded = str_getcsv( $raw_data, $csv_separator );
|
||||
if ( count( $headers ) !== count( $decoded ) ) {
|
||||
$this->add_error( esc_html__( 'Columns number mismatch.', 'rank-math-pro' ), 'columns_number_mismatch' );
|
||||
$this->row_failed( $line_number );
|
||||
return;
|
||||
}
|
||||
|
||||
$data = array_combine( $headers, $decoded );
|
||||
if ( ! in_array( $data['object_type'], array_keys( CSV_Import_Export::get_possible_object_types() ), true ) ) {
|
||||
$this->add_error( esc_html__( 'Unknown object type.', 'rank-math-pro' ), 'unknown_object_type' );
|
||||
$this->row_failed( $line_number );
|
||||
return;
|
||||
}
|
||||
|
||||
new Import_Row( $data, $this->settings );
|
||||
$this->row_imported( $line_number );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get term ID from slug.
|
||||
*
|
||||
* @param string $term_slug Term slug.
|
||||
* @return int
|
||||
*/
|
||||
public static function get_term_id( $term_slug ) {
|
||||
global $wpdb;
|
||||
|
||||
if ( ! empty( self::$term_ids[ $term_slug ] ) ) {
|
||||
return self::$term_ids[ $term_slug ];
|
||||
}
|
||||
|
||||
self::$term_ids[ $term_slug ] = $wpdb->get_var(
|
||||
$wpdb->prepare( "SELECT term_id FROM {$wpdb->terms} WHERE slug = %s", $term_slug )
|
||||
);
|
||||
|
||||
return self::$term_ids[ $term_slug ];
|
||||
}
|
||||
|
||||
/**
|
||||
* After each batch is finished.
|
||||
*
|
||||
* @param array $items Processed items.
|
||||
*/
|
||||
public function batch_done( $items ) { // phpcs:ignore
|
||||
unset( $this->spl );
|
||||
|
||||
$status = (array) get_option( 'rank_math_csv_import_status', [] );
|
||||
if ( ! isset( $status['errors'] ) || ! is_array( $status['errors'] ) ) {
|
||||
$status['errors'] = [];
|
||||
}
|
||||
if ( ! isset( $status['failed_rows'] ) || ! is_array( $status['failed_rows'] ) ) {
|
||||
$status['failed_rows'] = [];
|
||||
}
|
||||
if ( ! isset( $status['imported_rows'] ) || ! is_array( $status['imported_rows'] ) ) {
|
||||
$status['imported_rows'] = [];
|
||||
}
|
||||
|
||||
$status['imported_rows'] = array_merge( $status['imported_rows'], $this->get_imported_rows() );
|
||||
|
||||
$errors = $this->get_errors();
|
||||
if ( $errors ) {
|
||||
$status['errors'] = array_merge( $status['errors'], $errors );
|
||||
$status['failed_rows'] = array_merge( $status['failed_rows'], $this->get_failed_rows() );
|
||||
}
|
||||
|
||||
update_option( 'rank_math_csv_import_status', $status );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set row import status.
|
||||
*
|
||||
* @param int $row Row index.
|
||||
*/
|
||||
private function row_failed( $row ) {
|
||||
$this->failed_rows[] = $row + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set row import status.
|
||||
*
|
||||
* @param int $row Row index.
|
||||
*/
|
||||
private function row_imported( $row ) {
|
||||
$this->imported_rows[] = $row + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get failed rows array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_failed_rows() {
|
||||
return $this->failed_rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get failed rows array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_imported_rows() {
|
||||
return $this->imported_rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all import errors.
|
||||
*
|
||||
* @return mixed Array of errors or false if there is no error.
|
||||
*/
|
||||
public function get_errors() {
|
||||
return empty( $this->errors ) ? false : $this->errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add import error.
|
||||
*
|
||||
* @param string $message Error message.
|
||||
* @param int $code Error code.
|
||||
*/
|
||||
public function add_error( $message, $code = null ) {
|
||||
if ( is_null( $code ) ) {
|
||||
$this->errors[] = $message;
|
||||
return;
|
||||
}
|
||||
$this->errors[ $code ] = $message;
|
||||
}
|
||||
}
|
@@ -0,0 +1 @@
|
||||
<?php // Silence is golden.
|
@@ -0,0 +1,318 @@
|
||||
<?php
|
||||
/**
|
||||
* The Sitemap wizard step
|
||||
*
|
||||
* @since 1.0
|
||||
* @package RankMathPro
|
||||
* @subpackage RankMathPro\Sitemap
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMathPro\Wizard;
|
||||
|
||||
use RankMath\KB;
|
||||
use RankMath\Helper;
|
||||
use RankMath\Wizard\Wizard_Step;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Step class.
|
||||
*/
|
||||
class Sitemap implements Wizard_Step {
|
||||
|
||||
/**
|
||||
* Render step body.
|
||||
*
|
||||
* @param object $wizard Wizard class instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function render( $wizard ) {
|
||||
?>
|
||||
<header>
|
||||
<h1><?php esc_html_e( 'Sitemap', 'rank-math-pro' ); ?> </h1>
|
||||
<p>
|
||||
<?php
|
||||
/* translators: Link to How to Setup Sitemap KB article */
|
||||
printf( esc_html__( 'Choose your Sitemap configuration and select which type of posts or pages you want to include in your Sitemaps. %s', 'rank-math-pro' ), '<a href="' . KB::get( 'configure-sitemaps', 'SW Sitemap Step' ) . '" target="_blank">' . esc_html__( 'Learn more.', 'rank-math-pro' ) . '</a>' );
|
||||
?>
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<?php $wizard->cmb->show_form(); ?>
|
||||
|
||||
<footer class="form-footer wp-core-ui rank-math-ui">
|
||||
<?php $wizard->get_skip_link(); ?>
|
||||
<button type="submit" class="button button-primary"><?php esc_html_e( 'Save and Continue', 'rank-math-pro' ); ?></button>
|
||||
</footer>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Render form for step.
|
||||
*
|
||||
* @param object $wizard Wizard class instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function form( $wizard ) {
|
||||
$wizard->cmb->add_field(
|
||||
[
|
||||
'id' => 'sitemap',
|
||||
'type' => 'toggle',
|
||||
'name' => esc_html__( 'Sitemaps', 'rank-math-pro' ),
|
||||
'desc' => esc_html__( 'XML Sitemaps help search engines index your website's content more effectively.', 'rank-math-pro' ),
|
||||
'default' => Helper::is_module_active( 'sitemap' ) ? 'on' : 'off',
|
||||
]
|
||||
);
|
||||
|
||||
$wizard->cmb->add_field(
|
||||
[
|
||||
'id' => 'include_images',
|
||||
'type' => 'toggle',
|
||||
'name' => esc_html__( 'Include Images', 'rank-math-pro' ),
|
||||
'desc' => esc_html__( 'Include reference to images from the post content in sitemaps. This helps search engines index your images better.', 'rank-math-pro' ),
|
||||
'default' => Helper::get_settings( 'sitemap.include_images' ) ? 'on' : 'off',
|
||||
'classes' => 'features-child',
|
||||
'dep' => [ [ 'sitemap', 'on' ] ],
|
||||
]
|
||||
);
|
||||
|
||||
// Post Types.
|
||||
$post_types = $this->get_post_types();
|
||||
$wizard->cmb->add_field(
|
||||
[
|
||||
'id' => 'sitemap_post_types',
|
||||
'type' => 'multicheck',
|
||||
'name' => esc_html__( 'Public Post Types', 'rank-math-pro' ),
|
||||
'desc' => esc_html__( 'Select post types to enable SEO options for them and include them in the sitemap.', 'rank-math-pro' ),
|
||||
'options' => $post_types['post_types'],
|
||||
'default' => $post_types['defaults'],
|
||||
'classes' => 'features-child cmb-multicheck-inline' . ( count( $post_types['post_types'] ) === count( $post_types['defaults'] ) ? ' multicheck-checked' : '' ),
|
||||
'dep' => [ [ 'sitemap', 'on' ] ],
|
||||
]
|
||||
);
|
||||
|
||||
// Taxonomies.
|
||||
$taxonomies = $this->get_taxonomies();
|
||||
$wizard->cmb->add_field(
|
||||
[
|
||||
'id' => 'sitemap_taxonomies',
|
||||
'type' => 'multicheck',
|
||||
'name' => esc_html__( 'Public Taxonomies', 'rank-math-pro' ),
|
||||
'desc' => esc_html__( 'Select taxonomies to enable SEO options for them and include them in the sitemap.', 'rank-math-pro' ),
|
||||
'options' => $taxonomies['taxonomies'],
|
||||
'default' => $taxonomies['defaults'],
|
||||
'classes' => 'features-child cmb-multicheck-inline' . ( count( $taxonomies['taxonomies'] ) === count( $taxonomies['defaults'] ) ? ' multicheck-checked' : '' ),
|
||||
'dep' => [ [ 'sitemap', 'on' ] ],
|
||||
]
|
||||
);
|
||||
|
||||
$news_sitemap_dep = [ 'relation' => 'and' ] + [ [ 'sitemap', 'on' ] ];
|
||||
$news_sitemap_dep[] = [ 'news-sitemap', 'on' ];
|
||||
$wizard->cmb->add_field(
|
||||
[
|
||||
'id' => 'news_sitemap_title',
|
||||
'type' => 'raw',
|
||||
'content' => sprintf( '<br><br><div class="cmb-form cmb-row nopb"><header class="sitemap-title"><h1>%1$s</h1><p>%2$s</p></header><div class="rank-math-cmb-dependency hidden" data-relation="or"><span class="hidden" data-field="sitemap" data-comparison="=" data-value="on"></span></div></div>', esc_html__( 'News Sitemap', 'rank-math-pro' ), esc_html__( 'News Sitemaps allow you to control which content you submit to Google News.', 'rank-math-pro' ) ),
|
||||
]
|
||||
);
|
||||
|
||||
$wizard->cmb->add_field(
|
||||
[
|
||||
'id' => 'news-sitemap',
|
||||
'type' => 'toggle',
|
||||
'name' => esc_html__( 'News Sitemaps', 'rank-math-pro' ),
|
||||
'desc' => esc_html__( 'You will generally only need a News Sitemap when your website is included in Google News.', 'rank-math-pro' ),
|
||||
'default' => Helper::is_module_active( 'news-sitemap' ) ? 'on' : 'off',
|
||||
'dep' => [ [ 'sitemap', 'on' ] ],
|
||||
]
|
||||
);
|
||||
|
||||
$wizard->cmb->add_field(
|
||||
[
|
||||
'id' => 'news_sitemap_publication_name',
|
||||
'type' => 'text',
|
||||
'name' => esc_html__( 'Google News Publication Name', 'rank-math-pro' ),
|
||||
'classes' => 'features-child cmb-multicheck-inline',
|
||||
'desc' => wp_kses_post( __( 'The name of the news publication. It must match the name exactly as it appears on your articles in news.google.com, omitting any trailing parentheticals. <a href="https://support.google.com/news/publisher-center/answer/9606710" target="_blank">More information at support.google.com</a>', 'rank-math-pro' ) ),
|
||||
'default' => Helper::get_settings( 'sitemap.news_sitemap_publication_name' ),
|
||||
'dep' => $news_sitemap_dep,
|
||||
]
|
||||
);
|
||||
|
||||
$wizard->cmb->add_field(
|
||||
[
|
||||
'id' => 'news_sitemap_post_type',
|
||||
'type' => 'multicheck_inline',
|
||||
'name' => esc_html__( 'News Post Type', 'rank-math-pro' ),
|
||||
'desc' => esc_html__( 'Select the post type you use for News articles.', 'rank-math-pro' ),
|
||||
'classes' => 'features-child cmb-multicheck-inline',
|
||||
'options' => $post_types['post_types'],
|
||||
'default' => Helper::get_settings( 'sitemap.news_sitemap_post_type' ),
|
||||
'dep' => $news_sitemap_dep,
|
||||
]
|
||||
);
|
||||
|
||||
$wizard->cmb->add_field(
|
||||
[
|
||||
'id' => 'video_sitemap_title',
|
||||
'type' => 'raw',
|
||||
'content' => sprintf( '<br><br><div class="cmb-form cmb-row nopb"><header class="sitemap-title"><h1>%1$s</h1><p>%2$s</p></header><div class="rank-math-cmb-dependency hidden" data-relation="or"><span class="hidden" data-field="sitemap" data-comparison="=" data-value="on"></span></div></div>', esc_html__( 'Video Sitemap', 'rank-math-pro' ), esc_html__( 'Video Sitemaps give search engines information about video content on your site.', 'rank-math-pro' ) ),
|
||||
]
|
||||
);
|
||||
|
||||
$wizard->cmb->add_field(
|
||||
[
|
||||
'id' => 'video-sitemap',
|
||||
'type' => 'toggle',
|
||||
'name' => esc_html__( 'Video Sitemaps', 'rank-math-pro' ),
|
||||
'desc' => esc_html__( 'You will generally only need a Video Sitemap when your website has video content.', 'rank-math-pro' ),
|
||||
'default' => Helper::is_module_active( 'video-sitemap' ) ? 'on' : 'off',
|
||||
'dep' => [ [ 'sitemap', 'on' ] ],
|
||||
]
|
||||
);
|
||||
|
||||
$wizard->cmb->add_field(
|
||||
[
|
||||
'id' => 'video_sitemap_post_type',
|
||||
'type' => 'multicheck_inline',
|
||||
'name' => esc_html__( 'Video Post Type', 'rank-math-pro' ),
|
||||
'desc' => esc_html__( 'Select the post type where you use videos and want them to be shown in the Video search.', 'rank-math-pro' ),
|
||||
'classes' => 'features-child cmb-multicheck-inline',
|
||||
'options' => $post_types['post_types'],
|
||||
'default' => Helper::get_settings( 'sitemap.video_sitemap_post_type', array_keys( $post_types['post_types'] ) ),
|
||||
'dep' => [ 'relation' => 'and' ] + [ [ 'sitemap', 'on' ], [ 'video-sitemap', 'on' ] ],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save handler for step.
|
||||
*
|
||||
* @param array $values Values to save.
|
||||
* @param object $wizard Wizard class instance.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function save( $values, $wizard ) {
|
||||
$settings = rank_math()->settings->all_raw();
|
||||
Helper::update_modules( [ 'sitemap' => $values['sitemap'] ] );
|
||||
Helper::update_modules( [ 'news-sitemap' => $values['news-sitemap'] ] );
|
||||
Helper::update_modules( [ 'video-sitemap' => $values['video-sitemap'] ] );
|
||||
|
||||
if ( 'on' === $values['sitemap'] ) {
|
||||
$settings['sitemap']['include_images'] = $values['include_images'];
|
||||
|
||||
$settings = $this->save_post_types( $settings, $values );
|
||||
$settings = $this->save_taxonomies( $settings, $values );
|
||||
Helper::update_all_settings( null, null, $settings['sitemap'] );
|
||||
}
|
||||
|
||||
if ( 'on' === $values['news-sitemap'] ) {
|
||||
$settings['sitemap']['news_sitemap_publication_name'] = ! empty( $values['news_sitemap_publication_name'] ) ? $values['news_sitemap_publication_name'] : '';
|
||||
$settings['sitemap']['news_sitemap_post_type'] = ! empty( $values['news_sitemap_post_type'] ) ? $values['news_sitemap_post_type'] : [];
|
||||
|
||||
Helper::update_all_settings( null, null, $settings['sitemap'] );
|
||||
}
|
||||
|
||||
if ( 'on' === $values['video-sitemap'] ) {
|
||||
$settings['sitemap']['video_sitemap_post_type'] = ! empty( $values['video_sitemap_post_type'] ) ? $values['video_sitemap_post_type'] : [];
|
||||
|
||||
Helper::update_all_settings( null, null, $settings['sitemap'] );
|
||||
}
|
||||
|
||||
Helper::schedule_flush_rewrite();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get post type data.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_post_types() {
|
||||
$p_defaults = [];
|
||||
$post_types = Helper::choices_post_types();
|
||||
if ( Helper::get_settings( 'general.attachment_redirect_urls', true ) ) {
|
||||
unset( $post_types['attachment'] );
|
||||
}
|
||||
|
||||
foreach ( $post_types as $post_type => $object ) {
|
||||
if ( true === Helper::get_settings( "sitemap.pt_{$post_type}_sitemap" ) ) {
|
||||
$p_defaults[] = $post_type;
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'defaults' => $p_defaults,
|
||||
'post_types' => $post_types,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get taxonomies data.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_taxonomies() {
|
||||
$t_defaults = [];
|
||||
$taxonomies = Helper::get_accessible_taxonomies();
|
||||
unset( $taxonomies['post_tag'], $taxonomies['post_format'], $taxonomies['product_tag'] );
|
||||
$taxonomies = wp_list_pluck( $taxonomies, 'label', 'name' );
|
||||
foreach ( $taxonomies as $taxonomy => $label ) {
|
||||
if ( true === Helper::get_settings( "sitemap.tax_{$taxonomy}_sitemap" ) ) {
|
||||
$t_defaults[] = $taxonomy;
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'defaults' => $t_defaults,
|
||||
'taxonomies' => $taxonomies,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Save Post Types
|
||||
*
|
||||
* @param array $settings Array of all settings.
|
||||
* @param array $values Array of posted values.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function save_post_types( $settings, $values ) {
|
||||
$post_types = Helper::choices_post_types();
|
||||
if ( ! isset( $values['sitemap_post_types'] ) ) {
|
||||
$values['sitemap_post_types'] = [];
|
||||
}
|
||||
|
||||
foreach ( $post_types as $post_type => $object ) {
|
||||
$settings['sitemap'][ "pt_{$post_type}_sitemap" ] = in_array( $post_type, $values['sitemap_post_types'], true ) ? 'on' : 'off';
|
||||
}
|
||||
|
||||
return $settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save Taxonomies
|
||||
*
|
||||
* @param array $settings Array of all settings.
|
||||
* @param array $values Array of posted values.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function save_taxonomies( $settings, $values ) {
|
||||
$taxonomies = Helper::get_accessible_taxonomies();
|
||||
$taxonomies = wp_list_pluck( $taxonomies, 'label', 'name' );
|
||||
if ( ! isset( $values['sitemap_taxonomies'] ) ) {
|
||||
$values['sitemap_taxonomies'] = [];
|
||||
}
|
||||
|
||||
foreach ( $taxonomies as $taxonomy => $label ) {
|
||||
$settings['sitemap'][ "tax_{$taxonomy}_sitemap" ] = in_array( $taxonomy, $values['sitemap_taxonomies'], true ) ? 'on' : 'off';
|
||||
}
|
||||
|
||||
return $settings;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user