getInputs(); $event_id = $inputs['event_id'] ?? '?'; $changed_parts = []; if ( ! empty( $inputs['title'] ) ) { $changed_parts[] = "title to \"{$inputs['title']}\""; } if ( ! empty( $inputs['start_date'] ) ) { $changed_parts[] = "start date to {$inputs['start_date']}"; } if ( ! empty( $inputs['end_date'] ) ) { $changed_parts[] = "end date to {$inputs['end_date']}"; } if ( ! empty( $inputs['start_time'] ) ) { $changed_parts[] = 'start time to ' . substr( $inputs['start_time'], 0, 5 ); } if ( ! empty( $inputs['end_time'] ) ) { $changed_parts[] = 'end time to ' . substr( $inputs['end_time'], 0, 5 ); } $summary = "Update event #{$event_id}"; if ( ! empty( $changed_parts ) ) { $summary .= ': ' . implode( ', ', $changed_parts ); } return $summary; } /** * Human-readable version of tool inputs for the approval card. * Event fields (title, dates) are already human-readable. * Resolves category_ids and tag_ids to names. * * @return array */ public function get_approval_inputs(): array { $inputs = $this->getInputs(); if ( ! empty( $inputs['category_ids'] ) ) { $category_ids_raw = $inputs['category_ids']; unset( $inputs['category_ids'] ); $ids = array_filter( array_map( 'intval', explode( ',', (string) $category_ids_raw ) ) ); $names = []; foreach ( $ids as $id ) { $term = get_term( $id, 'etn_category' ); if ( $term && ! is_wp_error( $term ) ) { $names[] = $term->name . ' (ID: ' . $id . ')'; } else { $names[] = 'ID: ' . $id; } } if ( ! empty( $names ) ) { $inputs['categories'] = implode( ', ', $names ); } } if ( ! empty( $inputs['tag_ids'] ) ) { $tag_ids_raw = $inputs['tag_ids']; unset( $inputs['tag_ids'] ); $ids = array_filter( array_map( 'intval', explode( ',', (string) $tag_ids_raw ) ) ); $names = []; foreach ( $ids as $id ) { $term = get_term( $id, 'etn_tags' ); if ( $term && ! is_wp_error( $term ) ) { $names[] = $term->name . ' (ID: ' . $id . ')'; } else { $names[] = 'ID: ' . $id; } } if ( ! empty( $names ) ) { $inputs['tags'] = implode( ', ', $names ); } } return $inputs; } /** * Execute the tool * * @param int $event_id ID of the event to update. * @param string|null $title New title. * @param string|null $timezone New timezone. * @param string|null $start_date New start date (YYYY-MM-DD). * @param string|null $end_date New end date (YYYY-MM-DD). * @param string|null $start_time New start time (HH:MM:SS). * @param string|null $end_time New end time (HH:MM:SS). * @param string|null $description New description. * @param string|null $location New location text. * @param string|null $event_type New event type. * @param string|null $category_ids Comma-separated category IDs. * @param string|null $tag_ids Comma-separated tag IDs. * @return array */ public function __invoke( int $event_id, ?string $title = null, ?string $timezone = null, ?string $start_date = null, ?string $end_date = null, ?string $start_time = null, ?string $end_time = null, ?string $description = null, ?string $location = null, ?string $event_type = null, ?string $category_ids = null, ?string $tag_ids = null ): array { $check = $this->guard( 'etn_manage_event' ); if ( $check ) { return $check; } try { if ( $event_id <= 0 ) { return [ 'error' => 'event_id must be a positive integer.' ]; } $post = get_post( $event_id ); if ( ! $post || 'etn' !== $post->post_type ) { return [ 'error' => "No Eventin event found with ID {$event_id}." ]; } $updated_fields = []; if ( null !== $title ) { $updated_fields[] = 'title'; } if ( null !== $description ) { $updated_fields[] = 'description'; } if ( null !== $start_date ) { $parsed = \DateTime::createFromFormat( 'Y-m-d', $start_date ); if ( ! $parsed || $parsed->format( 'Y-m-d' ) !== $start_date ) { return [ 'error' => 'start_date must be in YYYY-MM-DD format.' ]; } $updated_fields[] = 'start_date'; } if ( null !== $end_date ) { $parsed = \DateTime::createFromFormat( 'Y-m-d', $end_date ); if ( ! $parsed || $parsed->format( 'Y-m-d' ) !== $end_date ) { return [ 'error' => 'end_date must be in YYYY-MM-DD format.' ]; } $updated_fields[] = 'end_date'; } if ( null !== $start_time ) { $parsed = \DateTime::createFromFormat( 'H:i:s', $start_time ); if ( ! $parsed || $parsed->format( 'H:i:s' ) !== $start_time ) { return [ 'error' => 'start_time must be in HH:MM:SS format (24-hour).' ]; } $updated_fields[] = 'start_time'; } if ( null !== $end_time ) { $parsed = \DateTime::createFromFormat( 'H:i:s', $end_time ); if ( ! $parsed || $parsed->format( 'H:i:s' ) !== $end_time ) { return [ 'error' => 'end_time must be in HH:MM:SS format (24-hour).' ]; } $updated_fields[] = 'end_time'; } if ( null !== $timezone ) { try { new \DateTimeZone( $timezone ); } catch ( \Exception $tz_e ) { return [ 'error' => "Invalid timezone '{$timezone}'." ]; } $updated_fields[] = 'timezone'; } if ( null !== $location ) { $updated_fields[] = 'location'; } if ( null !== $event_type ) { $normalized = self::normalize_event_type( $event_type ); if ( null === $normalized ) { return [ 'error' => "Invalid event_type '{$event_type}'. Allowed: offline, online, hybrid." ]; } $event_type = $normalized; $updated_fields[] = 'event_type'; } if ( null !== $category_ids ) { $updated_fields[] = 'categories'; } if ( null !== $tag_ids ) { $updated_fields[] = 'tags'; } // Hydrate required fields from existing post meta (etn_validate requires all 6). $body = [ 'title' => get_the_title( $event_id ), 'timezone' => get_post_meta( $event_id, 'event_timezone', true ) ?: 'UTC', 'start_date' => get_post_meta( $event_id, 'etn_start_date', true ) ?: gmdate( 'Y-m-d' ), 'end_date' => get_post_meta( $event_id, 'etn_end_date', true ) ?: gmdate( 'Y-m-d' ), 'start_time' => get_post_meta( $event_id, 'etn_start_time', true ) ?: '00:00:00', 'end_time' => get_post_meta( $event_id, 'etn_end_time', true ) ?: '00:00:00', // Omit ticket_variations: Eventin's isset() guard would treat a sent [] as delete-all. ]; // Overlay only explicitly-provided fields. if ( null !== $title ) { $body['title'] = sanitize_text_field( $title ); } if ( null !== $description ) { $body['description'] = wp_kses_post( $description ); } if ( null !== $start_date ) { $body['start_date'] = $start_date; } if ( null !== $end_date ) { $body['end_date'] = $end_date; } if ( null !== $start_time ) { $body['start_time'] = $start_time; } if ( null !== $end_time ) { $body['end_time'] = $end_time; } if ( null !== $timezone ) { $body['timezone'] = sanitize_text_field( $timezone ); } if ( null !== $location ) { $body['location'] = [ 'address' => sanitize_text_field( $location ) ]; } if ( null !== $event_type ) { $body['event_type'] = $event_type; } if ( null !== $category_ids ) { $ids = array_filter( array_map( 'intval', explode( ',', $category_ids ) ) ); $body['categories'] = array_values( $ids ); } if ( null !== $tag_ids ) { $ids = array_filter( array_map( 'intval', explode( ',', $tag_ids ) ) ); $body['tags'] = array_values( $ids ); } $request = new \WP_REST_Request( 'POST' ); $request->set_header( 'content-type', 'application/json' ); $request->set_body( wp_json_encode( $body ) ); $request->set_url_params( [ 'id' => $event_id ] ); $controller = new \Eventin\Event\Api\EventController(); $response = $controller->update_item( $request ); if ( is_wp_error( $response ) ) { return [ 'error' => $response->get_error_message() ]; } return [ 'success' => true, 'event_id' => $event_id, 'updated_fields' => $updated_fields, 'edit_url' => get_edit_post_link( $event_id, 'raw' ), ]; } catch ( \Exception $e ) { Log::error( 'Eventin_Update_Event_Tool error', [ 'error' => $e->getMessage() ] ); return [ 'error' => 'Failed to update event: ' . $e->getMessage() ]; } } }