Completed
Push — develop ( 21c609...db7143 )
by Vladimir
04:02
created

Pulse::editPulseNameByID()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 6
ccs 0
cts 0
cp 0
rs 9.4285
cc 1
eloc 3
nc 1
nop 2
crap 2
1
<?php
2
3
/**
4
 * @copyright 2017 Vladimir Jimenez
5
 * @license   https://github.com/allejo/PhpPulse/blob/master/LICENSE.md MIT
6
 */
7
8
namespace allejo\DaPulse;
9
10
use allejo\DaPulse\Exceptions\ColumnNotFoundException;
11
use allejo\DaPulse\Exceptions\HttpException;
12
use allejo\DaPulse\Exceptions\InvalidColumnException;
13
use allejo\DaPulse\Exceptions\InvalidObjectException;
14
use allejo\DaPulse\Objects\PulseColumnDateValue;
15
use allejo\DaPulse\Objects\PulseColumnNumericValue;
16
use allejo\DaPulse\Objects\PulseColumnPersonValue;
17
use allejo\DaPulse\Objects\PulseColumnStatusValue;
18
use allejo\DaPulse\Objects\PulseColumnTextValue;
19
use allejo\DaPulse\Objects\PulseColumnTimelineValue;
20
use allejo\DaPulse\Objects\PulseColumnValue;
21
use allejo\DaPulse\Objects\SubscribableObject;
22
use allejo\DaPulse\Utilities\ArrayUtilities;
23
24
/**
25
 * A class representing a single pulse in a board
26
 *
27
 * @api
28
 * @package allejo\DaPulse
29
 * @since   0.1.0
30
 */
31
class Pulse extends SubscribableObject
32
{
33
    /**
34
     * @ignore
35
     */
36
    const API_PREFIX = "pulses";
37
38
    // ================================================================================================================
39
    //   Instance Variables
40
    // ================================================================================================================
41
42
    /**
43
     * The resource's URL.
44
     *
45
     * @var string
46
     */
47
    protected $url;
48
49
    /**
50
     * The pulse's name.
51
     *
52
     * @var string
53
     */
54
    protected $name;
55
56
    /**
57
     * The amount of updates a pulse has.
58
     *
59
     * @var int
60
     */
61
    protected $updates_count;
62
63
    /**
64
     * The ID of the parent board.
65
     *
66
     * @var int
67
     */
68
    protected $board_id;
69
70
    /**
71
     * Creation time.
72
     *
73
     * @var \DateTime
74
     */
75
    protected $created_at;
76
77
    /**
78
     * Last update time.
79
     *
80
     * @var \DateTime
81
     */
82
    protected $updated_at;
83
84
    /**
85
     * The ID of the group this pulse belongs to
86
     *
87
     * @var string
88
     */
89
    protected $group_id;
90
91
    /**
92
     * @var PulseColumn[]
93
     */
94
    protected $column_structure;
95
96
    /**
97
     * An array containing all of the values a pulse has for each column
98
     *
99
     * @var mixed
100
     */
101
    protected $raw_column_values;
102
103
    /**
104
     * An array containing objects extended from PulseColumnValue storing all of the values for each column
105
     *
106
     * @var array
107
     */
108
    protected $column_values;
109
110
    /**
111
     * The common URL path for retrieving objects relating a pulse such as subscribers, notes, or updates
112
     *
113
     * @var string
114
     */
115
    private $urlSyntax = "%s/%s/%s.json";
116
117
    // ================================================================================================================
118
    //   Overloaded functions
119
    // ================================================================================================================
120
121
    protected function initializeValues ()
122
    {
123 70
        $this->column_values     = array();
124
        $this->column_structure  = array();
125 70
        $this->raw_column_values = array();
126 70
    }
127 70
128 70
    // ================================================================================================================
129
    //   Getter functions
130
    // ================================================================================================================
131
132
    /**
133
     * The resource's URL.
134
     *
135
     * @return string
136
     */
137
    public function getUrl ()
138
    {
139 1
        $this->lazyLoad();
140
141 1
        return $this->url;
142
    }
143
144
    /**
145
     * The pulse's name.
146
     *
147
     * @return string
148
     */
149 2
    public function getName ()
150
    {
151 2
        $this->lazyLoad();
152
153
        return $this->name;
154
    }
155
156
    /**
157
     * The amount of updates a pulse has.
158
     *
159 1
     * @return int
160
     */
161 1
    public function getUpdatesCount ()
162
    {
163
        $this->lazyLoad();
164
165
        return $this->updates_count;
166
    }
167
168
    /**
169 40
     * The ID of the parent board.
170
     *
171 40
     * @return int
172
     */
173
    public function getBoardId ()
174
    {
175
        $this->lazyLoad();
176
177
        return $this->board_id;
178
    }
179 1
180
    /**
181 1
     * Creation time.
182
     *
183 1
     * @return \DateTime
184
     */
185
    public function getCreatedAt ()
186
    {
187
        $this->lazyLoad();
188
        self::lazyCast($this->created_at, '\DateTime');
189
190
        return $this->created_at;
191 1
    }
192
193 1
    /**
194
     * Last update time.
195 1
     *
196
     * @return \DateTime
197
     */
198
    public function getUpdatedAt ()
199
    {
200
        $this->lazyLoad();
201
        self::lazyCast($this->updated_at, '\DateTime');
202
203
        return $this->updated_at;
204
    }
205
206
    /**
207
     * 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
208
     * find the group ID via brute force.
209
     *
210
     * **Note** The group ID is cached if it is not available. To update the cached value, use $forceFetch to force an
211
     * API call to get a new value.
212 1
     *
213
     * **Warning** An API call is always slower than using the cached value.
214 1
     *
215
     * @param bool $forceFetch Force an API call to get an updated group ID if it has been changed
216 1
     *
217 1
     * @since 0.1.0
218
     * @return string
219 1
     */
220
    public function getGroupId ($forceFetch = false)
221 1
    {
222
        $this->lazyLoad();
223 1
224 1
        if (empty($this->group_id) || $forceFetch)
225
        {
226
            $parentBoard = new PulseBoard($this->board_id, true);
227
            $pulses      = $parentBoard->getPulses();
228
229 1
            foreach ($pulses as $pulse)
230
            {
231
                if ($this->getId() === $pulse->getId())
232
                {
233
                    $this->group_id = $pulse->getGroupId();
234
                    break;
235
                }
236
            }
237
        }
238
239
        return $this->group_id;
240
    }
241
242
    // ================================================================================================================
243
    //   Pulse functions
244
    // ================================================================================================================
245
246
    /**
247
     * Edit the name of the pulse
248
     *
249
     * @api
250
     * @param string $title
251
     * @since 0.1.0
252
     */
253
    public function editName($title)
254
    {
255
        $editUrl    = sprintf("%s/%d.json", self::apiEndpoint(), $this->getId());
256
        $postParams = array(
257
            'name' => $title
258
        );
259
260
        $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...
261
        $this->assignResults();
262
    }
263
264
    /**
265
     * Archive the current pulse
266
     *
267
     * This is the equivalent of a soft delete and can be restored from the DaPulse website.
268
     *
269
     * @api
270
     * @since 0.1.0
271
     */
272
    public function archivePulse ()
273
    {
274
        $archiveURL = sprintf("%s/%d.json", self::apiEndpoint(), $this->getId());
275
        $getParams  = array(
276
            'archive' => true
277
        );
278
279
        $this->jsonResponse = self::sendDelete($archiveURL, $getParams);
0 ignored issues
show
Documentation Bug introduced by
It seems like self::sendDelete($archiveURL, $getParams) 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...
280
        $this->assignResults();
281
    }
282
283
    /**
284
     * Delete the current Pulse
285
     *
286
     * @api
287
     * @since 0.1.0
288
     * @throws \allejo\DaPulse\Exceptions\InvalidObjectException
289
     */
290 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...
291
    {
292
        $this->checkInvalid();
293
294
        $deleteURL = sprintf("%s/%d.json", self::apiEndpoint(), $this->getId());
295
        $this->jsonResponse = self::sendDelete($deleteURL);
0 ignored issues
show
Documentation Bug introduced by
It seems like self::sendDelete($deleteURL) 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...
296
        $this->assignResults();
297
298
        $this->deletedObject = true;
299
    }
300
301
    public function duplicatePulse ($groupId = NULL, $ownerId = NULL)
302
    {
303
        $url        = sprintf("%s/%s/pulses/%s/duplicate.json", self::apiEndpoint("boards"), $this->getBoardId(), $this->getId());
304
        $postParams = array();
305
306
        if ($ownerId instanceof PulseUser)
307
        {
308
            $ownerId = $ownerId->getId();
309
        }
310
311
        self::setIfNotNullOrEmpty($postParams, "group_id", $groupId);
312
        self::setIfNotNullOrEmpty($postParams, "owner_id", $ownerId);
313
314
        $result = self::sendPost($url, $postParams);
315
        $this->pulseInjection($result);
316
317
        return (new Pulse($result['pulse']));
318
    }
319
320 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...
321
    {
322
        $parentBoard = new PulseBoard($this->getBoardId());
323
324
        // Inject some information so a Pulse object can survive on its own
325
        $result["pulse"]["group_id"]          = $result["board_meta"]["group_id"];
326
        $result["pulse"]["column_structure"]  = $parentBoard->getColumns();
327
        $result["pulse"]["raw_column_values"] = $result["column_values"];
328
    }
329
330
    // ================================================================================================================
331
    //   Column data functions
332
    // ================================================================================================================
333
334
    /**
335
     * Access a color type column value belonging to this pulse in order to read it or modify.
336
     *
337
     * This function should only be used to access color type values; an exception will be thrown otherwise.
338
     *
339
     * @api
340 6
     *
341
     * @param  string $columnId The ID of the column to access. This is typically a slugified version of the column name
342 6
     *
343
     * @since  0.1.0
344
     *
345
     * @throws ColumnNotFoundException The specified column ID does not exist for this Pulse
346
     * @throws InvalidColumnException  The specified column is not a "color" type column
347
     * @throws InvalidObjectException  The specified column exists but modification of its value is unsupported either
348
     *                                 by this library or the DaPulse API.
349
     *
350
     * @return PulseColumnStatusValue A column object with access to its contents
351
     */
352
    public function getStatusColumn ($columnId)
353
    {
354
        return $this->getColumn($columnId, PulseColumn::Status);
355
    }
356
357
    /**
358
     * Access a date type column value belonging to this pulse in order to read it or modify.
359
     *
360
     * This function should only be used to access data type values; an exception will be thrown otherwise.
361
     *
362
     * @api
363 9
     *
364
     * @param  string $columnId The ID of the column to access. This is typically a slugified version of the column name
365 9
     *
366
     * @since  0.1.0
367
     *
368
     * @throws ColumnNotFoundException The specified column ID does not exist for this Pulse
369
     * @throws InvalidColumnException  The specified column is not a "date" type column
370
     * @throws InvalidObjectException  The specified column exists but modification of its value is unsupported either
371
     *                                 by this library or the DaPulse API.
372
     *
373
     * @return PulseColumnDateValue A column object with access to its contents
374
     */
375
    public function getDateColumn ($columnId)
376
    {
377
        return $this->getColumn($columnId, PulseColumn::Date);
378
    }
379
380
    /**
381
     * Access a numeric type column value belonging to this pulse in order to read it or modify.
382
     *
383
     * This function should only be used to access data type values; an exception will be thrown otherwise.
384
     *
385
     * @api
386 7
     *
387
     * @param  string $columnId The ID of the column to access. This is typically a slugified version of the column name
388 7
     *
389
     * @since  0.2.0
390
     *
391
     * @throws ColumnNotFoundException The specified column ID does not exist for this Pulse
392
     * @throws InvalidColumnException  The specified column is not a "numeric" type column
393
     * @throws InvalidObjectException  The specified column exists but modification of its value is unsupported either
394
     *                                 by this library or the DaPulse API.
395
     *
396
     * @return PulseColumnNumericValue A column object with access to its contents
397
     */
398
    public function getNumericColumn ($columnId)
399
    {
400
        return $this->getColumn($columnId, PulseColumn::Numeric);
401
    }
402
403
    /**
404
     * Access a person type column value belonging to this pulse in order to read it or modify.
405
     *
406
     * This function should only be used to access person type values; an exception will be thrown otherwise.
407
     *
408
     * @api
409 9
     *
410
     * @param  string $columnId The ID of the column to access. This is typically a slugified version of the column name
411 9
     *
412
     * @since  0.1.0
413
     *
414
     * @throws ColumnNotFoundException The specified column ID does not exist for this Pulse
415
     * @throws InvalidColumnException  The specified column is not a "person" type column
416
     * @throws InvalidObjectException  The specified column exists but modification of its value is unsupported either
417
     *                                 by this library or the DaPulse API.
418
     *
419
     * @return PulseColumnPersonValue A column object with access to its contents
420
     */
421
    public function getPersonColumn ($columnId)
422
    {
423
        return $this->getColumn($columnId, PulseColumn::Person);
424
    }
425
426
    /**
427
     * Access a text type column value belonging to this pulse in order to read it or modify.
428
     *
429
     * This function should only be used to access text type values; an exception will be thrown otherwise.
430
     *
431
     * @api
432 4
     *
433
     * @param  string $columnId The ID of the column to access. This is typically a slugified version of the column name
434 4
     *
435
     * @since  0.1.0
436
437
     * @throws ColumnNotFoundException The specified column ID does not exist for this Pulse
438
     * @throws InvalidColumnException  The specified column is not a "text" type column
439
     * @throws InvalidObjectException  The specified column exists but modification of its value is unsupported either
440
     *                                 by this library or the DaPulse API.
441
     *
442
     * @return PulseColumnTextValue A column object with access to its contents
443
     */
444
    public function getTextColumn ($columnId)
445
    {
446
        return $this->getColumn($columnId, PulseColumn::Text);
447
    }
448
449
    /**
450
     * Access a timeline type column value belonging to this pulse in order to read it or modify.
451
     *
452
     * This function should only be used to access data type values; an exception will be thrown otherwise.
453
     *
454
     * @api
455 5
     *
456
     * @param  string $columnId The ID of the column to access. This is typically a slugified version of the column name
457 5
     *
458
     * @since  0.2.1
459
     *
460
     * @throws ColumnNotFoundException The specified column ID does not exist for this Pulse
461
     * @throws InvalidColumnException  The specified column is not a "numeric" type column
462
     * @throws InvalidObjectException  The specified column exists but modification of its value is unsupported either
463
     *                                 by this library or the DaPulse API.
464
     *
465
     * @return PulseColumnTimelineValue A column object with access to its contents
466
     */
467
    public function getTimelineColumn ($columnId)
468
    {
469
        return $this->getColumn($columnId, PulseColumn::Timeline);
470
    }
471
472
    /**
473
     * Build a pulse's column object if it doesn't exist or return the existing column.
474
     *
475
     * @param  string $columnId   The ID of the column to access. This is typically a slugified version of the column
476 40
     *                            title
477
     * @param  string $columnType The type of column being accessed: 'text', 'color', 'person', 'numeric', or 'date'
478 40
     *
479
     * @since  0.1.0
480 40
     *
481 40
     * @throws ColumnNotFoundException The specified column ID does not exist for this Pulse
482
     * @throws InvalidColumnException  The specified column is not the same type as specified in `$columnType`
483
     * @throws InvalidObjectException  The specified column exists but modification of its value is unsupported either
484
     *                                 by this library or the DaPulse API.
485
     *
486 40
     * @return PulseColumnValue The returned object will be a child of this abstract class.
487
     */
488 29
    private function getColumn ($columnId, $columnType)
489
    {
490 29
        if (!isset($this->column_values) || !array_key_exists($columnId, $this->column_values))
491
        {
492
            $key  = ArrayUtilities::array_search_column($this->raw_column_values, 'cid', $columnId);
493
            $data = array();
494
495 29
            // We can't find the key, this means that we got our information from accessing a Pulse directly instead of
496
            // getting it through a PulseBoard. This isn't as robust as accessing a PulseBoard but it's more efficient.
497 1
            // We make a separate API call to get the value of a column.
498
            if ($key === false)
499 1
            {
500
                $url    = sprintf("%s/%d/columns/%s/value.json", self::apiEndpoint("boards"), $this->getBoardId(), $columnId);
501
                $params = array(
502
                    "pulse_id" => $this->getId()
503
                );
504 28
505
                try
506
                {
507
                    $results = self::sendGet($url, $params);
508 11
                }
509 11
                catch (HttpException $e)
510
                {
511 11
                    throw new ColumnNotFoundException("The '$columnId' column could not be found");
512
                }
513 1
514
                // Store our value inside of jsonResponse so all of the respective objects can treat the data the same
515
                // as when accessed through a PulseBoard
516
                $data['jsonResponse']['value'] = $results['value'];
517 38
            }
518 38
            else
519 38
            {
520
                $data = $this->raw_column_values[$key];
521 38
                $type = $this->column_structure[$key]->getType();
522
523
                if ($type !== $columnType)
524 38
                {
525
                    throw new InvalidColumnException("The '$columnId' column was expected to be '$columnType' but was '$type' instead.");
526
                }
527
            }
528
529
            $data['column_id'] = $columnId;
530
            $data['board_id']  = $this->getBoardId();
531
            $data['pulse_id']  = $this->getId();
532
533
            $this->column_values[$columnId] = PulseColumnValue::_createColumnType($columnType, $data);
534
        }
535
536
        return $this->column_values[$columnId];
537
    }
538
539
    // ================================================================================================================
540
    //   Notes functions
541
    // ================================================================================================================
542
543
    /**
544
     * Create a new note in this project
545
     *
546
     * @api
547
     *
548
     * @param  string   $title         The title of the note
549
     * @param  string   $content       The body of the note
550
     * @param  bool     $ownersOnly    Set to true if only pulse owners can edit this note.
551
     * @param  int|null $userId        The id of the user to be marked as the note's last updater
552
     * @param  bool     $createUpdate  Indicates whether to create an update on the pulse notifying subscribers on the
553
     *                                 changes (required user_id to be set).
554
     *
555
     * @since  0.1.0
556
     * @return PulseNote
557
     */
558
    public function addNote ($title, $content, $ownersOnly = false, $userId = NULL, $createUpdate = false)
559
    {
560
        $url        = sprintf($this->urlSyntax, self::apiEndpoint(), $this->id, "notes");
561
        $postParams = array(
562
            "id"            => $this->id,
563
            "title"         => $title,
564
            "content"       => $content,
565
            "owners_only"   => $ownersOnly,
566
            "create_update" => $createUpdate
567
        );
568
569
        self::setIfNotNullOrEmpty($postParams, "user_id", $userId);
570
571
        if ($createUpdate && is_null($userId))
572
        {
573
            throw new \InvalidArgumentException("The user_id value must be set if an update is to be created");
574
        }
575
576
        $noteResult = self::sendPost($url, $postParams);
577
578
        return (new PulseNote($noteResult));
579
    }
580
581
    /**
582
     * Return all of the notes belonging to this project
583
     *
584
     * @api
585
     * @since  0.1.0
586
     * @return PulseNote[]
587
     */
588
    public function getNotes ()
589
    {
590
        $url = sprintf($this->urlSyntax, self::apiEndpoint(), $this->id, "notes");
591
592
        return self::fetchAndCastToObjectArray($url, "PulseNote");
593
    }
594
595
    // ================================================================================================================
596 20
    //   Updates functions
597
    // ================================================================================================================
598 20
599
    /**
600 20
     * Get all of the updates that belong to this Pulse in reverse chronological order
601
     *
602
     * @api
603
     *
604
     * @since 0.1.0
605
     *
606
     * @return PulseUpdate[]
607
     */
608
    public function getUpdates ()
609
    {
610
        $url = sprintf($this->urlSyntax, self::apiEndpoint(), $this->id, "updates");
611
612
        return self::fetchAndCastToObjectArray($url, "PulseUpdate");
613
    }
614
615
    /**
616
     * Create an update for the current Pulse
617
     *
618
     * @api
619
     *
620
     * @param  int|PulseUser $user
621
     * @param  string        $text
622
     * @param  null|bool     $announceToAll
623
     *
624
     * @since  0.2.2 A PulseUpdate object is returned containing the information of the newly created Update
625
     * @since  0.1.0
626
     *
627
     * @return PulseUpdate
628
     */
629
    public function createUpdate ($user, $text, $announceToAll = NULL)
630
    {
631
        return PulseUpdate::createUpdate($user, $this->getId(), $text, $announceToAll);
632
    }
633
634
    // ================================================================================================================
635
    //   Static functions
636
    // ================================================================================================================
637
638
    /**
639
     * Get all of the pulses that belong to the organization across all boards.
640
     *
641
     * To modify the amount of data returned with pagination, use the following values in the array to configure your
642
     * pagination or offsets.
643
     *
644
     * ```php
645
     * $params = array(
646
     *     "page"     => 1,          // (int) Page offset to fetch
647
     *     "per_page" => 10,         // (int) Number of results per page
648
     *     "offset"   => 5,          // (int) Instead of starting at result 0, start counting from result 5
649
     *     "order_by_latest" => true // (bool) Order the pulses with the most recent first
650
     * );
651
     * ```
652
     *
653
     * @api
654
     *
655
     * @param array $params GET parameters passed to with the query to modify the data returned.
656
     *
657
     * @since 0.1.0
658
     * @return Pulse[]
659
     */
660
    public static function getPulses ($params = array())
661
    {
662
        $url = sprintf("%s.json", self::apiEndpoint());
663
664
        return self::fetchAndCastToObjectArray($url, "Pulse", $params);
665
    }
666
}
667