219 lines
5.6 KiB
PHP
219 lines
5.6 KiB
PHP
<?php
|
|
/**
|
|
* Meta Box Class
|
|
*
|
|
* Provides per-post Open Graph and social media customization fields
|
|
* in the WordPress post editor.
|
|
*
|
|
* @package ROBOTSTXT_OG
|
|
* @since 1.2.0
|
|
*/
|
|
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit; // Exit if accessed directly.
|
|
}
|
|
|
|
/**
|
|
* Class Robotstxt_OG_Meta_Box
|
|
*
|
|
* Registers and handles the Open Graph meta box in the post editor,
|
|
* and registers the underlying post meta for REST API access.
|
|
*
|
|
* @since 1.2.0
|
|
*/
|
|
class Robotstxt_OG_Meta_Box {
|
|
|
|
/**
|
|
* Initialize hooks.
|
|
*
|
|
* @since 1.2.0
|
|
*
|
|
* @return void
|
|
*/
|
|
public function init(): void {
|
|
// Register post meta for REST API access (block editor).
|
|
add_action( 'init', array( $this, 'register_post_meta' ) );
|
|
|
|
// Meta box UI is admin-only.
|
|
if ( is_admin() ) {
|
|
add_action( 'add_meta_boxes', array( $this, 'register_meta_box' ) );
|
|
add_action( 'save_post', array( $this, 'save_meta_box' ), 10, 2 );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Register custom post meta for all public post types.
|
|
*
|
|
* Exposes _og_title and _og_description via the REST API so the
|
|
* block editor can read and write them via useEntityProp.
|
|
*
|
|
* @since 1.2.0
|
|
*
|
|
* @return void
|
|
*/
|
|
public function register_post_meta(): void {
|
|
$post_types = get_post_types( array( 'public' => true ), 'names' );
|
|
|
|
foreach ( $post_types as $post_type ) {
|
|
register_post_meta(
|
|
$post_type,
|
|
'_og_title',
|
|
array(
|
|
'type' => 'string',
|
|
'single' => true,
|
|
'sanitize_callback' => 'sanitize_text_field',
|
|
'auth_callback' => static function () {
|
|
return current_user_can( 'edit_posts' );
|
|
},
|
|
'show_in_rest' => true,
|
|
)
|
|
);
|
|
|
|
register_post_meta(
|
|
$post_type,
|
|
'_og_description',
|
|
array(
|
|
'type' => 'string',
|
|
'single' => true,
|
|
'sanitize_callback' => 'sanitize_textarea_field',
|
|
'auth_callback' => static function () {
|
|
return current_user_can( 'edit_posts' );
|
|
},
|
|
'show_in_rest' => true,
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Register the meta box for all public post types.
|
|
*
|
|
* @since 1.2.0
|
|
*
|
|
* @return void
|
|
*/
|
|
public function register_meta_box(): void {
|
|
$post_types = get_post_types( array( 'public' => true ), 'names' );
|
|
|
|
foreach ( $post_types as $post_type ) {
|
|
add_meta_box(
|
|
'robotstxt-og-meta-box',
|
|
__( 'Open Graph / Social Media', 'robotstxt-og' ),
|
|
array( $this, 'render_meta_box' ),
|
|
$post_type,
|
|
'normal',
|
|
'default'
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Render the meta box HTML.
|
|
*
|
|
* @since 1.2.0
|
|
*
|
|
* @param WP_Post $post The current post object.
|
|
* @return void
|
|
*/
|
|
public function render_meta_box( WP_Post $post ): void {
|
|
wp_nonce_field( 'robotstxt_og_meta_box', 'robotstxt_og_meta_box_nonce' );
|
|
|
|
$og_title = (string) get_post_meta( $post->ID, '_og_title', true );
|
|
$og_description = (string) get_post_meta( $post->ID, '_og_description', true );
|
|
|
|
?>
|
|
<table class="form-table" role="presentation">
|
|
<tbody>
|
|
<tr>
|
|
<th scope="row">
|
|
<label for="robotstxt_og_title">
|
|
<?php esc_html_e( 'Custom Title', 'robotstxt-og' ); ?>
|
|
</label>
|
|
</th>
|
|
<td>
|
|
<input
|
|
type="text"
|
|
id="robotstxt_og_title"
|
|
name="robotstxt_og_title"
|
|
value="<?php echo esc_attr( $og_title ); ?>"
|
|
class="large-text"
|
|
/>
|
|
<p class="description">
|
|
<?php esc_html_e( 'Overrides the default og:title for this post. Leave blank to use the post title automatically.', 'robotstxt-og' ); ?>
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row">
|
|
<label for="robotstxt_og_description">
|
|
<?php esc_html_e( 'Custom Description', 'robotstxt-og' ); ?>
|
|
</label>
|
|
</th>
|
|
<td>
|
|
<textarea
|
|
id="robotstxt_og_description"
|
|
name="robotstxt_og_description"
|
|
class="large-text"
|
|
rows="3"
|
|
><?php echo esc_textarea( $og_description ); ?></textarea>
|
|
<p class="description">
|
|
<?php esc_html_e( 'Overrides the default og:description for this post. Leave blank to use the excerpt automatically.', 'robotstxt-og' ); ?>
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<?php
|
|
}
|
|
|
|
/**
|
|
* Save meta box values on post save.
|
|
*
|
|
* @since 1.2.0
|
|
*
|
|
* @param int $post_id The post ID.
|
|
* @param WP_Post $post The post object.
|
|
* @return void
|
|
*/
|
|
public function save_meta_box( int $post_id, WP_Post $post ): void {
|
|
// Skip autosaves and revisions.
|
|
if ( wp_is_post_autosave( $post_id ) || wp_is_post_revision( $post_id ) ) {
|
|
return;
|
|
}
|
|
|
|
// Verify nonce.
|
|
$nonce_raw = filter_input( INPUT_POST, 'robotstxt_og_meta_box_nonce', FILTER_SANITIZE_SPECIAL_CHARS );
|
|
$nonce = $nonce_raw ? sanitize_text_field( wp_unslash( $nonce_raw ) ) : '';
|
|
|
|
if ( ! wp_verify_nonce( $nonce, 'robotstxt_og_meta_box' ) ) {
|
|
return;
|
|
}
|
|
|
|
// Check permissions.
|
|
$post_type_obj = get_post_type_object( $post->post_type );
|
|
|
|
if ( ! $post_type_obj || ! current_user_can( $post_type_obj->cap->edit_post, $post_id ) ) {
|
|
return;
|
|
}
|
|
|
|
// Save og:title.
|
|
$og_title_raw = filter_input( INPUT_POST, 'robotstxt_og_title', FILTER_SANITIZE_SPECIAL_CHARS );
|
|
$og_title = $og_title_raw ? sanitize_text_field( wp_unslash( $og_title_raw ) ) : '';
|
|
|
|
if ( empty( $og_title ) ) {
|
|
delete_post_meta( $post_id, '_og_title' );
|
|
} else {
|
|
update_post_meta( $post_id, '_og_title', $og_title );
|
|
}
|
|
|
|
// Save og:description.
|
|
$og_desc_raw = filter_input( INPUT_POST, 'robotstxt_og_description', FILTER_UNSAFE_RAW );
|
|
$og_desc = $og_desc_raw ? sanitize_textarea_field( wp_unslash( $og_desc_raw ) ) : '';
|
|
|
|
if ( empty( $og_desc ) ) {
|
|
delete_post_meta( $post_id, '_og_description' );
|
|
} else {
|
|
update_post_meta( $post_id, '_og_description', $og_desc );
|
|
}
|
|
}
|
|
}
|