plug/s1-seo-meta74/includes/class-s1-seo-meta-term.php

237 lines
6.4 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* Handles saving and retrieving SEO meta for taxonomy terms
* (categories, tags, and all public custom taxonomies).
*
* @package S1_SEO_Meta
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class S1_SEO_Meta_Term {
/**
* Option-table key prefix used to store term meta (WP < 4.4 fallback aware).
* From WP 4.4+ term meta is stored in wp_termmeta via get/update_term_meta().
*/
const META_TITLE = 's1_seo_title';
const META_DESC = 's1_seo_description';
public function __construct() {
add_action( 'init', array( $this, 'register_term_hooks' ) );
}
/**
* Register add/edit/save hooks for every public taxonomy.
*/
public function register_term_hooks() {
$taxonomies = get_taxonomies( array( 'public' => true ), 'names' );
foreach ( $taxonomies as $taxonomy ) {
// Fields on the "Add new term" form.
add_action( "{$taxonomy}_add_form_fields", array( $this, 'add_form_fields' ) );
// Fields on the "Edit term" form.
add_action( "{$taxonomy}_edit_form_fields", array( $this, 'edit_form_fields' ), 10, 2 );
// Save on create.
add_action( "created_{$taxonomy}", array( $this, 'save_term_meta' ), 10, 2 );
// Save on update.
add_action( "edited_{$taxonomy}", array( $this, 'save_term_meta' ), 10, 2 );
}
}
/**
* Render fields on the "Add new term" screen.
*
* @param string $taxonomy Current taxonomy slug.
*/
public function add_form_fields( $taxonomy ) {
wp_nonce_field( 's1_seo_term_save', 's1_seo_term_nonce' );
?>
<div class="form-field s1-seo-term-wrap">
<h3 class="s1-seo-term-heading"><?php esc_html_e( 'S1 SEO', 's1-seo-meta' ); ?></h3>
<div class="form-field">
<label for="s1_seo_title"><?php esc_html_e( 'SEO Title', 's1-seo-meta' ); ?></label>
<input
type="text"
id="s1_seo_title"
name="s1_seo_title"
value=""
maxlength="666"
/>
<p class="s1-seo-counter">
<span id="s1_seo_title_count">0</span>/60 <?php esc_html_e( 'characters', 's1-seo-meta' ); ?>
</p>
</div>
<div class="form-field">
<label for="s1_seo_description"><?php esc_html_e( 'SEO Description', 's1-seo-meta' ); ?></label>
<?php
$settings = array(
'media_buttons' => false,
'textarea_rows' => 5,
'teeny' => true,
'tinymce' => array(
'toolbar1' => 'bold,italic,underline,link,unlink',
'toolbar2' => '',
),
);
wp_editor( '', 's1_seo_description', $settings );
?>
<p class="s1-seo-counter">
<span id="s1_seo_desc_count">0</span>/160 <?php esc_html_e( 'characters (recommended: 120–160)', 's1-seo-meta' ); ?>
</p>
</div>
</div>
<?php
}
/**
* Render fields on the "Edit term" screen.
*
* @param WP_Term $term Current term object.
* @param string $taxonomy Current taxonomy slug.
*/
public function edit_form_fields( $term, $taxonomy ) {
wp_nonce_field( 's1_seo_term_save', 's1_seo_term_nonce' );
$seo_title = get_term_meta( $term->term_id, self::META_TITLE, true );
$seo_desc = get_term_meta( $term->term_id, self::META_DESC, true );
?>
<tr class="form-field s1-seo-term-row">
<td colspan="2">
<h3 class="s1-seo-term-heading"><?php esc_html_e( 'S1 SEO', 's1-seo-meta' ); ?></h3>
</td>
</tr>
<tr class="form-field">
<th scope="row">
<label for="s1_seo_title"><?php esc_html_e( 'SEO Title', 's1-seo-meta' ); ?></label>
</th>
<td>
<input
type="text"
id="s1_seo_title"
name="s1_seo_title"
value="<?php echo esc_attr( $seo_title ); ?>"
placeholder="<?php echo esc_attr( $term->name ); ?>"
maxlength="60"
/>
<p class="description s1-seo-counter">
<span id="s1_seo_title_count"><?php echo esc_html( mb_strlen( $seo_title ) ); ?></span>/60
<?php esc_html_e( 'characters (recommended: 50–60)', 's1-seo-meta' ); ?>
</p>
</td>
</tr>
<tr class="form-field">
<th scope="row">
<label for="s1_seo_description"><?php esc_html_e( 'SEO Description', 's1-seo-meta' ); ?></label>
</th>
<td>
<?php
$settings = array(
'media_buttons' => false,
'textarea_rows' => 5,
'teeny' => true,
'tinymce' => array(
'toolbar1' => 'bold,italic,underline,link,unlink',
'toolbar2' => '',
),
);
wp_editor( $seo_desc, 's1_seo_description', $settings );
?>
<p class="description s1-seo-counter">
<span id="s1_seo_desc_count"><?php echo esc_html( mb_strlen( wp_strip_all_tags( $seo_desc ) ) ); ?></span>/160
<?php esc_html_e( 'characters (recommended: 120–160)', 's1-seo-meta' ); ?>
</p>
</td>
</tr>
<?php
}
/**
* Save term SEO meta.
*
* @param int $term_id Term ID.
*/
public function save_term_meta( $term_id ) {
if (
! isset( $_POST['s1_seo_term_nonce'] ) ||
! wp_verify_nonce( sanitize_key( $_POST['s1_seo_term_nonce'] ), 's1_seo_term_save' )
) {
return;
}
if ( ! current_user_can( 'manage_categories' ) ) {
return;
}
if ( isset( $_POST['s1_seo_title'] ) ) {
update_term_meta(
$term_id,
self::META_TITLE,
sanitize_text_field( wp_unslash( $_POST['s1_seo_title'] ) )
);
}
if ( isset( $_POST['s1_seo_description'] ) ) {
$description = wp_unslash( $_POST['s1_seo_description'] );
// Разрешаем безопасные HTML теги для SEO описания
$allowed_tags = array(
'a' => array(
'href' => array(),
'title' => array(),
'target' => array(),
),
'b' => array(),
'strong' => array(),
'i' => array(),
'em' => array(),
'br' => array(),
'p' => array(),
'span' => array(),
'ul' => array(),
'ol' => array(),
'li' => array(),
);
// Для администраторов разрешаем все теги, для остальных - только безопасные
if ( current_user_can( 'unfiltered_html' ) ) {
$sanitized = $description;
} else {
$sanitized = wp_kses( $description, $allowed_tags );
}
update_term_meta(
$term_id,
self::META_DESC,
$sanitized
);
}
}
/**
* Static helper: retrieve SEO title for a term.
*
* @param int $term_id Term ID.
* @return string
*/
public static function get_title( $term_id ) {
return (string) get_term_meta( $term_id, self::META_TITLE, true );
}
/**
* Static helper: retrieve SEO description for a term.
*
* @param int $term_id Term ID.
* @return string
*/
public static function get_description( $term_id ) {
return (string) get_term_meta( $term_id, self::META_DESC, true );
}
}