settings = new Settings(); $this->audit_page = new AuditPage(); $this->tools_page = new ToolsPage(); $this->detail_page = new AttachmentDetailPage(); } /** * Attaches all WordPress hooks. * * @return void */ public function run(): void { add_action( 'init', array( $this, 'load_textdomain' ) ); add_action( 'admin_menu', array( $this, 'register_admin_pages' ) ); add_action( 'admin_init', array( $this->settings, 'register' ) ); add_action( 'admin_init', array( $this, 'check_db_version' ) ); add_action( AttachmentIndexer::AS_HOOK, array( AttachmentIndexer::class, 'process_scheduled_batch' ) ); add_action( UsageScanner::AS_HOOK, array( UsageScanner::class, 'process_scheduled_batch' ) ); add_action( ExternalScanner::AS_HOOK, array( ExternalScanner::class, 'process_scheduled_batch' ) ); add_action( 'wp_ajax_mra_run_batch', array( $this->tools_page, 'ajax_run_batch' ) ); add_filter( 'mra/external/providers', array( $this, 'register_providers' ) ); add_filter( 'wp_privacy_personal_data_exporters', array( DataExporter::class, 'register' ) ); add_filter( 'wp_privacy_personal_data_erasers', array( DataEraser::class, 'register' ) ); $this->audit_page->register_hooks(); $this->register_cli_commands(); } /** * Loads the plugin text domain. * * @return void */ public function load_textdomain(): void { load_plugin_textdomain( 'robotstxt-mediaaudit', false, dirname( plugin_basename( ROBOTSTXT_MEDIAAUDIT_PLUGIN_FILE ) ) . '/languages' ); } /** * Registers admin menu pages. * * @return void */ public function register_admin_pages(): void { $suffix = add_menu_page( __( 'Media Audit', 'robotstxt-mediaaudit' ), __( 'Media Audit', 'robotstxt-mediaaudit' ), 'edit_others_posts', 'robotstxt-mediaaudit', array( $this->audit_page, 'render' ), 'dashicons-camera', 60 ); $this->audit_page->set_hook_suffix( $suffix ); // Rename the auto-created first submenu entry. add_submenu_page( 'robotstxt-mediaaudit', __( 'Media Audit', 'robotstxt-mediaaudit' ), __( 'Media Audit', 'robotstxt-mediaaudit' ), 'edit_others_posts', 'robotstxt-mediaaudit', array( $this->audit_page, 'render' ) ); $tools_suffix = add_submenu_page( 'robotstxt-mediaaudit', __( 'Tools', 'robotstxt-mediaaudit' ), __( 'Tools', 'robotstxt-mediaaudit' ), 'manage_options', 'robotstxt-mediaaudit-tools', array( $this->tools_page, 'render' ) ); if ( is_string( $tools_suffix ) ) { $this->tools_page->set_hook_suffix( $tools_suffix ); } add_submenu_page( 'robotstxt-mediaaudit', __( 'Settings', 'robotstxt-mediaaudit' ), __( 'Settings', 'robotstxt-mediaaudit' ), 'manage_options', 'robotstxt-mediaaudit-settings', array( $this->settings, 'render' ) ); add_submenu_page( '', // hidden from menu. __( 'Attachment Report', 'robotstxt-mediaaudit' ), '', 'edit_posts', 'robotstxt-mediaaudit-detail', array( $this->detail_page, 'render' ) ); } /** * Runs pending DB migrations when the stored schema version is behind the constant. * * @return void */ public function check_db_version(): void { $raw = get_option( 'robotstxt_mediaaudit_db_version', '0.0.0' ); $stored = is_string( $raw ) ? $raw : '0.0.0'; if ( ROBOTSTXT_MEDIAAUDIT_DB_VERSION !== $stored ) { Database::run_migrations(); update_option( 'robotstxt_mediaaudit_db_version', ROBOTSTXT_MEDIAAUDIT_DB_VERSION ); } } /** * Registers built-in external providers via the mra/external/providers filter. * * @param mixed $providers Accumulated provider list. * * @return array<\MediaRightsAudit\External\AbstractProvider> */ public function register_providers( $providers ): array { $list = array(); if ( is_array( $providers ) ) { foreach ( $providers as $p ) { if ( $p instanceof AbstractProvider ) { $list[] = $p; } } } $list[] = new GoogleVisionProvider(); $list[] = new TinEyeProvider(); if ( $this->is_provider_configured( 'picdefense' ) ) { $list[] = new PicDefenseProvider(); } return $list; } /** * Returns whether a provider has its credentials configured. * * Checks provider-specific option keys in the plugin settings. * * @param string $slug Provider slug (e.g. 'picdefense'). * * @return bool */ private function is_provider_configured( string $slug ): bool { $raw = get_option( Settings::OPTION_NAME, array() ); $opts = is_array( $raw ) ? $raw : array(); if ( 'picdefense' === $slug ) { $uid = $opts['picdefense_user_id'] ?? ''; $key = $opts['picdefense_api_key'] ?? ''; return is_string( $uid ) && '' !== trim( $uid ) && is_string( $key ) && '' !== trim( $key ); } return false; } /** * Registers WP-CLI commands when running in CLI context. * * @return void */ private function register_cli_commands(): void { if ( defined( 'WP_CLI' ) && WP_CLI ) { \WP_CLI::add_command( 'mra', Command::class ); } } }