rules = $rules; } public static function sanitize_status( $status ) { $status = sanitize_key( (string) $status ); return in_array( $status, self::STATUSES, true ) ? $status : ''; } public function supports( $post_id ) { return in_array( get_post_type( $post_id ), self::SUPPORTED_POST_TYPES, true ); } public function get_status( $post_id ) { if ( ! $this->supports( $post_id ) || ! metadata_exists( 'post', $post_id, self::META_KEY ) ) { return 'unchecked'; } $status = self::sanitize_status( get_post_meta( $post_id, self::META_KEY, true ) ); return $status ?: 'unchecked'; } public function set_status( $post_id, $status ) { $post_id = absint( $post_id ); $status = self::sanitize_status( $status ); if ( ! $post_id || ! $status || ! $this->supports( $post_id ) ) { return new WP_Error( 'aiparently_invalid_classification', __( 'Invalid content or AI status.', 'aiparently' ) ); } $result = update_post_meta( $post_id, self::META_KEY, $status ); if ( false === $result && $status !== get_post_meta( $post_id, self::META_KEY, true ) ) { return new WP_Error( 'aiparently_save_failed', __( 'The AI status could not be saved.', 'aiparently' ) ); } do_action( 'aiparently_classification_changed', $post_id, $status ); return true; } public function get_decision( $post_id ) { $status = $this->get_status( $post_id ); return $this->rules->evaluate( $status, array( 'post_id' => absint( $post_id ), 'post_type' => get_post_type( $post_id ), ) ); } public function check_content( $post_id ) { if ( ! $this->supports( $post_id ) ) { return new WP_Error( 'aiparently_not_supported', __( 'This content type is not supported.', 'aiparently' ) ); } return array( 'post_id' => absint( $post_id ), 'classification' => $this->get_status( $post_id ), 'disclosure' => $this->get_decision( $post_id ), ); } public function list_content( $args = array() ) { $defaults = array( 'post_type' => self::SUPPORTED_POST_TYPES, 'post_status' => array( 'publish', 'draft', 'pending', 'private', 'inherit' ), 'posts_per_page' => 20, 'paged' => 1, 'orderby' => 'modified', 'order' => 'DESC', 'status' => '', ); $args = wp_parse_args( $args, $defaults ); $status = sanitize_key( (string) $args['status'] ); unset( $args['status'] ); if ( 'unchecked' === $status ) { // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Classification is intentionally stored as post meta and indexed by WordPress. $args['meta_query'] = array( array( 'key' => self::META_KEY, 'compare' => 'NOT EXISTS' ), ); } elseif ( in_array( $status, self::STATUSES, true ) ) { // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Classification is intentionally stored as post meta and queried through WP_Query. $args['meta_key'] = self::META_KEY; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value -- Classification is intentionally stored as post meta and queried through WP_Query. $args['meta_value'] = $status; } return new WP_Query( $args ); } public function get_counts( $args = array() ) { $counts = array(); foreach ( array( 'none', 'assisted', 'generated', 'unchecked' ) as $status ) { $query = $this->list_content( array_merge( $args, array( 'status' => $status, 'posts_per_page' => 1, 'fields' => 'ids', 'no_found_rows' => false, ) ) ); $counts[ $status ] = (int) $query->found_posts; } $counts['reviewed'] = $counts['none'] + $counts['assisted'] + $counts['generated']; return $counts; } }