415 lines
14 KiB
PHP
415 lines
14 KiB
PHP
<?php
|
|
/**
|
|
* Admin Settings Page View
|
|
*
|
|
* Template for the OpenGraph settings page with tab navigation.
|
|
*
|
|
* @package ROBOTSTXT_OG
|
|
* @since 1.0.0
|
|
*/
|
|
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit; // Exit if accessed directly.
|
|
}
|
|
|
|
// phpcs:disable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
|
|
|
|
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
|
$tab_raw = isset( $_GET['tab'] ) && is_string( $_GET['tab'] ) ? $_GET['tab'] : '';
|
|
$active_tab = $tab_raw ? sanitize_key( wp_unslash( $tab_raw ) ) : 'settings';
|
|
$valid_tabs = array( 'settings', 'tools', 'diagnostics' );
|
|
|
|
if ( ! in_array( $active_tab, $valid_tabs, true ) ) {
|
|
$active_tab = 'settings';
|
|
}
|
|
|
|
$page_url = admin_url( 'options-general.php?page=robotstxt-og-settings' );
|
|
?>
|
|
|
|
<div class="wrap">
|
|
<h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
|
|
|
|
<?php settings_errors( 'robotstxt_og_messages' ); ?>
|
|
|
|
<?php if ( ! Robotstxt_OG_Manager_Notice::is_manager_active() ) : ?>
|
|
<div class="notice notice-warning">
|
|
<p>
|
|
<?php
|
|
echo wp_kses_post(
|
|
sprintf(
|
|
/* translators: %s: Manager (by ROBOTSTXT) plugin page URL. */
|
|
__( 'To receive plugin updates, the <a href="%s">Manager (by ROBOTSTXT)</a> plugin must be installed and active.', 'robotstxt-og' ),
|
|
esc_url( Robotstxt_OG_Manager_Notice::MANAGER_URL )
|
|
)
|
|
);
|
|
?>
|
|
</p>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<nav class="nav-tab-wrapper" aria-label="<?php esc_attr_e( 'Settings tabs', 'robotstxt-og' ); ?>">
|
|
<a href="<?php echo esc_url( add_query_arg( 'tab', 'settings', $page_url ) ); ?>"
|
|
class="nav-tab <?php echo 'settings' === $active_tab ? 'nav-tab-active' : ''; ?>">
|
|
<?php esc_html_e( 'Settings', 'robotstxt-og' ); ?>
|
|
</a>
|
|
<a href="<?php echo esc_url( add_query_arg( 'tab', 'tools', $page_url ) ); ?>"
|
|
class="nav-tab <?php echo 'tools' === $active_tab ? 'nav-tab-active' : ''; ?>">
|
|
<?php esc_html_e( 'Tools', 'robotstxt-og' ); ?>
|
|
</a>
|
|
<a href="<?php echo esc_url( add_query_arg( 'tab', 'diagnostics', $page_url ) ); ?>"
|
|
class="nav-tab <?php echo 'diagnostics' === $active_tab ? 'nav-tab-active' : ''; ?>">
|
|
<?php esc_html_e( 'Diagnostics', 'robotstxt-og' ); ?>
|
|
</a>
|
|
</nav>
|
|
|
|
<div class="tab-content" style="margin-top: 1em;">
|
|
|
|
<?php if ( 'settings' === $active_tab ) : ?>
|
|
|
|
<form method="post" action="options.php">
|
|
<?php
|
|
settings_fields( 'robotstxt_og_settings' );
|
|
do_settings_sections( 'robotstxt-og-settings' );
|
|
submit_button( __( 'Save Settings', 'robotstxt-og' ) );
|
|
?>
|
|
</form>
|
|
|
|
<?php elseif ( 'tools' === $active_tab ) : ?>
|
|
|
|
<h2><?php esc_html_e( 'Cache Management', 'robotstxt-og' ); ?></h2>
|
|
|
|
<p><?php esc_html_e( 'Use these tools to manage cached fallback image URLs.', 'robotstxt-og' ); ?></p>
|
|
|
|
<table class="form-table" role="presentation">
|
|
<tbody>
|
|
<tr>
|
|
<th scope="row">
|
|
<?php esc_html_e( 'Clear All Caches', 'robotstxt-og' ); ?>
|
|
</th>
|
|
<td>
|
|
<a href="
|
|
<?php
|
|
echo esc_url(
|
|
wp_nonce_url(
|
|
add_query_arg(
|
|
array(
|
|
'robotstxt_og_clear_cache' => '1',
|
|
'tab' => 'tools',
|
|
),
|
|
$page_url
|
|
),
|
|
'robotstxt_og_clear_cache'
|
|
)
|
|
);
|
|
?>
|
|
" class="button">
|
|
<?php esc_html_e( 'Clear All Cached URLs', 'robotstxt-og' ); ?>
|
|
</a>
|
|
<p class="description">
|
|
<?php esc_html_e( 'Delete all cached fallback URLs. Images will be re-resolved on next page view.', 'robotstxt-og' ); ?>
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row">
|
|
<?php esc_html_e( 'Re-resolve All Images', 'robotstxt-og' ); ?>
|
|
</th>
|
|
<td>
|
|
<a href="
|
|
<?php
|
|
echo esc_url(
|
|
wp_nonce_url(
|
|
add_query_arg(
|
|
array(
|
|
'robotstxt_og_resolve_all' => '1',
|
|
'tab' => 'tools',
|
|
),
|
|
$page_url
|
|
),
|
|
'robotstxt_og_resolve_all'
|
|
)
|
|
);
|
|
?>
|
|
" class="button">
|
|
<?php esc_html_e( 'Re-resolve All Images Now', 'robotstxt-og' ); ?>
|
|
</a>
|
|
<p class="description">
|
|
<?php esc_html_e( 'Clear cache and immediately re-resolve all posts with featured images. May take time on large sites.', 'robotstxt-og' ); ?>
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
<h2 style="margin-top: 2em;"><?php esc_html_e( 'Plugin Information', 'robotstxt-og' ); ?></h2>
|
|
|
|
<table class="form-table" role="presentation">
|
|
<tbody>
|
|
<tr>
|
|
<th scope="row"><?php esc_html_e( 'Version', 'robotstxt-og' ); ?></th>
|
|
<td><code><?php echo esc_html( ROBOTSTXT_OG_VERSION ); ?></code></td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row"><?php esc_html_e( 'Documentation', 'robotstxt-og' ); ?></th>
|
|
<td>
|
|
<a href="https://git.robotstxt.es/ROBOTSTXT/robotstxt-og" target="_blank" rel="noopener noreferrer">
|
|
<?php esc_html_e( 'View Documentation', 'robotstxt-og' ); ?>
|
|
</a>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row"><?php esc_html_e( 'Support', 'robotstxt-og' ); ?></th>
|
|
<td>
|
|
<a href="https://git.robotstxt.es/ROBOTSTXT/robotstxt-og/issues" target="_blank" rel="noopener noreferrer">
|
|
<?php esc_html_e( 'Report an Issue', 'robotstxt-og' ); ?>
|
|
</a>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
<?php elseif ( 'diagnostics' === $active_tab ) : ?>
|
|
|
|
<?php
|
|
global $wpdb;
|
|
|
|
// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
|
|
// Diagnostics page requires live data — caching would show stale counts.
|
|
$total_cached = (int) $wpdb->get_var(
|
|
$wpdb->prepare(
|
|
"SELECT COUNT(*) FROM {$wpdb->postmeta} WHERE meta_key = %s",
|
|
'_og_image_fallback_url'
|
|
)
|
|
);
|
|
|
|
$total_with_thumbnail = (int) $wpdb->get_var(
|
|
$wpdb->prepare(
|
|
"SELECT COUNT(*) FROM {$wpdb->postmeta} WHERE meta_key = %s",
|
|
'_thumbnail_id'
|
|
)
|
|
);
|
|
|
|
$posts_per_page = 20;
|
|
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
|
$paged_raw = isset( $_GET['paged'] ) && is_string( $_GET['paged'] ) ? $_GET['paged'] : '';
|
|
$current_page = $paged_raw ? max( 1, absint( $paged_raw ) ) : 1;
|
|
$offset = ( $current_page - 1 ) * $posts_per_page;
|
|
$total_pages = (int) ceil( $total_cached / $posts_per_page );
|
|
|
|
$cached_entries = $wpdb->get_results(
|
|
$wpdb->prepare(
|
|
"SELECT pm.post_id, pm.meta_value as fallback_url, p.post_title, p.post_type
|
|
FROM {$wpdb->postmeta} pm
|
|
INNER JOIN {$wpdb->posts} p ON p.ID = pm.post_id
|
|
WHERE pm.meta_key = %s
|
|
ORDER BY pm.post_id DESC
|
|
LIMIT %d OFFSET %d",
|
|
'_og_image_fallback_url',
|
|
$posts_per_page,
|
|
$offset
|
|
)
|
|
);
|
|
// phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
|
|
?>
|
|
|
|
<h2><?php esc_html_e( 'Statistics', 'robotstxt-og' ); ?></h2>
|
|
|
|
<table class="widefat striped" style="max-width: 480px;">
|
|
<tbody>
|
|
<tr>
|
|
<th><?php esc_html_e( 'Posts with featured images', 'robotstxt-og' ); ?></th>
|
|
<td><?php echo absint( $total_with_thumbnail ); ?></td>
|
|
</tr>
|
|
<tr>
|
|
<th><?php esc_html_e( 'Posts with cached fallback URLs', 'robotstxt-og' ); ?></th>
|
|
<td><?php echo absint( $total_cached ); ?></td>
|
|
</tr>
|
|
<tr>
|
|
<th><?php esc_html_e( 'Coverage', 'robotstxt-og' ); ?></th>
|
|
<td>
|
|
<?php
|
|
if ( $total_with_thumbnail > 0 ) {
|
|
echo esc_html( number_format_i18n( ( $total_cached / $total_with_thumbnail ) * 100, 1 ) ) . '%';
|
|
} else {
|
|
esc_html_e( 'N/A', 'robotstxt-og' );
|
|
}
|
|
?>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
<h2 style="margin-top: 2em;"><?php esc_html_e( 'Test URL', 'robotstxt-og' ); ?></h2>
|
|
|
|
<p><?php esc_html_e( 'Test whether a URL is reachable via HTTP HEAD request.', 'robotstxt-og' ); ?></p>
|
|
|
|
<form method="get" action="<?php echo esc_url( $page_url ); ?>">
|
|
<input type="hidden" name="page" value="robotstxt-og-settings" />
|
|
<input type="hidden" name="tab" value="diagnostics" />
|
|
<?php wp_nonce_field( 'robotstxt_og_test_url', '_wpnonce', false ); ?>
|
|
<table class="form-table" role="presentation">
|
|
<tr>
|
|
<th scope="row">
|
|
<label for="test_url"><?php esc_html_e( 'URL to test', 'robotstxt-og' ); ?></label>
|
|
</th>
|
|
<td>
|
|
<?php
|
|
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
|
$test_url_input = isset( $_GET['test_url'] ) && is_string( $_GET['test_url'] ) ? $_GET['test_url'] : '';
|
|
$test_url_raw = $test_url_input ? esc_url_raw( wp_unslash( $test_url_input ) ) : '';
|
|
?>
|
|
<input
|
|
type="url"
|
|
id="test_url"
|
|
name="test_url"
|
|
value="<?php echo esc_attr( $test_url_raw ); ?>"
|
|
class="regular-text"
|
|
placeholder="https://example.com/image.jpg"
|
|
/>
|
|
<?php submit_button( __( 'Test URL', 'robotstxt-og' ), 'secondary', 'submit', false ); ?>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</form>
|
|
|
|
<?php
|
|
if ( ! empty( $test_url_raw ) ) {
|
|
$nonce_raw = filter_input( INPUT_GET, '_wpnonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
|
|
$nonce = $nonce_raw ? sanitize_text_field( wp_unslash( $nonce_raw ) ) : '';
|
|
|
|
if ( wp_verify_nonce( $nonce, 'robotstxt_og_test_url' ) ) {
|
|
$response = wp_remote_head(
|
|
$test_url_raw,
|
|
array(
|
|
'timeout' => 5,
|
|
'user-agent' => 'WordPress/' . get_bloginfo( 'version' ) . '; ' . get_bloginfo( 'url' ),
|
|
)
|
|
);
|
|
|
|
echo '<h3>' . esc_html__( 'Test Result', 'robotstxt-og' ) . '</h3>';
|
|
|
|
if ( is_wp_error( $response ) ) {
|
|
echo '<div class="notice notice-error inline"><p><strong>';
|
|
esc_html_e( 'Error:', 'robotstxt-og' );
|
|
echo '</strong> ' . esc_html( $response->get_error_message() ) . '</p></div>';
|
|
} else {
|
|
$http_code = (int) wp_remote_retrieve_response_code( $response );
|
|
$http_message = wp_remote_retrieve_response_message( $response );
|
|
$notice_type = ( $http_code >= 200 && $http_code < 300 ) ? 'success' : 'error';
|
|
|
|
echo '<div class="notice notice-' . esc_attr( $notice_type ) . ' inline"><p>';
|
|
echo '<strong>' . esc_html__( 'HTTP Status:', 'robotstxt-og' ) . '</strong> ';
|
|
echo esc_html( $http_code . ' ' . $http_message ) . '</p></div>';
|
|
|
|
$headers = wp_remote_retrieve_headers( $response );
|
|
if ( ! empty( $headers ) ) {
|
|
echo '<table class="widefat striped" style="max-width:600px;margin-top:10px;">';
|
|
echo '<thead><tr><th>' . esc_html__( 'Header', 'robotstxt-og' ) . '</th>';
|
|
echo '<th>' . esc_html__( 'Value', 'robotstxt-og' ) . '</th></tr></thead><tbody>';
|
|
foreach ( $headers as $header_key => $header_value ) {
|
|
echo '<tr><td><code>' . esc_html( $header_key ) . '</code></td>';
|
|
if ( is_array( $header_value ) ) {
|
|
$display_value = implode( ', ', array_map( static fn( $v ) => is_scalar( $v ) ? (string) $v : '', $header_value ) );
|
|
} elseif ( is_string( $header_value ) ) {
|
|
$display_value = $header_value;
|
|
} else {
|
|
$display_value = '';
|
|
}
|
|
echo '<td>' . esc_html( $display_value ) . '</td></tr>';
|
|
}
|
|
echo '</tbody></table>';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
?>
|
|
|
|
<h2 style="margin-top:2em;">
|
|
<?php
|
|
/* translators: %d: total entries */
|
|
printf( esc_html__( 'Cached Fallback URLs (%d)', 'robotstxt-og' ), absint( $total_cached ) );
|
|
?>
|
|
</h2>
|
|
|
|
<?php if ( empty( $cached_entries ) ) : ?>
|
|
<p><?php esc_html_e( 'No cached fallback URLs found.', 'robotstxt-og' ); ?></p>
|
|
<?php else : ?>
|
|
|
|
<table class="widefat striped">
|
|
<thead>
|
|
<tr>
|
|
<th><?php esc_html_e( 'Post ID', 'robotstxt-og' ); ?></th>
|
|
<th><?php esc_html_e( 'Title', 'robotstxt-og' ); ?></th>
|
|
<th><?php esc_html_e( 'Type', 'robotstxt-og' ); ?></th>
|
|
<th><?php esc_html_e( 'Cached Fallback URL', 'robotstxt-og' ); ?></th>
|
|
<th><?php esc_html_e( 'Actions', 'robotstxt-og' ); ?></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ( $cached_entries as $cached_entry ) : ?>
|
|
<tr>
|
|
<td><?php echo absint( $cached_entry->post_id ); ?></td>
|
|
<td>
|
|
<a href="<?php echo esc_url( get_edit_post_link( $cached_entry->post_id ) ?? '' ); ?>">
|
|
<?php echo esc_html( $cached_entry->post_title ); ?>
|
|
</a>
|
|
</td>
|
|
<td><code><?php echo esc_html( $cached_entry->post_type ); ?></code></td>
|
|
<td style="word-break:break-all;">
|
|
<a href="<?php echo esc_url( $cached_entry->fallback_url ); ?>" target="_blank" rel="noopener noreferrer">
|
|
<?php echo esc_html( $cached_entry->fallback_url ); ?>
|
|
</a>
|
|
</td>
|
|
<td>
|
|
<a href="
|
|
<?php
|
|
echo esc_url(
|
|
wp_nonce_url(
|
|
add_query_arg(
|
|
array(
|
|
'robotstxt_og_clear_single' => $cached_entry->post_id,
|
|
'tab' => 'diagnostics',
|
|
),
|
|
$page_url
|
|
),
|
|
'robotstxt_og_clear_single_' . $cached_entry->post_id
|
|
)
|
|
);
|
|
?>
|
|
" class="button button-small">
|
|
<?php esc_html_e( 'Clear', 'robotstxt-og' ); ?>
|
|
</a>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
|
|
<?php if ( $total_pages > 1 ) : ?>
|
|
<div class="tablenav bottom">
|
|
<div class="tablenav-pages">
|
|
<?php
|
|
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
|
echo paginate_links(
|
|
array(
|
|
'base' => add_query_arg( 'paged', '%#%' ),
|
|
'format' => '',
|
|
'current' => $current_page,
|
|
'total' => $total_pages,
|
|
'prev_text' => '«',
|
|
'next_text' => '»',
|
|
)
|
|
);
|
|
?>
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php endif; ?>
|
|
|
|
<?php endif; ?>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<?php // phpcs:enable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound ?>
|