0 ? get_post_meta($id, '_pcwp_schedule', true) : ['type' => 'continuous']), $timezone, ($post->post_type ?? get_post_type($id)) === 'pcwp_series' || (int) ($meta['_pcwp_series_id'] ?? get_post_meta($id, '_pcwp_series_id', true)) > 0, ); } catch (\InvalidArgumentException $error) { return new \WP_Error('pcwp_invalid_schedule', $error->getMessage(), ['status' => 400]); } if ($schedule['type'] === 'daily') { $slots = DailySchedule::intervals($schedule, $timezone); $meta['_pcwp_start'] = $slots[0]['time']->start->format('Y-m-d\TH:i:s'); $meta['_pcwp_end'] = $slots[count($slots) - 1]['time']->end->format('Y-m-d\TH:i:s'); $meta['_pcwp_all_day'] = false; $meta['_pcwp_schedule'] = $schedule; } $request->set_param('meta', $meta); self::$restSaving = ($post->post_type ?? get_post_type($id)) !== 'pcwp_series'; return $post; } public function afterSave(\WP_Post $post): void { self::$restSaving = false; (new EventSaver())->sync($post->ID, $post); } public function guardMeta(mixed $check, int $id, string $key, mixed $value, mixed $previous): mixed { unset($previous); if ($check !== null || self::$restSaving || self::$deriving || ! in_array($key, ['_pcwp_schedule', '_pcwp_timezone', '_pcwp_series_id', '_pcwp_all_day'], true)) { return $check; } if (! in_array(get_post_type($id), ['pcwp_event', 'pcwp_series'], true)) { return $check; } try { $schedule = DailySchedule::validate( $key === '_pcwp_schedule' ? $value : get_post_meta($id, '_pcwp_schedule', true), $key === '_pcwp_timezone' ? (string) ($value ?: wp_timezone_string()) : (string) (get_post_meta($id, '_pcwp_timezone', true) ?: wp_timezone_string()), get_post_type($id) === 'pcwp_series' || (int) ($key === '_pcwp_series_id' ? $value : get_post_meta($id, '_pcwp_series_id', true)) > 0, ); if ($schedule['type'] === 'daily' && $key === '_pcwp_all_day' && (bool) $value) { return false; } } catch (\InvalidArgumentException) { return false; } return $check; } public function notice(): void { $message = get_transient('pcwp_schedule_error_' . get_current_user_id()); if (is_string($message) && $message !== '') { delete_transient('pcwp_schedule_error_' . get_current_user_id()); echo '

' . esc_html($message) . '

'; } } /** Stage a new generation before switching the parent row, so queries never see a partial schedule. * @param array $schedule */ public static function stage(int $id, array $schedule, string $timezone): string { global $wpdb; $revision = wp_generate_password(32, false, false); foreach (DailySchedule::intervals($schedule, $timezone) as $slot) { $time = $slot['time']; if ( $wpdb->insert($wpdb->prefix . 'pcwp_daily_intervals', [ 'event_id' => $id, 'revision' => $revision, 'slot_id' => $slot['id'], 'start_local' => $time->start->format('Y-m-d H:i:s'), 'end_local' => $time->end->format('Y-m-d H:i:s'), 'start_utc' => $time->startUtc()->format('Y-m-d H:i:s'), 'end_utc' => $time->endUtc()->format('Y-m-d H:i:s'), ]) === false ) { $wpdb->delete($wpdb->prefix . 'pcwp_daily_intervals', ['event_id' => $id, 'revision' => $revision]); throw new \RuntimeException('Could not save daily schedule intervals.'); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Exception messages are data; REST encodes them and admin callers escape output. } } return $revision; } }