robotstxt-mediaaudit/includes/Admin/Settings.php
2026-06-03 06:28:34 +00:00

486 lines
14 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
/**
* Settings page handler.
*
* @package MediaRightsAudit\Admin
*/
namespace MediaRightsAudit\Admin;
/**
* Registers and renders the plugin Settings page.
*
* Settings are stored in a single option array: robotstxt_mediaaudit_settings.
*/
class Settings {
/**
* WordPress Settings API option group name.
*/
const OPTION_GROUP = 'robotstxt_mediaaudit';
/**
* Option name in the database.
*/
const OPTION_NAME = 'robotstxt_mediaaudit_settings';
/**
* Registers all settings, sections, and fields via the WordPress Settings API.
*
* Hooked to admin_init.
*
* @return void
*/
public function register(): void {
register_setting(
self::OPTION_GROUP,
self::OPTION_NAME,
array(
'type' => 'array',
'sanitize_callback' => array( $this, 'sanitize' ),
'default' => array(),
)
);
add_settings_section(
'mra_general',
__( 'General', 'robotstxt-mediaaudit' ),
'__return_false',
'robotstxt-mediaaudit-settings'
);
add_settings_field(
'delete_on_uninstall',
__( 'Delete data on uninstall', 'robotstxt-mediaaudit' ),
array( $this, 'field_delete_on_uninstall' ),
'robotstxt-mediaaudit-settings',
'mra_general'
);
add_settings_section(
'mra_api_credentials',
__( 'API Credentials', 'robotstxt-mediaaudit' ),
'__return_false',
'robotstxt-mediaaudit-settings'
);
add_settings_field(
'google_vision_api_key',
__( 'Google Cloud Vision API Key', 'robotstxt-mediaaudit' ),
array( $this, 'field_google_vision_api_key' ),
'robotstxt-mediaaudit-settings',
'mra_api_credentials'
);
add_settings_field(
'tineye_api_key',
__( 'TinEye API Key', 'robotstxt-mediaaudit' ),
array( $this, 'field_tineye_api_key' ),
'robotstxt-mediaaudit-settings',
'mra_api_credentials'
);
add_settings_field(
'picdefense_user_id',
__( 'PicDefense User ID', 'robotstxt-mediaaudit' ),
array( $this, 'field_picdefense_user_id' ),
'robotstxt-mediaaudit-settings',
'mra_api_credentials'
);
add_settings_field(
'picdefense_api_key',
__( 'PicDefense API Key', 'robotstxt-mediaaudit' ),
array( $this, 'field_picdefense_api_key' ),
'robotstxt-mediaaudit-settings',
'mra_api_credentials'
);
add_settings_section(
'mra_external_scanning',
__( 'External Scanning', 'robotstxt-mediaaudit' ),
'__return_false',
'robotstxt-mediaaudit-settings'
);
add_settings_field(
'external_batch_size',
__( 'Batch Size', 'robotstxt-mediaaudit' ),
array( $this, 'field_external_batch_size' ),
'robotstxt-mediaaudit-settings',
'mra_external_scanning'
);
add_settings_field(
'rate_limit_per_minute',
__( 'Rate Limit (requests/min)', 'robotstxt-mediaaudit' ),
array( $this, 'field_rate_limit_per_minute' ),
'robotstxt-mediaaudit-settings',
'mra_external_scanning'
);
}
/**
* Sanitises the settings array on save.
*
* @param mixed $input Raw POST input.
*
* @return array<string, mixed>
*/
public function sanitize( $input ): array {
$output = array();
if ( ! is_array( $input ) ) {
return $output;
}
$output['delete_on_uninstall'] = ! empty( $input['delete_on_uninstall'] );
$key_val = $input['google_vision_api_key'] ?? null;
$output['google_vision_api_key'] = is_string( $key_val ) ? sanitize_text_field( $key_val ) : '';
$tineye_val = $input['tineye_api_key'] ?? null;
$output['tineye_api_key'] = is_string( $tineye_val ) ? sanitize_text_field( $tineye_val ) : '';
$pd_uid_val = $input['picdefense_user_id'] ?? null;
$output['picdefense_user_id'] = is_string( $pd_uid_val ) ? sanitize_text_field( $pd_uid_val ) : '';
$pd_key_val = $input['picdefense_api_key'] ?? null;
$output['picdefense_api_key'] = is_string( $pd_key_val ) ? sanitize_text_field( $pd_key_val ) : '';
$batch_val = $input['external_batch_size'] ?? null;
$batch = is_numeric( $batch_val ) ? (int) $batch_val : 10;
$output['external_batch_size'] = max( 1, min( 100, $batch ) );
$rl_val = $input['rate_limit_per_minute'] ?? null;
$rl = is_numeric( $rl_val ) ? (int) $rl_val : 10;
$output['rate_limit_per_minute'] = max( 1, min( 60, $rl ) );
return $output;
}
/**
* Renders the "Delete data on uninstall" checkbox field.
*
* @return void
*/
public function field_delete_on_uninstall(): void {
$options = (array) get_option( self::OPTION_NAME, array() );
$checked = ! empty( $options['delete_on_uninstall'] );
?>
<label>
<input
type="checkbox"
name="<?php echo esc_attr( self::OPTION_NAME ); ?>[delete_on_uninstall]"
value="1"
<?php checked( $checked ); ?>
/>
<?php esc_html_e( 'Remove all plugin data (tables and options) when the plugin is uninstalled.', 'robotstxt-mediaaudit' ); ?>
</label>
<p class="description">
<?php esc_html_e( 'By default, data is preserved after uninstall. Enable this only if you want a clean removal.', 'robotstxt-mediaaudit' ); ?>
</p>
<?php
}
/**
* Renders the Google Cloud Vision API key field.
*
* @return void
*/
public function field_google_vision_api_key(): void {
$options = (array) get_option( self::OPTION_NAME, array() );
$val = $options['google_vision_api_key'] ?? '';
$value = is_string( $val ) ? $val : '';
?>
<input
type="text"
id="google_vision_api_key"
name="<?php echo esc_attr( self::OPTION_NAME ); ?>[google_vision_api_key]"
value="<?php echo esc_attr( $value ); ?>"
class="regular-text"
autocomplete="off"
/>
<p class="description">
<?php esc_html_e( 'Required for Google Cloud Vision Web Detection. Obtain from the Google Cloud Console.', 'robotstxt-mediaaudit' ); ?>
&mdash;
<a href="https://cloud.google.com/vision/pricing" target="_blank" rel="noopener noreferrer">
<?php esc_html_e( 'View pricing', 'robotstxt-mediaaudit' ); ?>
</a>
</p>
<table class="mra-pricing-table">
<thead>
<tr>
<th><?php esc_html_e( 'Monthly requests', 'robotstxt-mediaaudit' ); ?></th>
<th><?php esc_html_e( 'Price per 1,000', 'robotstxt-mediaaudit' ); ?></th>
</tr>
</thead>
<tbody>
<tr>
<td><?php esc_html_e( 'First 1,000', 'robotstxt-mediaaudit' ); ?></td>
<td><?php esc_html_e( 'Free', 'robotstxt-mediaaudit' ); ?></td>
</tr>
<tr>
<td>1,001 5,000,000</td>
<td>$1.50</td>
</tr>
<tr>
<td>5,000,001+</td>
<td>$0.60</td>
</tr>
</tbody>
</table>
<?php
}
/**
* Renders the TinEye API key field.
*
* @return void
*/
public function field_tineye_api_key(): void {
$options = (array) get_option( self::OPTION_NAME, array() );
$val = $options['tineye_api_key'] ?? '';
$value = is_string( $val ) ? $val : '';
?>
<input
type="text"
id="tineye_api_key"
name="<?php echo esc_attr( self::OPTION_NAME ); ?>[tineye_api_key]"
value="<?php echo esc_attr( $value ); ?>"
class="regular-text"
autocomplete="off"
/>
<p class="description">
<?php esc_html_e( 'Required for TinEye reverse image search. Obtain from your TinEye Commercial account.', 'robotstxt-mediaaudit' ); ?>
&mdash;
<a href="https://services.tineye.com/TinEyeAPI" target="_blank" rel="noopener noreferrer">
<?php esc_html_e( 'View pricing', 'robotstxt-mediaaudit' ); ?>
</a>
</p>
<table class="mra-pricing-table">
<thead>
<tr>
<th><?php esc_html_e( 'Bundle', 'robotstxt-mediaaudit' ); ?></th>
<th><?php esc_html_e( 'Searches', 'robotstxt-mediaaudit' ); ?></th>
<th><?php esc_html_e( 'Price', 'robotstxt-mediaaudit' ); ?></th>
</tr>
</thead>
<tbody>
<tr>
<td><?php esc_html_e( 'Starter', 'robotstxt-mediaaudit' ); ?></td>
<td>500</td>
<td>$50</td>
</tr>
<tr>
<td><?php esc_html_e( 'Standard', 'robotstxt-mediaaudit' ); ?></td>
<td>5,000</td>
<td>$200</td>
</tr>
<tr>
<td><?php esc_html_e( 'Professional', 'robotstxt-mediaaudit' ); ?></td>
<td>25,000</td>
<td>$600</td>
</tr>
</tbody>
</table>
<?php
}
/**
* Renders the PicDefense User ID field.
*
* @return void
*/
public function field_picdefense_user_id(): void {
$options = (array) get_option( self::OPTION_NAME, array() );
$val = $options['picdefense_user_id'] ?? '';
$value = is_string( $val ) ? $val : '';
?>
<input
type="text"
id="picdefense_user_id"
name="<?php echo esc_attr( self::OPTION_NAME ); ?>[picdefense_user_id]"
value="<?php echo esc_attr( $value ); ?>"
class="regular-text"
autocomplete="off"
/>
<p class="description">
<?php esc_html_e( 'Required for PicDefense copyright risk analysis. Your PicDefense account user ID.', 'robotstxt-mediaaudit' ); ?>
</p>
<?php
}
/**
* Renders the PicDefense API key field.
*
* @return void
*/
public function field_picdefense_api_key(): void {
$options = (array) get_option( self::OPTION_NAME, array() );
$val = $options['picdefense_api_key'] ?? '';
$value = is_string( $val ) ? $val : '';
?>
<input
type="password"
id="picdefense_api_key"
name="<?php echo esc_attr( self::OPTION_NAME ); ?>[picdefense_api_key]"
value="<?php echo esc_attr( $value ); ?>"
class="regular-text"
autocomplete="off"
/>
<p class="description">
<?php esc_html_e( 'Required for PicDefense copyright risk analysis. Your PicDefense API key.', 'robotstxt-mediaaudit' ); ?>
&mdash;
<a href="https://picdefense.io" target="_blank" rel="noopener noreferrer">
<?php esc_html_e( 'View pricing', 'robotstxt-mediaaudit' ); ?>
</a>
</p>
<?php
}
/**
* Renders the external batch size field.
*
* @return void
*/
public function field_external_batch_size(): void {
$options = (array) get_option( self::OPTION_NAME, array() );
$raw = $options['external_batch_size'] ?? 10;
$value = is_numeric( $raw ) ? (int) $raw : 10;
?>
<input
type="number"
id="external_batch_size"
name="<?php echo esc_attr( self::OPTION_NAME ); ?>[external_batch_size]"
value="<?php echo esc_attr( (string) $value ); ?>"
min="1"
max="100"
class="small-text"
/>
<p class="description">
<?php esc_html_e( 'Number of images to scan per scheduled batch (1100). Default: 10.', 'robotstxt-mediaaudit' ); ?>
</p>
<?php
}
/**
* Renders the per-minute rate limit field.
*
* @return void
*/
public function field_rate_limit_per_minute(): void {
$options = (array) get_option( self::OPTION_NAME, array() );
$raw = $options['rate_limit_per_minute'] ?? 10;
$value = is_numeric( $raw ) ? (int) $raw : 10;
?>
<input
type="number"
id="rate_limit_per_minute"
name="<?php echo esc_attr( self::OPTION_NAME ); ?>[rate_limit_per_minute]"
value="<?php echo esc_attr( (string) $value ); ?>"
min="1"
max="60"
class="small-text"
/>
<p class="description">
<?php esc_html_e( 'Maximum API requests per minute per provider (160). Default: 10.', 'robotstxt-mediaaudit' ); ?>
</p>
<?php
}
/**
* Returns whether Google Cloud Vision is configured.
*
* @return bool
*/
private function is_google_vision_configured(): bool {
$raw = get_option( self::OPTION_NAME, array() );
$opts = is_array( $raw ) ? $raw : array();
$key = $opts['google_vision_api_key'] ?? '';
return is_string( $key ) && '' !== trim( $key );
}
/**
* Returns whether TinEye is configured.
*
* @return bool
*/
private function is_tineye_configured(): bool {
$raw = get_option( self::OPTION_NAME, array() );
$opts = is_array( $raw ) ? $raw : array();
$key = $opts['tineye_api_key'] ?? '';
return is_string( $key ) && '' !== trim( $key );
}
/**
* Returns whether PicDefense is configured.
*
* @return bool
*/
private function is_picdefense_configured(): bool {
$raw = get_option( self::OPTION_NAME, array() );
$opts = is_array( $raw ) ? $raw : array();
$uid = $opts['picdefense_user_id'] ?? '';
$key = $opts['picdefense_api_key'] ?? '';
return is_string( $uid ) && '' !== trim( $uid ) && is_string( $key ) && '' !== trim( $key );
}
/**
* Renders the Settings admin page.
*
* @return void
*/
public function render(): void {
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( esc_html__( 'You do not have permission to access this page.', 'robotstxt-mediaaudit' ) );
}
$gv_ok = $this->is_google_vision_configured();
$te_ok = $this->is_tineye_configured();
$pd_ok = $this->is_picdefense_configured();
?>
<div class="wrap">
<h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
<div class="mra-provider-status">
<strong><?php esc_html_e( 'API Credentials Status', 'robotstxt-mediaaudit' ); ?></strong>
<ul>
<li>
<?php if ( $gv_ok ) : ?>
<span class="dashicons dashicons-yes-alt" style="color:green;"></span>
<?php else : ?>
<span class="dashicons dashicons-warning" style="color:orange;"></span>
<?php endif; ?>
<?php esc_html_e( 'Google Cloud Vision', 'robotstxt-mediaaudit' ); ?>
</li>
<li>
<?php if ( $te_ok ) : ?>
<span class="dashicons dashicons-yes-alt" style="color:green;"></span>
<?php else : ?>
<span class="dashicons dashicons-warning" style="color:orange;"></span>
<?php endif; ?>
<?php esc_html_e( 'TinEye', 'robotstxt-mediaaudit' ); ?>
</li>
<li>
<?php if ( $pd_ok ) : ?>
<span class="dashicons dashicons-yes-alt" style="color:green;"></span>
<?php else : ?>
<span class="dashicons dashicons-warning" style="color:orange;"></span>
<?php endif; ?>
PicDefense
</li>
</ul>
</div>
<form method="post" action="options.php">
<?php
settings_fields( self::OPTION_GROUP );
do_settings_sections( 'robotstxt-mediaaudit-settings' );
submit_button();
?>
</form>
</div>
<?php
}
}