Skip to content

Commit 67cb3cb

Browse files
committed
Fix year-week boundary bug
1 parent 583be3c commit 67cb3cb

7 files changed

Lines changed: 26 additions & 24 deletions

File tree

classes/suggested-tasks/class-task.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
* @property int|null $target_term_id The target term ID for the task
3030
* @property string|null $target_taxonomy The target taxonomy for the task
3131
* @property string|null $target_term_name The target term name for the task
32-
* @property string|null $date The task date in YW format (year-week)
32+
* @property string|null $date The task date in oW format (ISO year + ISO week)
3333
*/
3434
class Task {
3535
/**

classes/suggested-tasks/class-tasks-manager.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ public function cleanup_pending_tasks() {
315315
$task_provider = $this->get_task_provider( $task->get_provider_id() );
316316

317317
// Should we delete the task? Delete tasks which don't have a task provider or repetitive tasks which were created in the previous week.
318-
if ( ! $task_provider || ( $task_provider->is_repetitive() && ( ! $task->date || \gmdate( 'YW' ) !== (string) $task->date ) ) ) {
318+
if ( ! $task_provider || ( $task_provider->is_repetitive() && ( ! $task->date || \gmdate( 'oW' ) !== (string) $task->date ) ) ) {
319319
\progress_planner()->get_suggested_tasks_db()->delete_recommendation( $task->ID );
320320
}
321321
}
@@ -346,7 +346,7 @@ public function handle_task_unsnooze( $new_status, $old_status, $post ) {
346346
$task_provider = $this->get_task_provider( $task->get_provider_id() );
347347

348348
// Delete tasks which don't have a task provider or repetitive tasks which were created in the previous week.
349-
if ( ! $task_provider || ( $task_provider->is_repetitive() && ( ! $task->date || \gmdate( 'YW' ) !== (string) $task->date ) ) ) {
349+
if ( ! $task_provider || ( $task_provider->is_repetitive() && ( ! $task->date || \gmdate( 'oW' ) !== (string) $task->date ) ) ) {
350350
\progress_planner()->get_suggested_tasks_db()->delete_recommendation( $task->ID );
351351
}
352352

classes/suggested-tasks/providers/class-content-create.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ public function should_add_task() {
109109
}
110110

111111
// Add tasks if there are no posts published this week.
112-
return \gmdate( 'YW' ) !== \gmdate( 'YW', \strtotime( $last_published_post_data['post_date'] ) );
112+
return \gmdate( 'oW' ) !== \gmdate( 'oW', \strtotime( $last_published_post_data['post_date'] ) );
113113
}
114114

115115
/**

classes/suggested-tasks/providers/class-content-review.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ public function get_tasks_to_inject() {
289289
'provider_id' => $this->get_provider_id(),
290290
'target_post_id' => $task_data['target_post_id'],
291291
'target_post_type' => $task_data['target_post_type'],
292-
'date' => \gmdate( 'YW' ),
292+
'date' => \gmdate( 'oW' ),
293293
'post_title' => $this->get_title_with_data( $task_data ),
294294
'url' => $this->get_url_with_data( $task_data ),
295295
'url_target' => $this->get_url_target(),

classes/suggested-tasks/providers/class-tasks.php

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,9 @@ public function get_task_id( $task_data = [] ) {
295295
$parts[] = $task_data['target_taxonomy'] ?? false;
296296
// If the task is repetitive, add the date as the last part (format: YYYYWW, e.g., 202542 for week 42 of 2025).
297297
// This creates a new task instance each week for repetitive tasks.
298-
$parts[] = $this->is_repetitive() ? \gmdate( 'YW' ) : false;
298+
// Note: We use 'oW' format (ISO year + ISO week) instead of 'YW' to handle year boundaries correctly.
299+
// For example, Dec 29, 2025 is ISO week 01 of 2026, so 'oW' returns '202601' while 'YW' would incorrectly return '202501'.
300+
$parts[] = $this->is_repetitive() ? \gmdate( 'oW' ) : false;
299301

300302
// Remove empty parts to keep IDs clean.
301303
$parts = \array_filter( $parts );
@@ -447,7 +449,7 @@ public function is_task_relevant() {
447449
* - Returns the task object if completed, false otherwise
448450
*
449451
* Repetitive tasks:
450-
* - Must be completed within the same week they were created (using YW format: year + week number)
452+
* - Must be completed within the same week they were created (using oW format: ISO year + ISO week number)
451453
* - For example, a task created in week 42 of 2025 must be completed in 2025W42
452454
* - This prevents tasks from previous weeks being marked as complete
453455
* - Allows child classes to add completion data (e.g., post_id for "create post" tasks)
@@ -483,8 +485,8 @@ public function evaluate_task( $task_id ) {
483485
$task->provider &&
484486
$task->provider->slug === $this->get_provider_id() &&
485487
\DateTime::createFromFormat( 'Y-m-d H:i:s', $task->post_date ) &&
486-
// Check if the task was created in the current week (YW format: e.g., 202542 = week 42 of 2025).
487-
\gmdate( 'YW' ) === \gmdate( 'YW', \DateTime::createFromFormat( 'Y-m-d H:i:s', $task->post_date )->getTimestamp() ) && // @phpstan-ignore-line
488+
// Check if the task was created in the current week (oW format: ISO year + ISO week, e.g., 202542 = week 42 of 2025).
489+
\gmdate( 'oW' ) === \gmdate( 'oW', \DateTime::createFromFormat( 'Y-m-d H:i:s', $task->post_date )->getTimestamp() ) && // @phpstan-ignore-line
488490
$this->is_task_completed( \progress_planner()->get_suggested_tasks()->get_task_id_from_slug( $task->post_name ) )
489491
) {
490492
// Allow adding more data, for example in case of 'create-post' tasks we are adding the post_id.
@@ -599,7 +601,7 @@ public function get_task_details( $task_data = [] ) {
599601
'parent' => $this->get_parent(),
600602
'priority' => $this->get_priority(),
601603
'points' => $this->get_points(),
602-
'date' => \gmdate( 'YW' ),
604+
'date' => \gmdate( 'oW' ),
603605
'url' => $this->get_url_with_data( $task_data ),
604606
'url_target' => $this->get_url_target(),
605607
'link_setting' => $this->get_link_setting(),

classes/suggested-tasks/providers/traits/class-dismissable-task.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public function handle_task_dismissal( $post_id ) {
8787

8888
// Store the task dismissal data.
8989
$dismissal_data = [
90-
'date' => \gmdate( 'YW' ),
90+
'date' => \gmdate( 'oW' ),
9191
'timestamp' => \time(),
9292
];
9393

@@ -157,7 +157,7 @@ protected function is_task_dismissed( $task_data ) {
157157
$dismissal_data = $dismissed_tasks[ $provider_key ][ $task_identifier ];
158158

159159
// If the task was dismissed in the current week, don't show it again.
160-
if ( $dismissal_data['date'] === \gmdate( 'YW' ) ) {
160+
if ( $dismissal_data['date'] === \gmdate( 'oW' ) ) {
161161
return true;
162162
}
163163

tests/phpunit/test-class-suggested-tasks.php

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,30 +21,30 @@ public function test_task_cleanup() {
2121
// Tasks that should not be removed.
2222
$tasks_to_keep = [
2323
[
24-
'post_title' => 'review-post-14-' . \gmdate( 'YW' ),
25-
'task_id' => 'review-post-14-' . \gmdate( 'YW' ),
26-
'date' => \gmdate( 'YW' ),
24+
'post_title' => 'review-post-14-' . \gmdate( 'oW' ),
25+
'task_id' => 'review-post-14-' . \gmdate( 'oW' ),
26+
'date' => \gmdate( 'oW' ),
2727
'category' => 'content-update',
2828
'provider_id' => 'review-post',
2929
],
3030
[
31-
'post_title' => 'create-post-' . \gmdate( 'YW' ),
32-
'task_id' => 'create-post-' . \gmdate( 'YW' ),
33-
'date' => \gmdate( 'YW' ),
31+
'post_title' => 'create-post-' . \gmdate( 'oW' ),
32+
'task_id' => 'create-post-' . \gmdate( 'oW' ),
33+
'date' => \gmdate( 'oW' ),
3434
'category' => 'content-new',
3535
'provider_id' => 'create-post',
3636
],
3737
[
38-
'post_title' => 'update-core-' . \gmdate( 'YW' ),
39-
'task_id' => 'update-core-' . \gmdate( 'YW' ),
40-
'date' => \gmdate( 'YW' ),
38+
'post_title' => 'update-core-' . \gmdate( 'oW' ),
39+
'task_id' => 'update-core-' . \gmdate( 'oW' ),
40+
'date' => \gmdate( 'oW' ),
4141
'category' => 'maintenance',
4242
'provider_id' => 'update-core',
4343
],
4444
[
45-
'post_title' => 'core-siteicon-' . \gmdate( 'YW' ),
46-
'task_id' => 'core-siteicon-' . \gmdate( 'YW' ),
47-
'date' => \gmdate( 'YW' ),
45+
'post_title' => 'core-siteicon-' . \gmdate( 'oW' ),
46+
'task_id' => 'core-siteicon-' . \gmdate( 'oW' ),
47+
'date' => \gmdate( 'oW' ),
4848
'provider_id' => 'core-siteicon',
4949
'category' => 'configuration',
5050
],

0 commit comments

Comments
 (0)