PluginProbe
UpStream: a Project Management Plugin for WordPress / 2.1.0
UpStream: a Project Management Plugin for WordPress v2.1.0
trunk 1.39.0 1.39.1 1.39.2 1.39.3 2.0.7 2.1.0
upstream / includes / model / class-upstream-model-task.php

class-upstream-model-task.php in UpStream: a Project Management Plugin for WordPress 2.1.0, at includes/model/class-upstream-model-task.php

517 lines 12.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * UpStream_Model_Task
4 *
5 * WordPress Coding Standart (WCS) note:
6 * All camelCase methods and object properties on this file are not converted to snake_case,
7 * because it being used (heavily) on another add-on plugins.
8 *
9 * @package UpStream
10 */
11
12 // Exit if accessed directly.
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit;
15 }
16
17 /**
18 * Class UpStream_Model_Task
19 */
20 class UpStream_Model_Task extends UpStream_Model_Meta_Object {
21
22 /**
23 * Status Code
24 *
25 * @var undefined
26 */
27 protected $statusCode = null; // phpcs:ignore
28
29 /**
30 * Progress
31 *
32 * @var int
33 */
34 protected $progress = 0;
35
36 /**
37 * Milestone Id
38 *
39 * @var int
40 */
41 protected $milestoneId = 0; // phpcs:ignore
42
43 /**
44 * Start Date
45 *
46 * @var undefined
47 */
48 protected $startDate = null; // phpcs:ignore
49
50 /**
51 * End Date
52 *
53 * @var undefined
54 */
55 protected $endDate = null; // phpcs:ignore
56
57 /**
58 * Notes
59 *
60 * @var string
61 */
62 protected $notes = '';
63
64 /**
65 * Reminders
66 *
67 * @var array
68 */
69 protected $reminders = array();
70
71 /**
72 * Time Records
73 *
74 * @var array
75 */
76 protected $timeRecords = array(); // phpcs:ignore
77
78 /**
79 * Metadata Key
80 *
81 * @var string
82 */
83 protected $metadataKey = '_upstream_project_tasks'; // phpcs:ignore
84
85 /**
86 * Type
87 *
88 * @var undefined
89 */
90 protected $type = UPSTREAM_ITEM_TYPE_TASK;
91
92
93 /**
94 * Construct
95 *
96 * @param mixed $parent Parent.
97 * @param mixed $item_metadata Item Metadata.
98 * @return void
99 */
100 public function __construct( $parent, $item_metadata ) {
101 parent::__construct( $parent, $item_metadata );
102 }
103
104 /**
105 * Load From Array
106 *
107 * @param mixed $item_metadata Item Metadata.
108 * @return void
109 */
110 protected function loadFromArray( $item_metadata ) {
111 parent::loadFromArray( $item_metadata );
112
113 $this->statusCode = ! empty( $item_metadata['status'] ) ? $item_metadata['status'] : null; // phpcs:ignore
114 $this->progress = ! empty( $item_metadata['progress'] ) ? $item_metadata['progress'] : 0;
115 $this->startDate = UpStream_Model_Object::loadDate( $item_metadata, 'start_date' ); // phpcs:ignore
116 $this->endDate = UpStream_Model_Object::loadDate( $item_metadata, 'end_date' ); // phpcs:ignore
117 $this->milestoneId = ! empty( $item_metadata['milestone'] ) ? $item_metadata['milestone'] : null; // phpcs:ignore
118 $this->notes = ! empty( $item_metadata['notes'] ) ? $item_metadata['notes'] : '';
119
120 if ( ! empty( $item_metadata['reminders'] ) ) {
121 foreach ( $item_metadata['reminders'] as $reminder_data ) {
122 $exception = null;
123 try {
124 $d = json_decode( $reminder_data, true );
125 $reminder = new UpStream_Model_Reminder( $d );
126 $this->reminders[] = $reminder;
127 } catch ( \Exception $e ) {
128 $exception = $e; // don't add anything else.
129 }
130 }
131 }
132
133 if ( ! empty( $item_metadata['records'] ) ) {
134 foreach ( $item_metadata['records'] as $tr_data ) {
135 $exception = null;
136 try {
137 $d = json_decode( $tr_data, true );
138 $time_record = new UpStream_Model_TimeRecord( $d );
139 $this->timeRecords[] = $time_record; // phpcs:ignore
140 } catch ( \Exception $e ) {
141 $exception = $e; // don't add anything else.
142 }
143 }
144 }
145
146 }
147
148 /**
149 * Store To Array
150 *
151 * @param mixed $item_metadata Item Metadata.
152 * @return void
153 */
154 public function storeToArray( &$item_metadata ) {
155 parent::storeToArray( $item_metadata );
156
157 // Phpcs ignore camelCase methods and object properties.
158 // phpcs:disable
159 if ( null !== $this->statusCode ) {
160 $item_metadata['status'] = $this->statusCode;
161 }
162 if ( $this->progress >= 0 ) {
163 $item_metadata['progress'] = $this->progress;
164 }
165 if ( null !== $this->startDate ) {
166 $item_metadata['start_date'] = UpStream_Model_Object::ymdToTimestamp( $this->startDate );
167 }
168 if ( null !== $this->endDate ) {
169 $item_metadata['end_date'] = UpStream_Model_Object::ymdToTimestamp( $this->endDate );
170 }
171 if ( null !== $this->startDate ) {
172 $item_metadata['start_date.YMD'] = $this->startDate;
173 }
174 if ( null !== $this->endDate ) {
175 $item_metadata['end_date.YMD'] = $this->endDate;
176 }
177 if ( null !== $this->notes ) {
178 $item_metadata['notes'] = $this->notes;
179 }
180 if ( $this->milestoneId > 0 ) {
181 $item_metadata['milestone'] = $this->milestoneId;
182 }
183 // phpcs:enable
184
185 $item_metadata['reminders'] = array();
186
187 foreach ( $this->reminders as $reminder ) {
188 $r = array();
189 $reminder->storeToArray( $r );
190 $item_metadata['reminders'][] = json_encode( $r );
191 }
192
193 $item_metadata['time_records'] = array();
194
195 foreach ( $this->timeRecords as $tr ) { // phpcs:ignore
196 $r = array();
197 $tr->storeToArray( $r );
198 $item_metadata['records'][] = json_encode( $r );
199 }
200 }
201
202 /**
203 * Calculate Elapsed Time
204 */
205 public function calculateElapsedTime() {
206 $total = 0;
207
208 foreach ( $this->timeRecords as $tr ) { // phpcs:ignore
209 $total += $tr->elapsedTime; // phpcs:ignore
210 }
211
212 return $total;
213 }
214
215 /**
216 * Calculate Budgeted
217 */
218 public function calculateBudgeted() {
219 $total = 0;
220
221 foreach ( $this->timeRecords as $tr ) { // phpcs:ignore
222 $total += $tr->budgeted;
223 }
224
225 return $total;
226 }
227
228 /**
229 * Calculate Spent
230 */
231 public function calculateSpent() {
232 $total = 0;
233
234 foreach ( $this->timeRecords as $tr ) { // phpcs:ignore
235 $total += $tr->spent;
236 }
237
238 return $total;
239 }
240
241 /**
242 * Get Milestone
243 */
244 public function getMilestone() {
245 if ( $this->milestoneId ) { // phpcs:ignore
246 $exception = null;
247 try {
248 return \UpStream_Model_Manager::get_instance()->getByID(
249 UPSTREAM_ITEM_TYPE_MILESTONE,
250 $this->milestoneId, // phpcs:ignore
251 UPSTREAM_ITEM_TYPE_PROJECT,
252 $this->parent->id
253 );
254 } catch ( \Exception $e ) {
255 $exception = $e;
256 }
257 }
258
259 return null;
260 }
261
262 /**
263 * Set Milestone
264 *
265 * @param mixed $milestone Milestone.
266 * @return void
267 */
268 public function setMilestone( $milestone ) {
269 $this->milestoneId = $milestone->id; // phpcs:ignore
270 }
271
272 /**
273 * Get
274 *
275 * @param mixed $property Property.
276 */
277 public function __get( $property ) {
278 $property = apply_filters( 'upstream_wcs_model_variable', $property );
279
280 switch ( $property ) {
281
282 case 'milestone':
283 return $this->getMilestone();
284
285 case 'status':
286 $s = $this->getStatuses();
287
288 foreach ( $s as $s_key => $s_value ) {
289 if ( $this->statusCode === $s_key ) { // phpcs:ignore
290 return $s_value;
291 }
292 }
293 return '';
294
295 case 'elapsedTime':
296 return $this->calculateElapsedTime();
297 case 'budgeted':
298 return $this->calculateBudgeted();
299 case 'spent':
300 return $this->calculateSpent();
301
302 case 'statusCode':
303 case 'notes':
304 case 'milestoneId':
305 case 'progress':
306 case 'timeRecords':
307 case 'startDate':
308 case 'endDate':
309 return $this->{$property};
310
311 default:
312 return parent::__get( $property );
313 }
314 }
315
316 /**
317 * Set
318 *
319 * @param mixed $property Property.
320 * @param mixed $value Value.
321 * @throws UpStream_Model_ArgumentException Exception.
322 */
323 public function __set( $property, $value ) {
324 $property = apply_filters( 'upstream_wcs_model_variable', $property );
325
326 switch ( $property ) {
327
328 case 'milestone':
329 if ( ! $value instanceof UpStream_Model_Milestone ) {
330 throw new UpStream_Model_ArgumentException( __( 'Argument must be of type milestone.', 'upstream' ) );
331 } elseif ( 0 === $value->id ) {
332 throw new UpStream_Model_ArgumentException( __( 'Milestone must be stored before setting.', 'upstream' ) );
333 }
334
335 return $this->setMilestone( $value );
336
337 case 'status':
338 $s = $this->getStatuses();
339 $sc = null;
340
341 foreach ( $s as $s_key => $s_value ) {
342 if ( $value === $s_value ) {
343 $sc = $s_key;
344 break;
345 }
346 }
347
348 if ( null === $sc ) {
349 throw new UpStream_Model_ArgumentException(
350 sprintf(
351 // translators: %s: status.
352 __( 'Status %s is invalid.', 'upstream' ),
353 $value
354 )
355 );
356 }
357
358 $this->statusCode = $sc; // phpcs:ignore
359
360 break;
361
362 case 'statusCode':
363 $s = $this->getStatuses();
364 $sc = null;
365
366 foreach ( $s as $s_key => $s_value ) {
367 if ( $value === $s_key ) {
368 $sc = $s_key;
369 break;
370 }
371 }
372
373 if ( null === $sc ) {
374 throw new UpStream_Model_ArgumentException(
375 sprintf(
376 // translators: %s: status code.
377 __( 'Status code %s is invalid.', 'upstream' ),
378 $value
379 )
380 );
381 }
382
383 $this->statusCode = $sc; // phpcs:ignore
384
385 break;
386
387 case 'notes':
388 $this->notes = wp_kses_post( $value );
389 break;
390
391 case 'milestoneId':
392 $milestone = UpStream_Model_Manager::get_instance()->getByID( UPSTREAM_ITEM_TYPE_MILESTONE, $value, UPSTREAM_ITEM_TYPE_PROJECT, $this->parent->id );
393 $this->milestoneId = $milestone->id; // phpcs:ignore
394 break;
395
396 case 'progress':
397 if ( ! filter_var( $value, FILTER_VALIDATE_INT ) || (int) $value < 0 || (int) $value > 100 || ( (int) $value ) % 5 !== 0 ) {
398 throw new UpStream_Model_ArgumentException( __( 'Argument must be a multiple of 5 between 0 and 100.', 'upstream' ) );
399 }
400
401 $this->{$property} = $value;
402 break;
403
404 case 'startDate':
405 case 'endDate':
406 if ( ! self::isValidDate( $value ) ) {
407 throw new UpStream_Model_ArgumentException( __( 'Argument is not a valid date of the form YYYY-MM-DD.', 'upstream' ) );
408 }
409
410 $this->{$property} = $value;
411 break;
412
413 case 'timeRecords':
414 if ( ! is_array( $value ) ) {
415 throw new UpStream_Model_ArgumentException( __( 'Argument must be an array of UpStream_Model_TimeRecord objects.', 'upstream' ) );
416 }
417
418 foreach ( $value as $item ) {
419 if ( ! $item instanceof UpStream_Model_TimeRecord ) {
420 throw new UpStream_Model_ArgumentException( __( 'Argument must be an array of UpStream_Model_TimeRecord objects.', 'upstream' ) );
421 }
422 }
423
424 $this->{$property} = $value;
425 break;
426
427 default:
428 parent::__set( $property, $value );
429 break;
430 }
431 }
432
433 /**
434 * Fields
435 */
436 public static function fields() {
437 $fields = parent::fields();
438
439 $fields['notes'] = array(
440 'type' => 'text',
441 'title' => __( 'Notes' ),
442 'search' => true,
443 'display' => true,
444 );
445 $fields['startDate'] = array(
446 'type' => 'date',
447 'title' => __( 'Start Date' ),
448 'search' => true,
449 'display' => true,
450 );
451 $fields['endDate'] = array(
452 'type' => 'date',
453 'title' => __( 'End Date' ),
454 'search' => true,
455 'display' => true,
456 );
457 $fields['statusCode'] = array(
458 'type' => 'select',
459 'title' => __( 'Status' ),
460 'search' => true,
461 'display' => true,
462 'options_cb' => 'UpStream_Model_Task::getStatuses',
463 );
464 $fields['progress'] = array(
465 'type' => 'number',
466 'title' => __( 'Progress (%)' ),
467 'search' => true,
468 'display' => true,
469 );
470
471 unset( $fields['description'] );
472
473 $fields = self::customFields( $fields, UPSTREAM_ITEM_TYPE_TASK );
474
475 return $fields;
476 }
477
478 /**
479 * Get Statuses
480 */
481 public static function getStatuses() {
482 $option = get_option( 'upstream_tasks' );
483 $statuses = isset( $option['statuses'] ) ? $option['statuses'] : '';
484 $array = array();
485 if ( $statuses ) {
486 foreach ( $statuses as $status ) {
487 $array[ $status['id'] ] = $status['name'];
488 }
489 }
490
491 return $array;
492 }
493
494 /**
495 * Create
496 *
497 * @param mixed $parent Parent.
498 * @param mixed $title Title.
499 * @param mixed $created_by Created By.
500 * @throws UpStream_Model_ArgumentException Exception.
501 */
502 public static function create( $parent, $title, $created_by ) {
503 if ( get_userdata( $created_by ) === false ) {
504 throw new UpStream_Model_ArgumentException( __( 'User ID does not exist.', 'upstream' ) );
505 }
506
507 $item_metadata =
508 array(
509 'title' => sanitize_text_field( $title ),
510 'created_by' => $created_by,
511 );
512
513 return new self( $parent, $item_metadata );
514 }
515
516 }
517