id = $id; if ( $id > 0 ) { $this->post = get_post( $id ); } } public function get_id(): int { return $this->id; } public function get_post(): ?\WP_Post { return $this->post; } public function exists(): bool { return $this->post instanceof \WP_Post && $this->post->post_type === 'aibp_events'; } public function get( string $key, mixed $default = '' ): mixed { if ( ! $this->exists() ) { return $default; } $value = get_post_meta( $this->id, $key, true ); return $value !== '' ? $value : $default; } public function set( string $key, mixed $value ): void { update_post_meta( $this->id, $key, $value ); } public function get_status(): string { return $this->get( 'aibp_status', 'passive' ); } public function is_active(): bool { return $this->get_status() === 'active'; } public function toggle_status(): string { $new_status = $this->is_active() ? 'passive' : 'active'; $this->set( 'aibp_status', $new_status ); return $new_status; } public function get_provider_id(): string { return $this->get( 'aibp_provider', $this->get( 'aibp_ai', 'openai' ) ); } public function get_model(): string { return $this->get( 'aibp_model', '' ); } public function get_subject(): string { return $this->get( 'aibp_subject', '' ); } public function get_length(): int { return (int) $this->get( 'aibp_length', 300 ); } public function get_prompt_title(): string { return $this->get( 'aibp_prompt_title', 'Write one blog post title about [subject].' ); } public function get_prompt_content(): string { return $this->get( 'aibp_prompt_content', 'Write blog post about [subject]. Use html characters and subheadings. And content length should be [length] words.' ); } public function get_recurrence_type(): string { return $this->get( 'aibp_recurrence_type', 'interval' ); } public function get_recurrence_interval(): int { return (int) $this->get( 'aibp_recurrence_interval', 1 ); } public function get_recurrence_days(): array { $days = $this->get( 'aibp_recurrence_days', [] ); return is_array( $days ) ? $days : []; } public function get_recurrence_time(): string { return $this->get( 'aibp_recurrence_time', '09:00' ); } public function get_post_type(): string { return $this->get( 'aibp_post_type', 'post' ); } public function get_post_status(): string { return $this->get( 'aibp_post_status', 'publish' ); } public function get_categories(): array { $cats = $this->get( 'aibp_post_categories', [] ); return is_array( $cats ) ? array_map( 'intval', $cats ) : []; } public function get_temperature(): float { return (float) $this->get( 'aibp_temperature', 0.7 ); } public function get_max_tokens(): int { return (int) $this->get( 'aibp_max_tokens', 4000 ); } public function get_count(): int { return (int) $this->get( 'aibp_count', 0 ); } public function get_last_run(): string { return $this->get( 'aibp_last_run', '' ); } public function increment_run(): void { $count = $this->get_count(); $this->set( 'aibp_count', $count + 1 ); $this->set( 'aibp_last_run', gmdate( 'Y-m-d H:i:s', current_time( 'timestamp' ) ) ); } public static function create( array $data ): int|\WP_Error { $post_id = wp_insert_post( [ 'post_type' => 'aibp_events', 'post_status' => 'publish', 'post_title' => sanitize_text_field( $data['title'] ?? '' ), 'meta_input' => self::sanitize_meta( $data ), ] ); if ( is_wp_error( $post_id ) ) { return $post_id; } // Handle legacy meta key migration. if ( ! empty( $data['ai'] ) && empty( $data['provider'] ) ) { update_post_meta( $post_id, 'aibp_provider', $data['ai'] ); } return $post_id; } public function update( array $data ): bool|\WP_Error { $result = wp_update_post( [ 'ID' => $this->id, 'post_title' => sanitize_text_field( $data['title'] ?? $this->post->post_title ), ] ); if ( is_wp_error( $result ) ) { return $result; } $meta = self::sanitize_meta( $data ); foreach ( $meta as $key => $value ) { update_post_meta( $this->id, $key, $value ); } return true; } public function delete(): bool { return (bool) wp_delete_post( $this->id, true ); } public function should_run_now(): bool { if ( ! $this->is_active() ) { return false; } $type = $this->get_recurrence_type(); $time = $this->get_recurrence_time(); $now = current_time( 'timestamp' ); // Check if current time matches the scheduled time (within a 5-minute window). $scheduled_time = strtotime( 'today ' . $time ); if ( abs( $now - $scheduled_time ) > 300 ) { return false; } if ( $type === 'interval' ) { return $this->should_run_interval(); } if ( $type === 'schedule' ) { return $this->should_run_schedule(); } return false; } private function should_run_interval(): bool { $last_run = $this->get_last_run(); $interval = $this->get_recurrence_interval(); if ( empty( $last_run ) ) { return true; } $days_since = (int) floor( ( time() - strtotime( $last_run ) ) / DAY_IN_SECONDS ); return $days_since >= $interval; } private function should_run_schedule(): bool { $days = $this->get_recurrence_days(); if ( empty( $days ) ) { return false; } $day_map = [ 'sun' => 0, 'mon' => 1, 'tue' => 2, 'wed' => 3, 'thu' => 4, 'fri' => 5, 'sat' => 6, ]; $today = gmdate( 'w', current_time( 'timestamp' ) ); foreach ( $days as $day ) { if ( isset( $day_map[ $day ] ) && (int) $day_map[ $day ] === (int) $today ) { return true; } } return false; } public function to_array(): array { return [ 'id' => $this->id, 'title' => $this->post ? $this->post->post_title : '', 'status' => $this->get_status(), 'provider' => $this->get_provider_id(), 'model' => $this->get_model(), 'subject' => $this->get_subject(), 'length' => $this->get_length(), 'prompt_title' => $this->get_prompt_title(), 'prompt_content' => $this->get_prompt_content(), 'recurrence_type' => $this->get_recurrence_type(), 'recurrence_interval' => $this->get_recurrence_interval(), 'recurrence_days' => $this->get_recurrence_days(), 'recurrence_time' => $this->get_recurrence_time(), 'post_type' => $this->get_post_type(), 'post_status' => $this->get_post_status(), 'categories' => $this->get_categories(), 'temperature' => $this->get_temperature(), 'max_tokens' => $this->get_max_tokens(), 'count' => $this->get_count(), 'last_run' => $this->get_last_run(), ]; } private static function sanitize_meta( array $data ): array { $meta = []; if ( isset( $data['provider'] ) || isset( $data['ai'] ) ) { $meta['aibp_provider'] = sanitize_text_field( $data['provider'] ?? $data['ai'] ?? 'openai' ); } if ( isset( $data['model'] ) ) { $meta['aibp_model'] = sanitize_text_field( $data['model'] ); } if ( isset( $data['subject'] ) ) { $meta['aibp_subject'] = sanitize_text_field( $data['subject'] ); } if ( isset( $data['length'] ) ) { $meta['aibp_length'] = absint( $data['length'] ); } if ( isset( $data['prompt_title'] ) ) { $meta['aibp_prompt_title'] = sanitize_textarea_field( $data['prompt_title'] ); } if ( isset( $data['prompt_content'] ) ) { $meta['aibp_prompt_content'] = sanitize_textarea_field( $data['prompt_content'] ); } if ( isset( $data['recurrence_type'] ) ) { $meta['aibp_recurrence_type'] = sanitize_text_field( $data['recurrence_type'] ); } if ( isset( $data['recurrence_interval'] ) ) { $meta['aibp_recurrence_interval'] = absint( $data['recurrence_interval'] ); } if ( isset( $data['recurrence_days'] ) ) { $meta['aibp_recurrence_days'] = array_map( 'sanitize_text_field', (array) $data['recurrence_days'] ); } if ( isset( $data['recurrence_time'] ) ) { $meta['aibp_recurrence_time'] = sanitize_text_field( $data['recurrence_time'] ); } if ( isset( $data['post_type'] ) ) { $meta['aibp_post_type'] = sanitize_text_field( $data['post_type'] ); } if ( isset( $data['post_status'] ) ) { $meta['aibp_post_status'] = sanitize_text_field( $data['post_status'] ); } if ( isset( $data['categories'] ) || isset( $data['post_categories'] ) ) { $cats = $data['categories'] ?? $data['post']['categories'] ?? $data['post_categories'] ?? []; $meta['aibp_post_categories'] = array_map( 'absint', (array) $cats ); } if ( isset( $data['temperature'] ) ) { $meta['aibp_temperature'] = (float) $data['temperature']; } if ( isset( $data['max_tokens'] ) ) { $meta['aibp_max_tokens'] = absint( $data['max_tokens'] ); } return $meta; } public static function get_all( array $args = [] ): array { $defaults = [ 'post_type' => 'aibp_events', 'posts_per_page' => -1, 'orderby' => 'date', 'order' => 'DESC', ]; $query = new \WP_Query( wp_parse_args( $args, $defaults ) ); $agents = []; foreach ( $query->posts as $post ) { $agents[] = new self( $post->ID ); } wp_reset_postdata(); return $agents; } public static function count( array $args = [] ): int { $defaults = [ 'post_type' => 'aibp_events', 'posts_per_page' => -1, 'fields' => 'ids', ]; $query = new \WP_Query( wp_parse_args( $args, $defaults ) ); $count = $query->found_posts; wp_reset_postdata(); return $count; } }