You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
439 lines
11 KiB
PHTML
439 lines
11 KiB
PHTML
8 months ago
|
<?php
|
||
|
/**
|
||
|
* The CMB2 functionality of the plugin.
|
||
|
*
|
||
|
* This class defines all code necessary to have setting pages and manager.
|
||
|
*
|
||
|
* @since 0.9.0
|
||
|
* @package RankMath
|
||
|
* @subpackage RankMath\Core
|
||
|
* @author Rank Math <support@rankmath.com>
|
||
|
*/
|
||
|
|
||
|
namespace RankMath;
|
||
|
|
||
|
use RankMath\Helper;
|
||
|
use RankMath\Helpers\Str;
|
||
|
use RankMath\Helpers\Param;
|
||
|
use RankMath\Admin\Admin_Helper;
|
||
|
|
||
|
defined( 'ABSPATH' ) || exit;
|
||
|
|
||
|
/**
|
||
|
* CMB2 class.
|
||
|
*/
|
||
|
class CMB2 {
|
||
|
|
||
|
/**
|
||
|
* Set field arguments based on type.
|
||
|
*
|
||
|
* @param CMB2 $cmb CMB2 metabox object.
|
||
|
*/
|
||
|
public static function pre_init( $cmb ) {
|
||
|
foreach ( $cmb->prop( 'fields' ) as $id => $field_args ) {
|
||
|
$type = $field_args['type'];
|
||
|
$field = $cmb->get_field( $id );
|
||
|
|
||
|
if ( in_array( $type, [ 'meta_tab_container_open', 'tab_container_open', 'tab_container_close', 'tab', 'raw' ], true ) ) {
|
||
|
$field->args['save_field'] = false;
|
||
|
$field->args['render_row_cb'] = [ '\RankMath\CMB2', "render_{$type}" ];
|
||
|
}
|
||
|
if ( 'notice' === $type ) {
|
||
|
$field->args['save_field'] = false;
|
||
|
}
|
||
|
|
||
|
if ( ! empty( $field_args['dep'] ) ) {
|
||
|
self::set_dependencies( $field, $field_args );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Generate the dependency html for JavaScript.
|
||
|
*
|
||
|
* @param CMB2_Field $field CMB2 field object.
|
||
|
* @param array $args Dependency array.
|
||
|
*/
|
||
|
private static function set_dependencies( $field, $args ) {
|
||
|
if ( ! isset( $args['dep'] ) || empty( $args['dep'] ) ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$dependency = '';
|
||
|
$relation = 'OR';
|
||
|
|
||
|
if ( 'relation' === key( $args['dep'] ) ) {
|
||
|
$relation = current( $args['dep'] );
|
||
|
unset( $args['dep']['relation'] );
|
||
|
}
|
||
|
|
||
|
foreach ( $args['dep'] as $dependence ) {
|
||
|
$compasrison = isset( $dependence[2] ) ? $dependence[2] : '=';
|
||
|
$dependency .= '<span class="hidden" data-field="' . $dependence[0] . '" data-comparison="' . $compasrison . '" data-value="' . $dependence[1] . '"></span>';
|
||
|
}
|
||
|
|
||
|
$where = 'group' === $args['type'] ? 'after_group' : 'after_field';
|
||
|
$field->args[ $where ] = '<div class="rank-math-cmb-dependency hidden" data-relation="' . strtolower( $relation ) . '">' . $dependency . '</div>';
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the object type for the current page, based on the $pagenow global.
|
||
|
*
|
||
|
* @see CMB2->current_object_type()
|
||
|
*
|
||
|
* @return string Page object type name.
|
||
|
*/
|
||
|
public static function current_object_type() {
|
||
|
global $pagenow;
|
||
|
$type = 'post';
|
||
|
|
||
|
if ( in_array( $pagenow, [ 'user-edit.php', 'profile.php', 'user-new.php' ], true ) ) {
|
||
|
$type = 'user';
|
||
|
}
|
||
|
|
||
|
if ( in_array( $pagenow, [ 'edit-comments.php', 'comment.php' ], true ) ) {
|
||
|
$type = 'comment';
|
||
|
}
|
||
|
|
||
|
if ( in_array( $pagenow, [ 'edit-tags.php', 'term.php' ], true ) ) {
|
||
|
$type = 'term';
|
||
|
}
|
||
|
|
||
|
if ( Helper::is_ajax() && 'add-tag' === Param::post( 'action' ) ) {
|
||
|
$type = 'term';
|
||
|
}
|
||
|
|
||
|
return $type;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Render raw field.
|
||
|
*
|
||
|
* @param array $field_args Array of field arguments.
|
||
|
* @param CMB2_Field $field The field object.
|
||
|
*
|
||
|
* @return CMB2_Field
|
||
|
*/
|
||
|
public static function render_raw( $field_args, $field ) {
|
||
|
if ( $field->args( 'file' ) ) {
|
||
|
include $field->args( 'file' );
|
||
|
} elseif ( $field->args( 'content' ) ) {
|
||
|
echo $field->args( 'content' );
|
||
|
}
|
||
|
|
||
|
return $field;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Render tab container opening <div> for option panel.
|
||
|
*
|
||
|
* @param array $field_args Array of field arguments.
|
||
|
* @param CMB2_Field $field The field object.
|
||
|
*
|
||
|
* @return CMB2_Field
|
||
|
*/
|
||
|
public static function render_tab_container_open( $field_args, $field ) {
|
||
|
$active = Param::get( 'rank-math-tab', 'general' );
|
||
|
echo '<div id="' . $field->prop( 'id' ) . '" class="rank-math-tabs">';
|
||
|
?>
|
||
|
<div class="rank-math-tabs-navigation <?php echo $field->prop( 'classes' ); ?>">
|
||
|
|
||
|
<?php
|
||
|
foreach ( $field->args( 'tabs' ) as $id => $tab ) :
|
||
|
if ( empty( $tab ) ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ( isset( $tab['type'] ) && 'seprator' === $tab['type'] ) {
|
||
|
printf( '<span class="separator">%s</span>', $tab['title'] );
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
$class = isset( $tab['classes'] ) ? $tab['classes'] : '';
|
||
|
$class .= $id === $active ? ' active' : '';
|
||
|
?>
|
||
|
<a href="#setting-panel-<?php echo $id; ?>" class="<?php echo $class; ?>"><span class="<?php echo esc_attr( $tab['icon'] ); ?>"></span><?php echo $tab['title']; ?></a>
|
||
|
<?php endforeach; ?>
|
||
|
|
||
|
</div>
|
||
|
|
||
|
<div class="rank-math-tabs-content">
|
||
|
<?php
|
||
|
return $field;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Render tab container opening <div> for metabox.
|
||
|
*
|
||
|
* @param array $field_args Array of field arguments.
|
||
|
* @param CMB2_Field $field The field object.
|
||
|
*
|
||
|
* @return CMB2_Field
|
||
|
*/
|
||
|
public static function render_meta_tab_container_open( $field_args, $field ) {
|
||
|
echo '<div id="' . esc_attr( $field->prop( 'id' ) ) . '" class="rank-math-sidebar-panel rank-math-tabs">';
|
||
|
if ( Admin_Helper::is_term_profile_page() ) :
|
||
|
?>
|
||
|
<h2 class="rank-math-metabox-frame-title"><?php esc_html_e( 'Rank Math', 'rank-math' ); ?></h2>
|
||
|
<?php endif; ?>
|
||
|
<div class="rank-math-tabs-navigation rank-math-custom wp-clearfix">
|
||
|
|
||
|
<?php
|
||
|
foreach ( $field->args( 'tabs' ) as $id => $tab ) :
|
||
|
if ( empty( $tab ) || ! Helper::has_cap( $tab['capability'] ) ) {
|
||
|
continue;
|
||
|
}
|
||
|
?>
|
||
|
<a href="#setting-panel-<?php echo esc_attr( $id ); ?>">
|
||
|
<span class="<?php echo esc_attr( $tab['icon'] ); ?>"></span>
|
||
|
<span class="rank-math-tab-text"><?php echo esc_html( $tab['title'] ); ?></span>
|
||
|
</a>
|
||
|
<?php endforeach; ?>
|
||
|
</div>
|
||
|
|
||
|
<div class="rank-math-tabs-content rank-math-custom components-tab-panel__tab-content interface-complementary-area">
|
||
|
<?php
|
||
|
return $field;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Render tab container closing <div>.
|
||
|
*
|
||
|
* @param array $field_args Array of field arguments.
|
||
|
* @param CMB2_Field $field The field object.
|
||
|
*
|
||
|
* @return CMB2_Field
|
||
|
*/
|
||
|
public static function render_tab_container_close( $field_args, $field ) {
|
||
|
echo '</div><!-- /.rank-math-tabs-content -->';
|
||
|
echo '</div><!-- /#' . $field->prop( 'id' ) . ' -->';
|
||
|
|
||
|
return $field;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Render tab content opening <div> and closing </div>.
|
||
|
*
|
||
|
* @param array $field_args Array of field arguments.
|
||
|
* @param CMB2_Field $field The field object.
|
||
|
*
|
||
|
* @return CMB2_Field
|
||
|
*/
|
||
|
public static function render_tab( $field_args, $field ) {
|
||
|
printf(
|
||
|
true === $field->prop( 'open' ) ? '<div id="%1$s" class="rank-math-tab rank-math-options-panel-content ' . $field->prop( 'classes' ) . '">' : '</div><!-- /#%1$s -->',
|
||
|
$field->prop( 'id' )
|
||
|
);
|
||
|
|
||
|
return $field;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Handles sanitization for HTML entities.
|
||
|
*
|
||
|
* @param mixed $value The unsanitized value from the form.
|
||
|
*
|
||
|
* @return mixed Sanitized value to be stored.
|
||
|
*/
|
||
|
public static function sanitize_htmlentities( $value ) {
|
||
|
return htmlentities( $value, ENT_COMPAT, get_option( 'blog_charset' ) );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Handles sanitization for Separator Character option.
|
||
|
*
|
||
|
* @param mixed $value The unsanitized value from the form.
|
||
|
*
|
||
|
* @return mixed Sanitized value to be stored.
|
||
|
*/
|
||
|
public static function sanitize_separator( $value ) {
|
||
|
return htmlentities( wp_strip_all_tags( $value, true ) );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Handles sanitization for text fields.
|
||
|
*
|
||
|
* @param string $value The unsanitized value from the form.
|
||
|
*
|
||
|
* @return string Sanitized value to be stored.
|
||
|
*/
|
||
|
public static function sanitize_textfield( $value ) {
|
||
|
if ( is_object( $value ) || is_array( $value ) ) {
|
||
|
return '';
|
||
|
}
|
||
|
|
||
|
$value = (string) $value;
|
||
|
$filtered = wp_check_invalid_utf8( $value );
|
||
|
|
||
|
if ( strpos( $filtered, '<' ) !== false ) {
|
||
|
$filtered = wp_pre_kses_less_than( $filtered );
|
||
|
|
||
|
// Strip extra whitespace.
|
||
|
$filtered = wp_strip_all_tags( $filtered, false );
|
||
|
|
||
|
// Use html entities in a special case to make sure no later
|
||
|
// newline stripping stage could lead to a functional tag!
|
||
|
$filtered = str_replace( "<\n", "<\n", $filtered );
|
||
|
}
|
||
|
$filtered = preg_replace( '/[\r\n\t ]+/', ' ', $filtered );
|
||
|
$filtered = trim( $filtered );
|
||
|
|
||
|
$found = false;
|
||
|
while ( preg_match( '/%[0-9]{2}/i', $filtered, $match ) ) {
|
||
|
$filtered = str_replace( $match[0], '', $filtered );
|
||
|
$found = true;
|
||
|
}
|
||
|
|
||
|
if ( $found ) {
|
||
|
// Strip out the whitespace that may now exist after removing the octets.
|
||
|
$filtered = trim( preg_replace( '/ +/', ' ', $filtered ) );
|
||
|
}
|
||
|
|
||
|
return apply_filters( 'sanitize_text_field', $filtered, $value );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Handles sanitization of rank_math_permalink.
|
||
|
*
|
||
|
* @param string $value The unsanitized value from the form.
|
||
|
*
|
||
|
* @return string Sanitized value to be stored.
|
||
|
*/
|
||
|
public static function sanitize_permalink( $value ) {
|
||
|
if ( empty( $value ) ) {
|
||
|
return '';
|
||
|
}
|
||
|
|
||
|
return sanitize_title( $value );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Handles escaping of rank_math_permalink.
|
||
|
*
|
||
|
* @param string $value The value from the DB.
|
||
|
*
|
||
|
* @return string Escaped value.
|
||
|
*/
|
||
|
public static function escape_permalink( $value ) {
|
||
|
if ( empty( $value ) ) {
|
||
|
return '';
|
||
|
}
|
||
|
|
||
|
return esc_attr( urldecode( $value ) );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Handles sanitization of floating point values.
|
||
|
*
|
||
|
* @param string $value The unsanitized value from the form.
|
||
|
*
|
||
|
* @return string Sanitized value to be stored.
|
||
|
*/
|
||
|
public static function sanitize_float( $value ) {
|
||
|
if ( empty( $value ) ) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
return filter_var( $value, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Handles sanitization for webmaster tag and remove <meta> tag.
|
||
|
*
|
||
|
* @param mixed $value The unsanitized value from the form.
|
||
|
*
|
||
|
* @return mixed Sanitized value to be stored.
|
||
|
*/
|
||
|
public static function sanitize_webmaster_tags( $value ) {
|
||
|
$value = trim( $value );
|
||
|
|
||
|
if ( ! empty( $value ) && Str::starts_with( '<meta', trim( $value ) ) ) {
|
||
|
preg_match( '/content="([^"]+)"/i', stripslashes( $value ), $matches );
|
||
|
$value = $matches[1];
|
||
|
}
|
||
|
|
||
|
return htmlentities( wp_strip_all_tags( $value ) );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Handles sanitization for custom webmaster tags.
|
||
|
* Only <meta> tags are allowed.
|
||
|
*
|
||
|
* @param mixed $value The unsanitized value from the form.
|
||
|
*/
|
||
|
public static function sanitize_custom_webmaster_tags( $value ) {
|
||
|
$sanitized = wp_kses(
|
||
|
$value,
|
||
|
[
|
||
|
'meta' => [
|
||
|
'name' => [],
|
||
|
'content' => [],
|
||
|
],
|
||
|
]
|
||
|
);
|
||
|
|
||
|
return $sanitized;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Handles sanitization of advanced robots data.
|
||
|
*
|
||
|
* @param array $robots The unsanitized value from the form.
|
||
|
*
|
||
|
* @return array Sanitized value to be stored.
|
||
|
*/
|
||
|
public static function sanitize_advanced_robots( $robots ) {
|
||
|
if ( empty( $robots ) ) {
|
||
|
return [];
|
||
|
}
|
||
|
|
||
|
$advanced_robots = [];
|
||
|
foreach ( $robots as $key => $robot ) {
|
||
|
$advanced_robots[ $key ] = ! empty( $robot['enable'] ) ? $robot['length'] : false;
|
||
|
}
|
||
|
|
||
|
return $advanced_robots;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Handles sanitization of Focus Keywords.
|
||
|
*
|
||
|
* @param mixed $value The unsanitized focus keywords.
|
||
|
*
|
||
|
* @return string Sanitized focus keywords to be stored.
|
||
|
*/
|
||
|
public static function sanitize_focus_keywords( $value ) {
|
||
|
$values = json_decode( stripslashes( $value ), true );
|
||
|
if ( empty( $values ) ) {
|
||
|
return '';
|
||
|
}
|
||
|
|
||
|
return implode(
|
||
|
',',
|
||
|
array_map(
|
||
|
function ( $entry ) {
|
||
|
return sanitize_text_field( $entry['value'] );
|
||
|
},
|
||
|
$values
|
||
|
)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Handles sanitization of Robots text.
|
||
|
*
|
||
|
* @since 1.0.45
|
||
|
*
|
||
|
* @param mixed $value The unsanitized Robots text.
|
||
|
*
|
||
|
* @return string Sanitized Robots text to be stored.
|
||
|
*/
|
||
|
public static function sanitize_robots_text( $value ) {
|
||
|
if ( empty( $value ) ) {
|
||
|
return '';
|
||
|
}
|
||
|
|
||
|
return wp_strip_all_tags( $value );
|
||
|
}
|
||
|
}
|