Completed
Push — develop ( a27f27...afc6a9 )
by Vladimir
04:06
created

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