From dad690e77e1727654ce25a8a5d87c9344f196eb8 Mon Sep 17 00:00:00 2001 From: Ali Shan Date: Sun, 30 Nov 2025 09:37:56 +0500 Subject: [PATCH 1/7] Add GitHub Action to automate ai.zip release asset - Triggers on release publish - Reuses existing build-plugin-zip workflow - Downloads built artifact - Uploads ai.zip as release asset Fixes #109 --- .github/workflows/release.yml | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..1f80ab66 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,33 @@ +name: Attach Plugin Zip to Release + +on: + release: + types: [published] + +permissions: + contents: write + +jobs: + build: + name: Build Plugin Zip + uses: ./.github/workflows/build-plugin-zip.yaml + permissions: + contents: read + + attach-to-release: + name: Attach to Release + needs: build + runs-on: ubuntu-24.04 + permissions: + contents: write + + steps: + - name: Download artifact + uses: actions/download-artifact@v4 + with: + name: ai + + - name: Upload to release + uses: softprops/action-gh-release@v2 + with: + files: ai.zip From 288d7e8b4592c74bcc7d7a6f7883d60c97c456cc Mon Sep 17 00:00:00 2001 From: Ali Shan Date: Sun, 30 Nov 2025 11:26:10 +0500 Subject: [PATCH 2/7] Add date calculation ability - Implements ai/calculate-dates ability as requested in #55 - Supports relative patterns (tomorrow, next Monday, in 3 days) - Supports nth weekday patterns (3rd Tuesday, first Friday, last Monday) - Supports recurring patterns (every Monday, every other Tuesday) - Supports interval patterns (every 2 weeks, every month) - Uses native PHP DateTime (no external dependencies) - Includes input validation and error handling - REST API enabled - Limits occurrences to 52 maximum - Requires edit_posts capability Addresses #55 --- .../Abilities/Utilities/Date_Calculation.php | 493 ++++++++++++++++++ includes/bootstrap.php | 5 + 2 files changed, 498 insertions(+) create mode 100644 includes/Abilities/Utilities/Date_Calculation.php diff --git a/includes/Abilities/Utilities/Date_Calculation.php b/includes/Abilities/Utilities/Date_Calculation.php new file mode 100644 index 00000000..9f7f679e --- /dev/null +++ b/includes/Abilities/Utilities/Date_Calculation.php @@ -0,0 +1,493 @@ +register_calculate_dates_ability(); + } + + /** + * Registers the calculate-dates ability. + * + * @since 0.2.0 + */ + private function register_calculate_dates_ability(): void { + wp_register_ability( + 'ai/calculate-dates', + array( + 'label' => esc_html__( 'Calculate dates', 'ai' ), + 'description' => esc_html__( 'Calculate dates from natural language patterns like "3rd Tuesday", "every Monday", or "next Friday".', 'ai' ), + 'category' => AI_EXPERIMENTS_DEFAULT_ABILITY_CATEGORY, + 'input_schema' => array( + 'type' => 'object', + 'properties' => array( + 'pattern' => array( + 'type' => 'string', + 'description' => esc_html__( 'Natural language date pattern (e.g., "3rd Tuesday", "every Monday", "next Friday", "in 3 days").', 'ai' ), + ), + 'start_date' => array( + 'type' => 'string', + 'description' => esc_html__( 'Starting date for calculations (ISO 8601 format or "now"). Defaults to current date/time.', 'ai' ), + 'default' => 'now', + ), + 'occurrences' => array( + 'type' => 'integer', + 'description' => esc_html__( 'Number of dates to calculate for recurring patterns (1-52).', 'ai' ), + 'minimum' => 1, + 'maximum' => self::OCCURRENCES_MAX, + 'default' => self::OCCURRENCES_DEFAULT, + ), + 'timezone' => array( + 'type' => 'string', + 'description' => esc_html__( 'Timezone for calculations (e.g., "America/New_York"). Defaults to WordPress site timezone.', 'ai' ), + ), + ), + 'required' => array( 'pattern' ), + ), + 'output_schema' => array( + 'type' => 'object', + 'properties' => array( + 'dates' => array( + 'type' => 'array', + 'description' => esc_html__( 'Calculated dates in ISO 8601 format.', 'ai' ), + 'items' => array( + 'type' => 'string', + 'format' => 'date-time', + ), + ), + 'pattern' => array( + 'type' => 'string', + 'description' => esc_html__( 'The original pattern that was interpreted.', 'ai' ), + ), + ), + ), + 'execute_callback' => array( $this, 'execute_calculate_dates' ), + 'permission_callback' => array( $this, 'permission_callback' ), + 'meta' => array( + 'show_in_rest' => true, + 'mcp' => array( + 'public' => true, + 'type' => 'tool', + ), + ), + ) + ); + } + + /** + * Execute the calculate-dates ability. + * + * @since 0.2.0 + * + * @param array $input The input arguments. + * @return array|\WP_Error The calculated dates or error. + */ + public function execute_calculate_dates( array $input ) { + // Validate pattern is provided. + if ( empty( $input['pattern'] ) ) { + return new WP_Error( + 'pattern_required', + esc_html__( 'A date pattern is required.', 'ai' ) + ); + } + + // Sanitize and set defaults. + $pattern = sanitize_text_field( $input['pattern'] ); + $start_date = isset( $input['start_date'] ) ? sanitize_text_field( $input['start_date'] ) : 'now'; + $occurrences = isset( $input['occurrences'] ) ? absint( $input['occurrences'] ) : self::OCCURRENCES_DEFAULT; + $timezone = isset( $input['timezone'] ) ? sanitize_text_field( $input['timezone'] ) : wp_timezone_string(); + + // Validate and limit occurrences. + $occurrences = min( max( $occurrences, 1 ), self::OCCURRENCES_MAX ); + + try { + // Calculate the dates. + $dates = $this->calculate_dates( $pattern, $start_date, $occurrences, $timezone ); + + return array( + 'dates' => $dates, + 'pattern' => $pattern, + ); + } catch ( Exception $e ) { + return new WP_Error( + 'date_calculation_failed', + sprintf( + /* translators: %s: Error message. */ + esc_html__( 'Failed to calculate dates: %s', 'ai' ), + $e->getMessage() + ) + ); + } + } + + /** + * Permission callback for date calculation. + * + * @since 0.2.0 + * + * @param array $args The input arguments. + * @return bool|\WP_Error True if permitted, WP_Error otherwise. + */ + public function permission_callback( array $args ) { + // Anyone who can edit posts can use date calculations. + if ( ! current_user_can( 'edit_posts' ) ) { + return new WP_Error( + 'insufficient_capabilities', + esc_html__( 'You do not have permission to calculate dates.', 'ai' ) + ); + } + + return true; + } + + /** + * Calculate dates from natural language pattern. + * + * @since 0.2.0 + * + * @param string $pattern The natural language date pattern. + * @param string $start_date The starting date. + * @param int $occurrences Number of dates to calculate. + * @param string $timezone The timezone to use. + * @return array Array of calculated dates in ISO 8601 format. + * @throws Exception If date calculation fails. + */ + private function calculate_dates( string $pattern, string $start_date, int $occurrences, string $timezone ): array { + $pattern = strtolower( trim( $pattern ) ); + + // Validate timezone. + try { + $tz = new DateTimeZone( $timezone ); + } catch ( Exception $e ) { + throw new Exception( + sprintf( + /* translators: %s: Timezone value. */ + esc_html__( 'Invalid timezone: %s', 'ai' ), + $timezone + ) + ); + } + + // Parse starting date. + try { + $current_date = new DateTime( $start_date, $tz ); + } catch ( Exception $e ) { + throw new Exception( + sprintf( + /* translators: %s: Start date value. */ + esc_html__( 'Invalid start date: %s', 'ai' ), + $start_date + ) + ); + } + + $dates = array(); + + // Relative patterns: "tomorrow", "next Monday", "in 3 days". + if ( $this->is_relative_pattern( $pattern ) ) { + $dates = $this->calculate_relative_dates( $pattern, $current_date, $occurrences ); + } elseif ( $this->is_nth_weekday_pattern( $pattern ) ) { + // Nth weekday patterns: "3rd Tuesday", "first Friday", "last Monday". + $dates = $this->calculate_nth_weekday_dates( $pattern, $current_date, $occurrences ); + } elseif ( $this->is_recurring_pattern( $pattern ) ) { + // Recurring patterns: "every Monday", "every other Tuesday". + $dates = $this->calculate_recurring_dates( $pattern, $current_date, $occurrences ); + } elseif ( $this->is_interval_pattern( $pattern ) ) { + // Interval patterns: "every 2 weeks", "every month". + $dates = $this->calculate_interval_dates( $pattern, $current_date, $occurrences ); + } else { + throw new Exception( + sprintf( + /* translators: %s: Date pattern. */ + esc_html__( 'Unable to parse pattern: %s', 'ai' ), + $pattern + ) + ); + } + + return $dates; + } + + /** + * Check if pattern is relative. + * + * @since 0.2.0 + * + * @param string $pattern The pattern to check. + * @return bool True if pattern is relative. + */ + private function is_relative_pattern( string $pattern ): bool { + return (bool) preg_match( '/^(tomorrow|yesterday|today|next\s+\w+day|in\s+\d+\s+(day|week|month|year)s?)$/i', $pattern ); + } + + /** + * Check if pattern is nth weekday. + * + * @since 0.2.0 + * + * @param string $pattern The pattern to check. + * @return bool True if pattern is nth weekday. + */ + private function is_nth_weekday_pattern( string $pattern ): bool { + return (bool) preg_match( '/^(\d+|first|second|third|fourth|fifth|last)\s+(\w+day)$/i', $pattern ); + } + + /** + * Check if pattern is recurring. + * + * @since 0.2.0 + * + * @param string $pattern The pattern to check. + * @return bool True if pattern is recurring. + */ + private function is_recurring_pattern( string $pattern ): bool { + return (bool) preg_match( '/^every\s+(other\s+)?(\w+day)$/i', $pattern ); + } + + /** + * Check if pattern is interval. + * + * @since 0.2.0 + * + * @param string $pattern The pattern to check. + * @return bool True if pattern is interval. + */ + private function is_interval_pattern( string $pattern ): bool { + return (bool) preg_match( '/^every\s+(\d+)\s+(day|week|month|year)s?$/i', $pattern ); + } + + /** + * Calculate relative dates. + * + * @since 0.2.0 + * + * @param string $pattern The pattern. + * @param DateTime $start_date The starting date. + * @param int $occurrences Number of occurrences. + * @return array Array of dates. + * @throws Exception If calculation fails. + */ + private function calculate_relative_dates( string $pattern, DateTime $start_date, int $occurrences ): array { + $dates = array(); + $date = clone $start_date; + + // Simple keywords. + if ( in_array( $pattern, array( 'today', 'tomorrow', 'yesterday' ), true ) ) { + $date->modify( $pattern ); + $dates[] = $date->format( 'c' ); + return $dates; + } + + // "next Monday" patterns. + if ( preg_match( '/^next\s+(\w+day)$/i', $pattern, $matches ) ) { + $weekday = $matches[1]; + $date->modify( 'next ' . $weekday ); + $dates[] = $date->format( 'c' ); + return $dates; + } + + // "in X days/weeks/months" patterns. + if ( preg_match( '/^in\s+(\d+)\s+(day|week|month|year)s?$/i', $pattern, $matches ) ) { + $amount = (int) $matches[1]; + $unit = $matches[2]; + $date->modify( "+{$amount} {$unit}" ); + $dates[] = $date->format( 'c' ); + return $dates; + } + + return $dates; + } + + /** + * Calculate nth weekday dates. + * + * @since 0.2.0 + * + * @param string $pattern The pattern. + * @param DateTime $start_date The starting date. + * @param int $occurrences Number of occurrences. + * @return array Array of dates. + * @throws Exception If calculation fails. + */ + private function calculate_nth_weekday_dates( string $pattern, DateTime $start_date, int $occurrences ): array { + $dates = array(); + + if ( ! preg_match( '/^(\d+|first|second|third|fourth|fifth|last)\s+(\w+day)$/i', $pattern, $matches ) ) { + return $dates; + } + + $ordinal = strtolower( $matches[1] ); + $weekday = ucfirst( strtolower( $matches[2] ) ); + $nth = $this->ordinal_to_number( $ordinal ); + + $date = clone $start_date; + + for ( $i = 0; $i < $occurrences; $i++ ) { + $temp = clone $date; + $temp->modify( 'first day of this month' ); + + if ( -1 === $nth ) { + // "last Monday". + $temp->modify( 'last ' . $weekday . ' of this month' ); + } else { + // Find first occurrence. + $temp->modify( 'first ' . $weekday . ' of this month' ); + + // Add weeks for nth occurrence. + if ( $nth > 1 ) { + $temp->modify( '+' . ( $nth - 1 ) . ' weeks' ); + } + } + + // Ensure we didn't overflow into next month. + if ( (int) $temp->format( 'n' ) === (int) $date->format( 'n' ) ) { + $dates[] = $temp->format( 'c' ); + } + + // Move to next month. + $date->modify( 'first day of next month' ); + } + + return $dates; + } + + /** + * Calculate recurring dates. + * + * @since 0.2.0 + * + * @param string $pattern The pattern. + * @param DateTime $start_date The starting date. + * @param int $occurrences Number of occurrences. + * @return array Array of dates. + * @throws Exception If calculation fails. + */ + private function calculate_recurring_dates( string $pattern, DateTime $start_date, int $occurrences ): array { + $dates = array(); + + if ( ! preg_match( '/^every\s+(other\s+)?(\w+day)$/i', $pattern, $matches ) ) { + return $dates; + } + + $is_every_other = ! empty( $matches[1] ); + $weekday = ucfirst( strtolower( $matches[2] ) ); + $interval = $is_every_other ? 2 : 1; + + $date = clone $start_date; + + // Move to next occurrence if not already on it. + if ( $date->format( 'l' ) !== $weekday ) { + $date->modify( 'next ' . $weekday ); + } + + for ( $i = 0; $i < $occurrences; $i++ ) { + $dates[] = $date->format( 'c' ); + $date->modify( '+' . $interval . ' weeks' ); + } + + return $dates; + } + + /** + * Calculate interval dates. + * + * @since 0.2.0 + * + * @param string $pattern The pattern. + * @param DateTime $start_date The starting date. + * @param int $occurrences Number of occurrences. + * @return array Array of dates. + * @throws Exception If calculation fails. + */ + private function calculate_interval_dates( string $pattern, DateTime $start_date, int $occurrences ): array { + $dates = array(); + + if ( ! preg_match( '/^every\s+(\d+)\s+(day|week|month|year)s?$/i', $pattern, $matches ) ) { + return $dates; + } + + $amount = (int) $matches[1]; + $unit = strtolower( $matches[2] ); + + $date = clone $start_date; + + for ( $i = 0; $i < $occurrences; $i++ ) { + $dates[] = $date->format( 'c' ); + $date->modify( "+{$amount} {$unit}" ); + } + + return $dates; + } + + /** + * Convert ordinal word to number. + * + * @since 0.2.0 + * + * @param string $ordinal The ordinal word. + * @return int The numeric value. + */ + private function ordinal_to_number( string $ordinal ): int { + $map = array( + 'first' => 1, + 'second' => 2, + 'third' => 3, + 'fourth' => 4, + 'fifth' => 5, + 'last' => -1, + ); + + $ordinal = strtolower( $ordinal ); + + return $map[ $ordinal ] ?? (int) $ordinal; + } +} diff --git a/includes/bootstrap.php b/includes/bootstrap.php index 854db622..98a3807e 100644 --- a/includes/bootstrap.php +++ b/includes/bootstrap.php @@ -12,6 +12,7 @@ namespace WordPress\AI; use WordPress\AI\Abilities\Utilities\Posts; +use WordPress\AI\Abilities\Utilities\Date_Calculation; use WordPress\AI\Settings\Settings_Page; use WordPress\AI\Settings\Settings_Registration; use WordPress\AI_Client\AI_Client; @@ -200,6 +201,10 @@ function initialize_experiments(): void { $post_abilities = new Posts(); $post_abilities->register(); + // Register our date calculation WordPress Abilities. + $date_calculation = new Date_Calculation(); + $date_calculation->register(); + add_action( 'wp_abilities_api_categories_init', static function () { From d63ba54e94d761e2506ae1bd352aba0b4142ab87 Mon Sep 17 00:00:00 2001 From: Ali Shan Date: Sat, 6 Dec 2025 23:18:29 +0500 Subject: [PATCH 3/7] Remove release.yml - belongs to #109, not this PR --- .github/workflows/release.yml | 33 --------------------------------- 1 file changed, 33 deletions(-) delete mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 1f80ab66..00000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: Attach Plugin Zip to Release - -on: - release: - types: [published] - -permissions: - contents: write - -jobs: - build: - name: Build Plugin Zip - uses: ./.github/workflows/build-plugin-zip.yaml - permissions: - contents: read - - attach-to-release: - name: Attach to Release - needs: build - runs-on: ubuntu-24.04 - permissions: - contents: write - - steps: - - name: Download artifact - uses: actions/download-artifact@v4 - with: - name: ai - - - name: Upload to release - uses: softprops/action-gh-release@v2 - with: - files: ai.zip From cf1c7c0100e9ad23354bce5fc5eac027d0041d47 Mon Sep 17 00:00:00 2001 From: Ali Shan Date: Sat, 6 Dec 2025 23:22:21 +0500 Subject: [PATCH 4/7] changed the @since 0.2.0 to @since x.x.x --- .../Abilities/Utilities/Date_Calculation.php | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/includes/Abilities/Utilities/Date_Calculation.php b/includes/Abilities/Utilities/Date_Calculation.php index 9f7f679e..bca847fd 100644 --- a/includes/Abilities/Utilities/Date_Calculation.php +++ b/includes/Abilities/Utilities/Date_Calculation.php @@ -17,14 +17,14 @@ /** * Date calculation utility WordPress Abilities. * - * @since 0.2.0 + * @since x.x.x */ class Date_Calculation { /** * The default number of occurrences to calculate. * - * @since 0.2.0 + * @since x.x.x * @var int */ private const OCCURRENCES_DEFAULT = 1; @@ -32,7 +32,7 @@ class Date_Calculation { /** * The maximum number of occurrences allowed. * - * @since 0.2.0 + * @since x.x.x * @var int */ private const OCCURRENCES_MAX = 52; @@ -40,7 +40,7 @@ class Date_Calculation { /** * Register any needed hooks. * - * @since 0.2.0 + * @since x.x.x */ public function register(): void { add_action( 'wp_abilities_api_init', array( $this, 'register_abilities' ) ); @@ -49,7 +49,7 @@ public function register(): void { /** * Registers any needed abilities. * - * @since 0.2.0 + * @since x.x.x */ public function register_abilities(): void { $this->register_calculate_dates_ability(); @@ -58,7 +58,7 @@ public function register_abilities(): void { /** * Registers the calculate-dates ability. * - * @since 0.2.0 + * @since x.x.x */ private function register_calculate_dates_ability(): void { wp_register_ability( @@ -126,7 +126,7 @@ private function register_calculate_dates_ability(): void { /** * Execute the calculate-dates ability. * - * @since 0.2.0 + * @since x.x.x * * @param array $input The input arguments. * @return array|\WP_Error The calculated dates or error. @@ -172,7 +172,7 @@ public function execute_calculate_dates( array $input ) { /** * Permission callback for date calculation. * - * @since 0.2.0 + * @since x.x.x * * @param array $args The input arguments. * @return bool|\WP_Error True if permitted, WP_Error otherwise. @@ -192,7 +192,7 @@ public function permission_callback( array $args ) { /** * Calculate dates from natural language pattern. * - * @since 0.2.0 + * @since x.x.x * * @param string $pattern The natural language date pattern. * @param string $start_date The starting date. @@ -260,7 +260,7 @@ private function calculate_dates( string $pattern, string $start_date, int $occu /** * Check if pattern is relative. * - * @since 0.2.0 + * @since x.x.x * * @param string $pattern The pattern to check. * @return bool True if pattern is relative. @@ -272,7 +272,7 @@ private function is_relative_pattern( string $pattern ): bool { /** * Check if pattern is nth weekday. * - * @since 0.2.0 + * @since x.x.x * * @param string $pattern The pattern to check. * @return bool True if pattern is nth weekday. @@ -284,7 +284,7 @@ private function is_nth_weekday_pattern( string $pattern ): bool { /** * Check if pattern is recurring. * - * @since 0.2.0 + * @since x.x.x * * @param string $pattern The pattern to check. * @return bool True if pattern is recurring. @@ -296,7 +296,7 @@ private function is_recurring_pattern( string $pattern ): bool { /** * Check if pattern is interval. * - * @since 0.2.0 + * @since x.x.x * * @param string $pattern The pattern to check. * @return bool True if pattern is interval. @@ -308,7 +308,7 @@ private function is_interval_pattern( string $pattern ): bool { /** * Calculate relative dates. * - * @since 0.2.0 + * @since x.x.x * * @param string $pattern The pattern. * @param DateTime $start_date The starting date. @@ -350,7 +350,7 @@ private function calculate_relative_dates( string $pattern, DateTime $start_date /** * Calculate nth weekday dates. * - * @since 0.2.0 + * @since x.x.x * * @param string $pattern The pattern. * @param DateTime $start_date The starting date. @@ -403,7 +403,7 @@ private function calculate_nth_weekday_dates( string $pattern, DateTime $start_d /** * Calculate recurring dates. * - * @since 0.2.0 + * @since x.x.x * * @param string $pattern The pattern. * @param DateTime $start_date The starting date. @@ -440,7 +440,7 @@ private function calculate_recurring_dates( string $pattern, DateTime $start_dat /** * Calculate interval dates. * - * @since 0.2.0 + * @since x.x.x * * @param string $pattern The pattern. * @param DateTime $start_date The starting date. @@ -471,7 +471,7 @@ private function calculate_interval_dates( string $pattern, DateTime $start_date /** * Convert ordinal word to number. * - * @since 0.2.0 + * @since x.x.x * * @param string $ordinal The ordinal word. * @return int The numeric value. From 5f7681b0f8d734e3ca0e035a45817a3cdf9e987d Mon Sep 17 00:00:00 2001 From: Ali Shan Date: Sat, 6 Dec 2025 23:24:11 +0500 Subject: [PATCH 5/7] removed show_in_rest from Date_Calculation --- includes/Abilities/Utilities/Date_Calculation.php | 1 - 1 file changed, 1 deletion(-) diff --git a/includes/Abilities/Utilities/Date_Calculation.php b/includes/Abilities/Utilities/Date_Calculation.php index bca847fd..3d4f8db6 100644 --- a/includes/Abilities/Utilities/Date_Calculation.php +++ b/includes/Abilities/Utilities/Date_Calculation.php @@ -113,7 +113,6 @@ private function register_calculate_dates_ability(): void { 'execute_callback' => array( $this, 'execute_calculate_dates' ), 'permission_callback' => array( $this, 'permission_callback' ), 'meta' => array( - 'show_in_rest' => true, 'mcp' => array( 'public' => true, 'type' => 'tool', From 78a870a65481e5c68be2b3bbbb63f053fdb1bf85 Mon Sep 17 00:00:00 2001 From: Ali Shan Date: Sat, 6 Dec 2025 23:26:44 +0500 Subject: [PATCH 6/7] Removed the validation from execute_calculate_dates, because this is set as required already in base --- includes/Abilities/Utilities/Date_Calculation.php | 8 -------- 1 file changed, 8 deletions(-) diff --git a/includes/Abilities/Utilities/Date_Calculation.php b/includes/Abilities/Utilities/Date_Calculation.php index 3d4f8db6..dd853dec 100644 --- a/includes/Abilities/Utilities/Date_Calculation.php +++ b/includes/Abilities/Utilities/Date_Calculation.php @@ -131,14 +131,6 @@ private function register_calculate_dates_ability(): void { * @return array|\WP_Error The calculated dates or error. */ public function execute_calculate_dates( array $input ) { - // Validate pattern is provided. - if ( empty( $input['pattern'] ) ) { - return new WP_Error( - 'pattern_required', - esc_html__( 'A date pattern is required.', 'ai' ) - ); - } - // Sanitize and set defaults. $pattern = sanitize_text_field( $input['pattern'] ); $start_date = isset( $input['start_date'] ) ? sanitize_text_field( $input['start_date'] ) : 'now'; From 8f2687aab5182e6666fe6f63e58a45fcad96c6be Mon Sep 17 00:00:00 2001 From: Ali Shan Date: Sat, 6 Dec 2025 23:28:46 +0500 Subject: [PATCH 7/7] permission changes to is_user_logged_in --- includes/Abilities/Utilities/Date_Calculation.php | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/includes/Abilities/Utilities/Date_Calculation.php b/includes/Abilities/Utilities/Date_Calculation.php index dd853dec..e791860e 100644 --- a/includes/Abilities/Utilities/Date_Calculation.php +++ b/includes/Abilities/Utilities/Date_Calculation.php @@ -169,15 +169,7 @@ public function execute_calculate_dates( array $input ) { * @return bool|\WP_Error True if permitted, WP_Error otherwise. */ public function permission_callback( array $args ) { - // Anyone who can edit posts can use date calculations. - if ( ! current_user_can( 'edit_posts' ) ) { - return new WP_Error( - 'insufficient_capabilities', - esc_html__( 'You do not have permission to calculate dates.', 'ai' ) - ); - } - - return true; + return is_user_logged_in(); } /**