taxonomy ) || $screen->taxonomy !== $taxonomy ) {
return;
}
wp_enqueue_media();
wp_add_inline_script(
'jquery',
'(function($){$(function(){var frame;$(".forwp-faq-seo-image-select").on("click",function(e){e.preventDefault();if(frame){frame.open();return;}frame=wp.media({title:"' . esc_js( __( 'Select image', '4wp-faq' ) ) . '",button:{text:"' . esc_js( __( 'Use image', '4wp-faq' ) ) . '"},multiple:false});frame.on("select",function(){var a=frame.state().get("selection").first().toJSON();var src=(a.sizes&&a.sizes.medium)?a.sizes.medium.url:a.url;$("#forwp_seo_image").val(a.id);$("#forwp_seo_image_preview").html("");});frame.open();});$(".forwp-faq-seo-image-remove").on("click",function(e){e.preventDefault();$("#forwp_seo_image").val("");$("#forwp_seo_image_preview").empty();});});}(jQuery));'
);
}
/**
* Register term meta for REST and sanitizing.
*/
public static function register_term_meta() {
if ( ! Settings::is_setup_complete() ) {
return;
}
$taxonomy = Settings::get_taxonomy();
if ( ! taxonomy_exists( $taxonomy ) ) {
return;
}
foreach (
[
self::META_DISPLAY_TITLE => __( 'Display title', '4wp-faq' ),
self::META_SEO_TITLE => __( 'SEO title', '4wp-faq' ),
self::META_SEO_DESC => __( 'SEO description', '4wp-faq' ),
] as $key => $description
) {
register_term_meta(
$taxonomy,
$key,
[
'type' => 'string',
'single' => true,
'show_in_rest' => true,
'sanitize_callback' => 'sanitize_text_field',
'auth_callback' => static function () {
return current_user_can( 'manage_categories' );
},
'description' => $description,
]
);
}
register_term_meta(
$taxonomy,
self::META_SEO_IMAGE,
[
'type' => 'integer',
'single' => true,
'show_in_rest' => true,
'sanitize_callback' => 'absint',
'auth_callback' => static function () {
return current_user_can( 'manage_categories' );
},
'description' => __( 'SEO image', '4wp-faq' ),
]
);
}
/**
* Fields on Add FAQ Category.
*/
public static function render_add_fields() {
?>
'forwp_display_title', self::META_SEO_TITLE => 'forwp_seo_title', self::META_SEO_DESC => 'forwp_seo_description', ]; foreach ( $fields as $meta_key => $post_key ) { if ( ! isset( $_POST[ $post_key ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing continue; } $value = sanitize_text_field( wp_unslash( (string) $_POST[ $post_key ] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing if ( '' === $value ) { delete_term_meta( $term_id, $meta_key ); } else { update_term_meta( $term_id, $meta_key, $value ); } } if ( isset( $_POST['forwp_seo_image'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing $image_id = absint( wp_unslash( $_POST['forwp_seo_image'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing if ( $image_id > 0 ) { update_term_meta( $term_id, self::META_SEO_IMAGE, $image_id ); } else { delete_term_meta( $term_id, self::META_SEO_IMAGE ); } } } /** * Active FAQ category term for the current request, if any. * * @return \WP_Term|null */ public static function get_active_term() { $slug = Faq_Filter::get_active_slug(); if ( '' === $slug ) { return null; } $taxonomy = Settings::get_taxonomy(); if ( ! taxonomy_exists( $taxonomy ) ) { return null; } $term = get_term_by( 'slug', $slug, $taxonomy ); return $term instanceof \WP_Term ? $term : null; } /** * Term for on-page title / description and document meta — pretty category URLs only. * * @return \WP_Term|null */ public static function get_seo_term() { if ( ! Faq_Filter::is_pretty_category_request() ) { return null; } return self::get_active_term(); } /** * On-page title: custom display title, else term name. * * @param \WP_Term $term Term. * @return string */ public static function get_display_title( $term ) { if ( ! $term instanceof \WP_Term ) { return ''; } $custom = get_term_meta( (int) $term->term_id, self::META_DISPLAY_TITLE, true ); if ( is_string( $custom ) && '' !== trim( $custom ) ) { return trim( $custom ); } return (string) $term->name; } /** * Custom SEO title when the term field is filled. * * @param \WP_Term $term Term. * @return string Empty when the field is not set. */ public static function get_custom_seo_title( $term ) { if ( ! $term instanceof \WP_Term ) { return ''; } $custom = get_term_meta( (int) $term->term_id, self::META_SEO_TITLE, true ); return is_string( $custom ) ? trim( $custom ) : ''; } /** * Document title for a category URL (custom SEO title or display title). * * @param \WP_Term $term Term. * @return string */ public static function get_seo_title( $term ) { $custom = self::get_custom_seo_title( $term ); return '' !== $custom ? $custom : self::get_display_title( $term ); } /** * Full document title: custom SEO title as-is, otherwise display title + site name. * * @param \WP_Term $term Term. * @return string */ public static function get_document_title( $term ) { $custom = self::get_custom_seo_title( $term ); if ( '' !== $custom ) { return $custom; } $seo = self::get_seo_title( $term ); $site = get_bloginfo( 'name', 'display' ); $site = is_string( $site ) ? trim( $site ) : ''; if ( '' === $seo ) { return $site; } if ( '' === $site || false !== strpos( $seo, $site ) ) { return $seo; } return $seo . ' – ' . $site; } /** * Meta description for a category URL. * * @param \WP_Term $term Term. * @return string */ public static function get_seo_description( $term ) { if ( ! $term instanceof \WP_Term ) { return ''; } $custom = get_term_meta( (int) $term->term_id, self::META_SEO_DESC, true ); return is_string( $custom ) ? trim( $custom ) : ''; } /** * Canonical / og:url for the pretty category request. * * @return string */ public static function get_pretty_canonical_url() { $term = self::get_seo_term(); if ( ! $term instanceof \WP_Term ) { return ''; } return Faq_Filter::get_category_url( $term->slug, true ); } /** * @param string $canonical Current canonical. * @param \WP_Post|null $post Queried post. * @return string */ public static function filter_canonical_url( $canonical, $post = null ) { unset( $post ); return self::prefer_pretty_canonical( $canonical ); } /** * @param string $canonical Current canonical / og:url. * @return string */ public static function filter_pretty_canonical( $canonical ) { return self::prefer_pretty_canonical( $canonical ); } /** * Replace the hub canonical with the pretty category URL, keeping scheme/host. * * @param string $canonical Current canonical. * @return string */ private static function prefer_pretty_canonical( $canonical ) { $url = self::get_pretty_canonical_url(); if ( '' === $url ) { return $canonical; } if ( is_string( $canonical ) && '' !== $canonical ) { $scheme = wp_parse_url( $canonical, PHP_URL_SCHEME ); if ( is_string( $scheme ) && '' !== $scheme ) { $url = set_url_scheme( $url, $scheme ); } } return $url; } /** * Category SEO image URL, if set. * * @param \WP_Term $term Term. * @return string */ public static function get_seo_image_url( $term ) { if ( ! $term instanceof \WP_Term ) { return ''; } $image_id = (int) get_term_meta( (int) $term->term_id, self::META_SEO_IMAGE, true ); if ( $image_id <= 0 ) { $image_id = (int) get_term_meta( (int) $term->term_id, 'thumbnail_id', true ); } if ( $image_id > 0 ) { $url = wp_get_attachment_image_url( $image_id, 'full' ); if ( is_string( $url ) && '' !== $url ) { return $url; } } if ( class_exists( '\WPSEO_Taxonomy_Meta' ) ) { $yoast = \WPSEO_Taxonomy_Meta::get_term_meta( $term, $term->taxonomy, 'opengraph-image' ); if ( is_string( $yoast ) && '' !== trim( $yoast ) ) { return trim( $yoast ); } } $rank = get_term_meta( (int) $term->term_id, 'rank_math_facebook_image', true ); if ( is_string( $rank ) && '' !== trim( $rank ) ) { return trim( $rank ); } return ''; } /** * Prefer the category image; keep the hub page image when the category has none. * * @param string $image Current og/twitter image. * @return string */ public static function filter_opengraph_image( $image ) { $term = self::get_seo_term(); if ( ! $term instanceof \WP_Term ) { return $image; } $url = self::get_seo_image_url( $term ); return '' !== $url ? $url : $image; } /** * @param string $title Current title. * @return string */ public static function filter_document_title( $title ) { $term = self::get_seo_term(); if ( ! $term instanceof \WP_Term ) { return $title; } $seo = self::get_document_title( $term ); return '' !== $seo ? $seo : $title; } /** * @param array
)(.*?)(<\/p>)/is', '$1' . $plain . '$3', $content, 1 ); return is_string( $updated ) ? $updated : $content; } if ( 'core/term-description' === $name ) { if ( ! self::is_current_or_unscoped_term_context( $parsed_block, $block, $term ) ) { return $content; } $inner = wpautop( wp_kses_post( $desc ) ); if ( ! is_string( $content ) || '' === trim( $content ) ) { return self::render_term_description_fallback( $parsed_block, $inner ); } $updated = preg_replace( '/(