$meta ] ); } /** * Shared helper: return a standardised error result. * status_code must be one of the SPEC standard status strings. */ protected function err( string $code, string $message, string $status_code = 'error', int $http_status = 400 ): array { return [ 'error' => [ 'code' => $code, 'message' => $message, 'status_code' => $status_code ], 'http_status' => $http_status, ]; } /** * Validate required string argument. Returns sanitized value or null. */ protected function require_string( array $args, string $key ): ?string { $val = $args[ $key ] ?? null; if ( $val === null || $val === '' ) { return null; } if ( ! is_scalar( $val ) ) { return null; // Reject arrays/objects — prevents silent "Array" string coercion } return (string) $val; } /** * Validate required int argument. Returns int or null. */ protected function require_int( array $args, string $key ): ?int { $val = $args[ $key ] ?? null; if ( $val === null ) { return null; } $int = filter_var( $val, FILTER_VALIDATE_INT ); return $int === false ? null : (int) $int; } /** * wp_untrash_post(), back to the status the post had before it was trashed. Since WordPress 5.6 it comes back * as a draft by default, so a restored published page went offline (football.ehot.ro, 2026-11-02). * * @return WP_Post|false|null */ protected function untrash_to_previous_status( int $id ) { add_filter( 'wp_untrash_post_status', 'wp_untrash_post_set_previous_status', 10, 3 ); try { return wp_untrash_post( $id ); } finally { remove_filter( 'wp_untrash_post_status', 'wp_untrash_post_set_previous_status', 10 ); } } /** * Register one tool with standard module/dependency filled in. */ protected function register( string $tool_name, array $meta ): void { $meta['module'] = $this->get_module_name(); $meta['dependency'] = $meta['dependency'] ?? null; AICOM_Tool_Registry::register( $tool_name, $meta ); } }