-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathclass-task.php
More file actions
225 lines (201 loc) · 6.12 KB
/
class-task.php
File metadata and controls
225 lines (201 loc) · 6.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
<?php
/**
* Task abstract class.
*
* @package Progress_Planner
*/
namespace Progress_Planner\Suggested_Tasks;
/**
* Task abstract class.
*
* @property int $ID The task ID
* @property string $post_status The task status
* @property string $post_title The task title
* @property string $post_name The task name
* @property string $post_date The task date
* @property int $menu_order The task menu order (priority)
* @property \stdClass|null $provider The task provider object with slug property
* @property string $provider_id The provider identifier
* @property int $priority The task priority (0-100, 0 being highest and 100 being lowest).
* @property int $points The task points
* @property bool $dismissable Whether the task is dismissable
* @property string $url The task URL
* @property string $url_target The task URL target
* @property string $description The task description
* @property array $data The task data array
* @property int|null $target_post_id The target post ID for the task
* @property int|null $target_term_id The target term ID for the task
* @property string|null $target_taxonomy The target taxonomy for the task
* @property string|null $target_term_name The target term name for the task
* @property string|null $date The task date in YW format (year-week)
*/
class Task {
/**
* The task data.
*
* @var array<string, mixed>
*/
protected array $data;
/**
* Constructor.
*
* @param array<string, mixed> $data The task data.
*/
public function __construct( array $data = [] ) {
$this->data = $data;
}
/**
* Get the task data.
*
* @return array<string, mixed>
*/
public function get_data(): array {
return $this->data;
}
/**
* Set the task data.
*
* @param array<string, mixed> $data The task data.
*
* @return void
*/
public function set_data( array $data ): void {
$this->data = $data;
}
/**
* Update the task data.
*
* @param array<string, mixed> $data The task data.
*
* @return void
*/
public function update( array $data ): void {
$this->data = $data;
// Update only if the task is already saved in the database.
if ( $this->ID ) {
\progress_planner()->get_suggested_tasks_db()->update_recommendation( $this->ID, $this->data );
}
}
/**
* Delete the task.
*
* @return void
*/
public function delete(): void {
// Delete only if the task is already saved in the database.
if ( $this->ID ) {
\progress_planner()->get_suggested_tasks_db()->delete_recommendation( $this->ID );
}
// Clear the data.
$this->data = [];
}
/**
* Check if the task is snoozed.
*
* A task is snoozed when its post_status is 'future', meaning it's scheduled
* to reappear at a later date (the snooze duration selected by the user).
*
* @return bool True if snoozed, false otherwise.
*/
public function is_snoozed(): bool {
return isset( $this->data['post_status'] ) && 'future' === $this->data['post_status'];
}
/**
* Get the date when a snoozed task will reappear.
*
* Return values explained:
* - DateTime object: Task is snoozed and will reappear on this date
* - null: Task is not snoozed (no post_date set)
* - false: post_date exists but couldn't be parsed (invalid format) - this is from DateTime::createFromFormat()
*
* @return \DateTime|null|false DateTime when task will un-snooze, null if not snoozed,
* false if date format is invalid.
*/
public function snoozed_until() {
return isset( $this->data['post_date'] ) ? \DateTime::createFromFormat( 'Y-m-d H:i:s', $this->data['post_date'] ) : null;
}
/**
* Check if the task is completed.
*
* Task completion statuses:
* - 'trash': Task was explicitly completed/dismissed by the user
* - 'pending': Task is in celebration mode (completed but showing celebration UI)
*
* Note: 'pending' being treated as completed is counterintuitive but intentional.
* It represents tasks that were completed and are now in a temporary "celebrate"
* state before being fully archived. This allows showing congratulations UI.
*
* @return bool True if completed (trash or pending status), false otherwise.
*/
public function is_completed(): bool {
return isset( $this->data['post_status'] ) && \in_array( $this->data['post_status'], [ 'trash', 'pending' ], true );
}
/**
* Set the task status to pending.
*
* @return bool
*/
public function celebrate(): bool {
return $this->ID && \progress_planner()->get_suggested_tasks_db()->update_recommendation( $this->ID, [ 'post_status' => 'pending' ] );
}
/**
* Get the provider ID.
*
* @return string
*/
public function get_provider_id(): string {
return $this->data['provider']->slug ?? ''; // @phpstan-ignore-line property.nonObject
}
/**
* Get the task ID.
*
* @return string
*/
public function get_task_id(): string {
return $this->data['task_id'] ?? '';
}
/**
* Magic getter.
*
* @param string $key The key.
*
* @return mixed
*/
public function __get( string $key ) {
return $this->data[ $key ] ?? null;
}
/**
* Get the REST formatted data.
*
* @param int|null $post_id The post ID.
*
* @return array
*/
public function get_rest_formatted_data( $post_id = null ): array {
if ( ! $post_id ) {
$post_id = $this->ID;
}
$post = \get_post( $post_id );
if ( ! $post ) {
return [];
}
// Make sure WP_REST_Posts_Controller is loaded.
if ( ! \class_exists( 'WP_REST_Posts_Controller' ) ) {
// @phpstan-ignore-next-line requireOnce.fileNotFound
require_once ABSPATH . 'wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php';
}
// Make sure WP_REST_Request is loaded.
if ( ! \class_exists( 'WP_REST_Request' ) ) {
// @phpstan-ignore-next-line requireOnce.fileNotFound
require_once ABSPATH . 'wp-includes/rest-api/class-wp-rest-request.php';
}
// Use the appropriate controller for the post type.
$controller = new \WP_REST_Posts_Controller( $post->post_type );
// Build dummy request object.
$request = new \WP_REST_Request();
$request->set_param( 'context', 'view' );
// Get formatted response.
$response = $controller->prepare_item_for_response( $post, $request );
return $response->get_data();
}
}