Completed
Push — master ( b02a3c...bb6279 )
by Vladimir
02:13
created

Pulse::getBoardId()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
/**
4
 * This file contains the Pulse class
5
 *
6
 * @copyright 2015 Vladimir Jimenez
7
 * @license   https://github.com/allejo/PhpPulse/blob/master/LICENSE.md MIT
8
 */
9
10
namespace allejo\DaPulse;
11
12
use allejo\DaPulse\Exceptions\HttpException;
13
use allejo\DaPulse\Exceptions\InvalidColumnException;
14
use allejo\DaPulse\Exceptions\InvalidObjectException;
15
use allejo\DaPulse\Objects\PulseColumnDateValue;
16
use allejo\DaPulse\Objects\PulseColumnPersonValue;
17
use allejo\DaPulse\Objects\PulseColumnStatusValue;
18
use allejo\DaPulse\Objects\PulseColumnTextValue;
19
use allejo\DaPulse\Objects\PulseColumnValue;
20
use allejo\DaPulse\Objects\SubscribableObject;
21
use allejo\DaPulse\Utilities\ArrayUtilities;
22
23
/**
24
 * A class representing a single pulse in a board
25
 *
26
 * @api
27
 * @package allejo\DaPulse
28
 * @since   0.1.0
29
 */
30
class Pulse extends SubscribableObject
31
{
32
    /**
33
     * @ignore
34
     */
35
    const API_PREFIX = "pulses";
36
37
    // ================================================================================================================
38
    //   Instance Variables
39
    // ================================================================================================================
40
41
    /**
42
     * The resource's URL.
43
     *
44
     * @var string
45
     */
46
    protected $url;
47
48
    /**
49
     * The pulse's name.
50
     *
51
     * @var string
52
     */
53
    protected $name;
54
55
    /**
56
     * The board's subscribers.
57
     *
58
     * @var PulseUser[]
59
     */
60
    protected $subscribers;
61
62
    /**
63
     * The amount of updates a pulse has.
64
     *
65
     * @var int
66
     */
67
    protected $updates_count;
68
69
    /**
70
     * The ID of the parent board.
71
     *
72
     * @var int
73
     */
74
    protected $board_id;
75
76
    /**
77
     * Creation time.
78
     *
79
     * @var \DateTime
80
     */
81
    protected $created_at;
82
83
    /**
84
     * Last update time.
85
     *
86
     * @var \DateTime
87
     */
88
    protected $updated_at;
89
90
    /**
91
     * The ID of the group this pulse belongs to
92
     *
93
     * @var string
94
     */
95
    protected $group_id;
96
97
    /**
98
     * @var PulseColumn[]
99
     */
100
    protected $column_structure;
101
102
    /**
103
     * An array containing all of the values a pulse has for each column
104
     *
105
     * @var mixed
106
     */
107
    protected $raw_column_values;
108
109
    /**
110
     * An array containing objects extended from PulseColumnValue storing all of the values for each column
111
     *
112
     * @var array
113
     */
114
    protected $column_values;
115
116
    /**
117
     * The common URL path for retrieving objects relating a pulse such as subscribers, notes, or updates
118
     *
119
     * @var string
120
     */
121
    private $urlSyntax = "%s/%s/%s.json";
122
123
    // ================================================================================================================
124
    //   Overloaded functions
125
    // ================================================================================================================
126
127
    protected function initializeValues ()
128
    {
129
        $this->column_values     = array();
130
        $this->column_structure  = array();
131
        $this->raw_column_values = array();
132
    }
133
134
    // ================================================================================================================
135
    //   Getter functions
136
    // ================================================================================================================
137
138
    /**
139
     * The resource's URL.
140
     *
141
     * @return string
142
     */
143
    public function getUrl ()
144
    {
145
        return $this->url;
146
    }
147
148
    /**
149
     * The pulse's name.
150
     *
151
     * @return string
152
     */
153
    public function getName ()
154
    {
155
        return $this->name;
156
    }
157
158
    /**
159
     * The amount of updates a pulse has.
160
     *
161
     * @return int
162
     */
163
    public function getUpdatesCount ()
164
    {
165
        return $this->updates_count;
166
    }
167
168
    /**
169
     * The ID of the parent board.
170
     *
171
     * @return int
172
     */
173
    public function getBoardId ()
174
    {
175
        return $this->board_id;
176
    }
177
178
    /**
179
     * Creation time.
180
     *
181
     * @return \DateTime
182
     */
183
    public function getCreatedAt ()
184
    {
185
        self::lazyLoad($this->created_at, '\DateTime');
186
187
        return $this->created_at;
188
    }
189
190
    /**
191
     * Last update time.
192
     *
193
     * @return \DateTime
194
     */
195
    public function getUpdatedAt ()
196
    {
197
        self::lazyLoad($this->updated_at, '\DateTime');
198
199
        return $this->updated_at;
200
    }
201
202
    /**
203
     * Get the ID of the group this Pulse is a part of. If this value is not available, an API call will be made to
204
     * find the group ID via brute force.
205
     *
206
     * **Note** The group ID is cached if it is not available. To update the cached value, use $forceFetch to force an
207
     * API call to get a new value.
208
     *
209
     * **Warning** An API call is always slower than using the cached value.
210
     *
211
     * @param bool $forceFetch Force an API call to get an updated group ID if it has been changed
212
     *
213
     * @since 0.1.0
214
     * @return string
215
     */
216
    public function getGroupId ($forceFetch = false)
217
    {
218
        if (empty($this->group_id) || $forceFetch)
219
        {
220
            $parentBoard = new PulseBoard($this->board_id);
221
            $pulses      = $parentBoard->getPulses();
222
223
            foreach ($pulses as $pulse)
224
            {
225
                if ($this->getId() === $pulse->getId())
226
                {
227
                    $this->group_id = $pulse->getGroupId();
228
                    break;
229
                }
230
            }
231
        }
232
233
        return $this->group_id;
234
    }
235
236
    // ================================================================================================================
237
    //   Pulse functions
238
    // ================================================================================================================
239
240
    /**
241
     * Edit the name of the pulse
242
     *
243
     * @api
244
     * @param string $title
245
     * @since 0.1.0
246
     */
247
    public function editName($title)
248
    {
249
        $editUrl    = sprintf("%s/%d.json", self::apiEndpoint(), $this->getId());
250
        $postParams = array(
251
            'name' => $title
252
        );
253
254
        $this->jsonResponse = self::sendPut($editUrl, $postParams);
0 ignored issues
show
Documentation Bug introduced by
It seems like self::sendPut($editUrl, $postParams) of type * is incompatible with the declared type array of property $jsonResponse.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
255
        $this->assignResults();
256
    }
257
258
    /**
259
     * Archive the current pulse.
260
     *
261
     * This is the equivalent of a soft delete and can be restored from the DaPulse website.
262
     *
263
     * @api
264
     * @since 0.1.0
265
     */
266
    public function archivePulse()
267
    {
268
        $archiveURL = sprintf("%s/%d.json", self::apiEndpoint(), $this->getId());
269
        $getParams  = array(
270
            'archive' => true
271
        );
272
273
        self::sendDelete($archiveURL, $getParams);
274
    }
275
276
    /**
277
     * Delete the current Pulse
278
     *
279
     * @api
280
     * @throws \allejo\DaPulse\Exceptions\InvalidObjectException
281
     */
282 View Code Duplication
    public function deletePulse ()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
283
    {
284
        $this->checkInvalid();
285
286
        $deleteURL = sprintf("%s/%d.json", self::apiEndpoint(), $this->getId());
287
288
        self::sendDelete($deleteURL);
289
290
        $this->deletedObject = true;
291
    }
292
293
    public function duplicatePulse ($groupId = NULL, $ownerId = NULL)
294
    {
295
        $url        = sprintf("%s/%s/pulses/%s/duplicate.json", self::apiEndpoint("boards"), $this->getBoardId(), $this->getId());
296
        $postParams = array();
297
298
        if ($ownerId instanceof PulseUser)
299
        {
300
            $ownerId = $ownerId->getId();
301
        }
302
303
        self::setIfNotNullOrEmpty($postParams, "group_id", $groupId);
304
        self::setIfNotNullOrEmpty($postParams, "owner_id", $ownerId);
305
306
        $result = self::sendPost($url, $postParams);
307
        $this->pulseInjection($result);
308
309
        return (new Pulse($result['pulse']));
310
    }
311
312 View Code Duplication
    private function pulseInjection (&$result)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
313
    {
314
        $parentBoard = new PulseBoard($this->getBoardId());
315
316
        // Inject some information so a Pulse object can survive on its own
317
        $result["pulse"]["group_id"]          = $result["board_meta"]["group_id"];
318
        $result["pulse"]["column_structure"]  = $parentBoard->getColumns();
319
        $result["pulse"]["raw_column_values"] = $result["column_values"];
320
    }
321
322
    // ================================================================================================================
323
    //   Column data functions
324
    // ================================================================================================================
325
326
    /**
327
     * Access a pulse's specific column to either access their value or to modify the value.
328
     *
329
     * See the related functions to see the appropriate replacements.
330
     *
331
     * @todo       This function only exists for legacy applications. Remove in 0.1.1
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
332
     *
333
     * @api
334
     * @deprecated 0.0.1 This function will be removed by 0.2.0. New stricter functions are available
335
     *
336
     * @param string $columnId The ID of the column to access. It's typically a slugified version of the column title
337
     *
338
     * @see        Pulse::getStatusColumn()  getColorColumn()
339
     * @see        Pulse::getDateColumn()   getDateColumn()
340
     * @see        Pulse::getPersonColumn() getPersonColumn()
341
     * @see        Pulse::getTextColumn()   getTextColumn()
342
     * @since      0.1.0
343
     * @throws InvalidObjectException The specified column exists but modification of its value is unsupported either
344
     *                                by this library or the DaPulse API.
345
     * @throws InvalidColumnException   The specified column ID does not exist for this Pulse
346
     * @return PulseColumnValue The returned object will be a child of this abstract class.
347
     */
348
    public function getColumnValue ($columnId)
349
    {
350
        if (!isset($this->column_values) || !array_key_exists($columnId, $this->column_values))
351
        {
352
            $key = ArrayUtilities::array_search_column($this->raw_column_values, 'cid', $columnId);
353
354
            $data = $this->raw_column_values[$key];
355
            $type = $this->column_structure[$key]->getType();
356
357
            $data['column_id'] = $data['cid'];
358
            $data['board_id']  = $this->getBoardId();
359
            $data['pulse_id']  = $this->getId();
360
361
            $this->column_values[$columnId] = PulseColumnValue::_createColumnType($type, $data);
362
        }
363
364
        return $this->column_values[$columnId];
365
    }
366
367
    /**
368
     * Access a color type column value belonging to this pulse in order to read it or modify.
369
     *
370
     * This function should only be used to access color type values; an exception will be thrown otherwise.
371
     *
372
     * @api
373
     *
374
     * @param string $columnId The ID of the column to access. This is typically a slugified version of the column name
375
     *
376
     * @since 0.1.0
377
     * @throws InvalidColumnException The specified column is not a "color" type column
378
     * @throws InvalidObjectException The specified column exists but modification of its value is unsupported either
379
     *                                by this library or the DaPulse API.
380
     * @throws InvalidColumnException   The specified column ID does not exist for this Pulse
381
     * @return PulseColumnStatusValue A column object with access to its contents
382
     */
383
    public function getStatusColumn ($columnId)
384
    {
385
        return $this->getColumn($columnId, PulseColumn::Status);
386
    }
387
388
    /**
389
     * Access a date type column value belonging to this pulse in order to read it or modify.
390
     *
391
     * This function should only be used to access data type values; an exception will be thrown otherwise.
392
     *
393
     * @api
394
     *
395
     * @param string $columnId The ID of the column to access. This is typically a slugified version of the column name
396
     *
397
     * @since                         0.1.0
398
     * @throws InvalidColumnException The specified column is not a "date" type column
399
     * @throws InvalidObjectException The specified column exists but modification of its value is unsupported either
400
     *                                by this library or the DaPulse API.
401
     * @throws InvalidColumnException   The specified column ID does not exist for this Pulse
402
     * @return PulseColumnDateValue A column object with access to its contents
403
     */
404
    public function getDateColumn ($columnId)
405
    {
406
        return $this->getColumn($columnId, PulseColumn::Date);
407
    }
408
409
    /**
410
     * Access a person type column value belonging to this pulse in order to read it or modify.
411
     *
412
     * This function should only be used to access person type values; an exception will be thrown otherwise.
413
     *
414
     * @api
415
     *
416
     * @param string $columnId The ID of the column to access. This is typically a slugified version of the column name
417
     *
418
     * @since                         0.1.0
419
     * @throws InvalidColumnException The specified column is not a "person" type column
420
     * @throws InvalidObjectException The specified column exists but modification of its value is unsupported either
421
     *                                by this library or the DaPulse API.
422
     * @throws InvalidColumnException   The specified column ID does not exist for this Pulse
423
     * @return PulseColumnPersonValue A column object with access to its contents
424
     */
425
    public function getPersonColumn ($columnId)
426
    {
427
        return $this->getColumn($columnId, PulseColumn::Person);
428
    }
429
430
    /**
431
     * Access a text type column value belonging to this pulse in order to read it or modify.
432
     *
433
     * This function should only be used to access text type values; an exception will be thrown otherwise.
434
     *
435
     * @api
436
     *
437
     * @param string $columnId The ID of the column to access. This is typically a slugified version of the column name
438
     *
439
     * @since                         0.1.0
440
     * @throws InvalidColumnException The specified column is not a "text" type column
441
     * @throws InvalidObjectException The specified column exists but modification of its value is unsupported either
442
     *                                by this library or the DaPulse API.
443
     * @throws InvalidColumnException   The specified column ID does not exist for this Pulse
444
     * @return PulseColumnTextValue A column object with access to its contents
445
     */
446
    public function getTextColumn ($columnId)
447
    {
448
        return $this->getColumn($columnId, PulseColumn::Text);
449
    }
450
451
    /**
452
     * Build a pulse's column object if it doesn't exist or return the existing column.
453
     *
454
     * @param string $columnId   The ID of the column to access. This is typically a slugified version of the column
455
     *                           title
456
     * @param string $columnType The type of column being accessed: 'text', 'color', 'person', or 'date'
457
     *
458
     * @since 0.1.0
459
     *
460
     * @throws InvalidColumnException The specified column is not the same type as specified in `$columnType`
461
     * @throws InvalidObjectException The specified column exists but modification of its value is unsupported either
462
     *                                by this library or the DaPulse API.
463
     * @throws InvalidColumnException   The specified column ID does not exist for this Pulse
464
     *
465
     * @return PulseColumnValue The returned object will be a child of this abstract class.
466
     */
467
    private function getColumn ($columnId, $columnType)
468
    {
469
        if (!isset($this->column_values) || !array_key_exists($columnId, $this->column_values))
470
        {
471
            $key  = ArrayUtilities::array_search_column($this->raw_column_values, 'cid', $columnId);
472
            $data = array();
473
474
            // We can't find the key, this means that we got our information from accessing a Pulse directly instead of
475
            // getting it through a PulseBoard. This isn't as robust as accessing a PulseBoard but it's more efficient.
476
            // We make a separate API call to get the value of a column.
477
            if ($key === false)
478
            {
479
                $url    = sprintf("%s/%d/columns/%s/value.json", self::apiEndpoint("boards"), $this->getBoardId(), $columnId);
480
                $params = array(
481
                    "pulse_id" => $this->getId()
482
                );
483
484
                try
485
                {
486
                    $results = self::sendGet($url, $params);
487
                }
488
                catch (HttpException $e)
489
                {
490
                    throw new InvalidColumnException("The '$columnId' column could not be found");
491
                }
492
493
                // Store our value inside of jsonResponse so all of the respective objects can treat the data the same
494
                // as when accessed through a PulseBoard
495
                $data['jsonResponse']['value'] = $results['value'];
496
            }
497
            else
498
            {
499
                $data = $this->raw_column_values[$key];
500
                $type = $this->column_structure[$key]->getType();
501
502
                if ($type !== $columnType)
503
                {
504
                    throw new InvalidColumnException("The '$columnId' column was expected to be '$columnType' but was '$type' instead.");
505
                }
506
            }
507
508
            $data['column_id'] = $columnId;
509
            $data['board_id']  = $this->getBoardId();
510
            $data['pulse_id']  = $this->getId();
511
512
            $this->column_values[$columnId] = PulseColumnValue::_createColumnType($columnType, $data);
513
        }
514
515
        return $this->column_values[$columnId];
516
    }
517
518
    // ================================================================================================================
519
    //   Notes functions
520
    // ================================================================================================================
521
522
    /**
523
     * Create a new note in this project
524
     *
525
     * @api
526
     *
527
     * @param  string   $title         The title of the note
528
     * @param  string   $content       The body of the note
529
     * @param  bool     $ownersOnly    Set to true if only pulse owners can edit this note.
530
     * @param  int|null $userId        The id of the user to be marked as the note's last updater
531
     * @param  bool     $createUpdate  Indicates whether to create an update on the pulse notifying subscribers on the
532
     *                                 changes (required user_id to be set).
533
     *
534
     * @since  0.1.0
535
     * @return PulseNote
536
     */
537
    public function addNote ($title, $content, $ownersOnly = false, $userId = NULL, $createUpdate = false)
538
    {
539
        $url        = sprintf($this->urlSyntax, self::apiEndpoint(), $this->id, "notes");
540
        $postParams = array(
541
            "id"            => $this->id,
542
            "title"         => $title,
543
            "content"       => $content,
544
            "owners_only"   => $ownersOnly,
545
            "create_update" => $createUpdate
546
        );
547
548
        self::setIfNotNullOrEmpty($postParams, "user_id", $userId);
549
550
        if ($createUpdate && is_null($userId))
551
        {
552
            throw new \InvalidArgumentException("The user_id value must be set if an update is to be created");
553
        }
554
555
        $noteResult = self::sendPost($url, $postParams);
556
557
        return (new PulseNote($noteResult));
558
    }
559
560
    /**
561
     * Return all of the notes belonging to this project
562
     *
563
     * @api
564
     * @since  0.1.0
565
     * @return PulseNote[]
566
     */
567
    public function getNotes ()
568
    {
569
        $url = sprintf($this->urlSyntax, self::apiEndpoint(), $this->id, "notes");
570
571
        return self::fetchJsonArrayToObjectArray($url, "PulseNote");
572
    }
573
574
    // ================================================================================================================
575
    //   Updates functions
576
    // ================================================================================================================
577
578
    /**
579
     * Get all of the updates that belong this Pulse in reverse chronological order
580
     *
581
     * @api
582
     * @since 0.1.0
583
     * @return PulseUpdate[]
584
     */
585
    public function getUpdates ()
586
    {
587
        $url = sprintf($this->urlSyntax, self::apiEndpoint(), $this->id, "updates");
588
589
        return self::fetchJsonArrayToObjectArray($url, "PulseUpdate");
590
    }
591
592
    /**
593
     * Create an update for the current Pulse
594
     *
595
     * @api
596
     *
597
     * @param int|PulseUser $user
598
     * @param string        $text
599
     * @param null|bool     $announceToAll
600
     *
601
     * @since 0.1.0
602
     */
603
    public function createUpdate ($user, $text, $announceToAll = NULL)
604
    {
605
        PulseUpdate::createUpdate($user, $this->getId(), $text, $announceToAll);
606
    }
607
608
    // ================================================================================================================
609
    //   Static functions
610
    // ================================================================================================================
611
612
    /**
613
     * Get all of the pulses that belong to the organization across all boards.
614
     *
615
     * To modify the amount of data returned with pagination, use the following values in the array to configure your
616
     * pagination or offsets.
617
     *
618
     * ```php
619
     * $params = array(
620
     *     "page"     => 1,          // (int) Page offset to fetch
621
     *     "per_page" => 10,         // (int) Number of results per page
622
     *     "offset"   => 5,          // (int) Instead of starting at result 0, start counting from result 5
623
     *     "order_by_latest" => true // (bool) Order the pulses with the most recent first
624
     * );
625
     * ```
626
     *
627
     * @api
628
     *
629
     * @param array $params GET parameters passed to with the query to modify the data returned.
630
     *
631
     * @since 0.1.0
632
     * @return Pulse[]
633
     */
634
    public static function getPulses ($params = array())
635
    {
636
        $url = sprintf("%s.json", self::apiEndpoint());
637
638
        return self::fetchJsonArrayToObjectArray($url, "Pulse", $params);
639
    }
640
}