Completed
Push — develop ( a05ff5...d1fb89 )
by Vladimir
03:27
created

Pulse   B

Complexity

Total Complexity 37

Size/Duplication

Total Lines 622
Duplicated Lines 3.05 %

Coupling/Cohesion

Components 2
Dependencies 8

Test Coverage

Coverage 100%

Importance

Changes 5
Bugs 0 Features 0
Metric Value
wmc 37
c 5
b 0
f 0
lcom 2
cbo 8
dl 19
loc 622
ccs 63
cts 63
cp 1
rs 8.6

25 Methods

Rating   Name   Duplication   Size   Complexity  
A initializeValues() 0 6 1
A getUrl() 0 4 1
A getName() 0 4 1
A getUpdatesCount() 0 4 1
A getBoardId() 0 4 1
A getCreatedAt() 0 6 1
A getUpdatedAt() 0 6 1
A getStatusColumn() 0 4 1
A getDateColumn() 0 4 1
A getNumericColumn() 0 4 1
A getPersonColumn() 0 4 1
A getTextColumn() 0 4 1
A getTimelineColumn() 0 4 1
B getGroupId() 0 19 5
A editName() 0 10 1
A archivePulse() 0 9 1
A deletePulse() 10 10 1
A duplicatePulse() 0 18 2
A pulseInjection() 9 9 1
B getColumn() 0 50 6
A addNote() 0 22 3
A getNotes() 0 6 1
A getUpdates() 0 6 1
A createUpdate() 0 4 1
A getPulses() 0 6 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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 46
    protected function initializeValues ()
124
    {
125 46
        $this->column_values     = array();
126 46
        $this->column_structure  = array();
127 46
        $this->raw_column_values = array();
128 46
    }
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 23
    public function getBoardId ()
170
    {
171 23
        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
    /**
237
     * Edit the name of the pulse
238
     *
239
     * @api
240
     * @param string $title
241
     * @since 0.1.0
242
     */
243
    public function editName($title)
244
    {
245
        $editUrl    = sprintf("%s/%d.json", self::apiEndpoint(), $this->getId());
246
        $postParams = array(
247
            'name' => $title
248
        );
249
250
        $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...
251
        $this->assignResults();
252
    }
253
254
    /**
255
     * Archive the current pulse.
256
     *
257
     * This is the equivalent of a soft delete and can be restored from the DaPulse website.
258
     *
259
     * @api
260
     * @since 0.1.0
261
     */
262
    public function archivePulse()
263
    {
264
        $archiveURL = sprintf("%s/%d.json", self::apiEndpoint(), $this->getId());
265
        $getParams  = array(
266
            'archive' => true
267
        );
268
269
        self::sendDelete($archiveURL, $getParams);
270
    }
271
272
    /**
273
     * Delete the current Pulse
274
     *
275
     * @api
276
     * @throws \allejo\DaPulse\Exceptions\InvalidObjectException
277
     */
278 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...
279
    {
280
        $this->checkInvalid();
281
282
        $deleteURL = sprintf("%s/%d.json", self::apiEndpoint(), $this->getId());
283
284
        self::sendDelete($deleteURL);
285
286
        $this->deletedObject = true;
287
    }
288
289
    public function duplicatePulse ($groupId = NULL, $ownerId = NULL)
290
    {
291
        $url        = sprintf("%s/%s/pulses/%s/duplicate.json", self::apiEndpoint("boards"), $this->getBoardId(), $this->getId());
292
        $postParams = array();
293
294
        if ($ownerId instanceof PulseUser)
295
        {
296
            $ownerId = $ownerId->getId();
297
        }
298
299
        self::setIfNotNullOrEmpty($postParams, "group_id", $groupId);
300
        self::setIfNotNullOrEmpty($postParams, "owner_id", $ownerId);
301
302
        $result = self::sendPost($url, $postParams);
303
        $this->pulseInjection($result);
304
305
        return (new Pulse($result['pulse']));
306
    }
307
308 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...
309
    {
310
        $parentBoard = new PulseBoard($this->getBoardId());
311
312
        // Inject some information so a Pulse object can survive on its own
313
        $result["pulse"]["group_id"]          = $result["board_meta"]["group_id"];
314
        $result["pulse"]["column_structure"]  = $parentBoard->getColumns();
315
        $result["pulse"]["raw_column_values"] = $result["column_values"];
316
    }
317
318
    // ================================================================================================================
319
    //   Column data functions
320
    // ================================================================================================================
321
322
    /**
323
     * Access a color type column value belonging to this pulse in order to read it or modify.
324
     *
325
     * This function should only be used to access color type values; an exception will be thrown otherwise.
326
     *
327
     * @api
328
     *
329
     * @param  string $columnId The ID of the column to access. This is typically a slugified version of the column name
330
     *
331
     * @since  0.1.0
332
     *
333
     * @throws ColumnNotFoundException The specified column ID does not exist for this Pulse
334
     * @throws InvalidColumnException  The specified column is not a "color" type column
335
     * @throws InvalidObjectException  The specified column exists but modification of its value is unsupported either
336
     *                                 by this library or the DaPulse API.
337
     *
338
     * @return PulseColumnStatusValue A column object with access to its contents
339
     */
340 6
    public function getStatusColumn ($columnId)
341
    {
342 6
        return $this->getColumn($columnId, PulseColumn::Status);
343
    }
344
345
    /**
346
     * Access a date type column value belonging to this pulse in order to read it or modify.
347
     *
348
     * This function should only be used to access data type values; an exception will be thrown otherwise.
349
     *
350
     * @api
351
     *
352
     * @param  string $columnId The ID of the column to access. This is typically a slugified version of the column name
353
     *
354
     * @since  0.1.0
355
     *
356
     * @throws ColumnNotFoundException The specified column ID does not exist for this Pulse
357
     * @throws InvalidColumnException  The specified column is not a "date" type column
358
     * @throws InvalidObjectException  The specified column exists but modification of its value is unsupported either
359
     *                                 by this library or the DaPulse API.
360
     *
361
     * @return PulseColumnDateValue A column object with access to its contents
362
     */
363 5
    public function getDateColumn ($columnId)
364
    {
365 5
        return $this->getColumn($columnId, PulseColumn::Date);
366
    }
367
368
    /**
369
     * Access a numeric type column value belonging to this pulse in order to read it or modify.
370
     *
371
     * This function should only be used to access data type values; an exception will be thrown otherwise.
372
     *
373
     * @api
374
     *
375
     * @param  string $columnId The ID of the column to access. This is typically a slugified version of the column name
376
     *
377
     * @since  0.2.0
378
     *
379
     * @throws ColumnNotFoundException The specified column ID does not exist for this Pulse
380
     * @throws InvalidColumnException  The specified column is not a "numeric" type column
381
     * @throws InvalidObjectException  The specified column exists but modification of its value is unsupported either
382
     *                                 by this library or the DaPulse API.
383
     *
384
     * @return PulseColumnNumericValue A column object with access to its contents
385
     */
386 3
    public function getNumericColumn ($columnId)
387
    {
388 3
        return $this->getColumn($columnId, PulseColumn::Numeric);
389
    }
390
391
    /**
392
     * Access a person type column value belonging to this pulse in order to read it or modify.
393
     *
394
     * This function should only be used to access person type values; an exception will be thrown otherwise.
395
     *
396
     * @api
397
     *
398
     * @param  string $columnId The ID of the column to access. This is typically a slugified version of the column name
399
     *
400
     * @since  0.1.0
401
     *
402
     * @throws ColumnNotFoundException The specified column ID does not exist for this Pulse
403
     * @throws InvalidColumnException  The specified column is not a "person" type column
404
     * @throws InvalidObjectException  The specified column exists but modification of its value is unsupported either
405
     *                                 by this library or the DaPulse API.
406
     *
407
     * @return PulseColumnPersonValue A column object with access to its contents
408
     */
409 4
    public function getPersonColumn ($columnId)
410
    {
411 4
        return $this->getColumn($columnId, PulseColumn::Person);
412
    }
413
414
    /**
415
     * Access a text type column value belonging to this pulse in order to read it or modify.
416
     *
417
     * This function should only be used to access text type values; an exception will be thrown otherwise.
418
     *
419
     * @api
420
     *
421
     * @param  string $columnId The ID of the column to access. This is typically a slugified version of the column name
422
     *
423
     * @since  0.1.0
424
425
     * @throws ColumnNotFoundException The specified column ID does not exist for this Pulse
426
     * @throws InvalidColumnException  The specified column is not a "text" type column
427
     * @throws InvalidObjectException  The specified column exists but modification of its value is unsupported either
428
     *                                 by this library or the DaPulse API.
429
     *
430
     * @return PulseColumnTextValue A column object with access to its contents
431
     */
432 2
    public function getTextColumn ($columnId)
433
    {
434 2
        return $this->getColumn($columnId, PulseColumn::Text);
435
    }
436
437
    /**
438
     * Access a timeline type column value belonging to this pulse in order to read it or modify.
439
     *
440
     * This function should only be used to access data type values; an exception will be thrown otherwise.
441
     *
442
     * @api
443
     *
444
     * @param  string $columnId The ID of the column to access. This is typically a slugified version of the column name
445
     *
446
     * @since  0.2.1
447
     *
448
     * @throws ColumnNotFoundException The specified column ID does not exist for this Pulse
449
     * @throws InvalidColumnException  The specified column is not a "numeric" type column
450
     * @throws InvalidObjectException  The specified column exists but modification of its value is unsupported either
451
     *                                 by this library or the DaPulse API.
452
     *
453
     * @return PulseColumnTimelineValue A column object with access to its contents
454
     */
455 3
    public function getTimelineColumn ($columnId)
456
    {
457 3
        return $this->getColumn($columnId, PulseColumn::Timeline);
458
    }
459
460
    /**
461
     * Build a pulse's column object if it doesn't exist or return the existing column.
462
     *
463
     * @param  string $columnId   The ID of the column to access. This is typically a slugified version of the column
464
     *                            title
465
     * @param  string $columnType The type of column being accessed: 'text', 'color', 'person', 'numeric', or 'date'
466
     *
467
     * @since  0.1.0
468
     *
469
     * @throws ColumnNotFoundException The specified column ID does not exist for this Pulse
470
     * @throws InvalidColumnException  The specified column is not the same type as specified in `$columnType`
471
     * @throws InvalidObjectException  The specified column exists but modification of its value is unsupported either
472
     *                                 by this library or the DaPulse API.
473
     *
474
     * @return PulseColumnValue The returned object will be a child of this abstract class.
475
     */
476 23
    private function getColumn ($columnId, $columnType)
477
    {
478 23
        if (!isset($this->column_values) || !array_key_exists($columnId, $this->column_values))
479
        {
480 23
            $key  = ArrayUtilities::array_search_column($this->raw_column_values, 'cid', $columnId);
481 23
            $data = array();
482
483
            // We can't find the key, this means that we got our information from accessing a Pulse directly instead of
484
            // getting it through a PulseBoard. This isn't as robust as accessing a PulseBoard but it's more efficient.
485
            // We make a separate API call to get the value of a column.
486 23
            if ($key === false)
487
            {
488 12
                $url    = sprintf("%s/%d/columns/%s/value.json", self::apiEndpoint("boards"), $this->getBoardId(), $columnId);
489
                $params = array(
490 12
                    "pulse_id" => $this->getId()
491
                );
492
493
                try
494
                {
495 12
                    $results = self::sendGet($url, $params);
496
                }
497 1
                catch (HttpException $e)
498
                {
499 1
                    throw new ColumnNotFoundException("The '$columnId' column could not be found");
500
                }
501
502
                // Store our value inside of jsonResponse so all of the respective objects can treat the data the same
503
                // as when accessed through a PulseBoard
504 11
                $data['jsonResponse']['value'] = $results['value'];
505
            }
506
            else
507
            {
508 11
                $data = $this->raw_column_values[$key];
509 11
                $type = $this->column_structure[$key]->getType();
510
511 11
                if ($type !== $columnType)
512
                {
513 1
                    throw new InvalidColumnException("The '$columnId' column was expected to be '$columnType' but was '$type' instead.");
514
                }
515
            }
516
517 21
            $data['column_id'] = $columnId;
518 21
            $data['board_id']  = $this->getBoardId();
519 21
            $data['pulse_id']  = $this->getId();
520
521 21
            $this->column_values[$columnId] = PulseColumnValue::_createColumnType($columnType, $data);
522
        }
523
524 21
        return $this->column_values[$columnId];
525
    }
526
527
    // ================================================================================================================
528
    //   Notes functions
529
    // ================================================================================================================
530
531
    /**
532
     * Create a new note in this project
533
     *
534
     * @api
535
     *
536
     * @param  string   $title         The title of the note
537
     * @param  string   $content       The body of the note
538
     * @param  bool     $ownersOnly    Set to true if only pulse owners can edit this note.
539
     * @param  int|null $userId        The id of the user to be marked as the note's last updater
540
     * @param  bool     $createUpdate  Indicates whether to create an update on the pulse notifying subscribers on the
541
     *                                 changes (required user_id to be set).
542
     *
543
     * @since  0.1.0
544
     * @return PulseNote
545
     */
546
    public function addNote ($title, $content, $ownersOnly = false, $userId = NULL, $createUpdate = false)
547
    {
548
        $url        = sprintf($this->urlSyntax, self::apiEndpoint(), $this->id, "notes");
549
        $postParams = array(
550
            "id"            => $this->id,
551
            "title"         => $title,
552
            "content"       => $content,
553
            "owners_only"   => $ownersOnly,
554
            "create_update" => $createUpdate
555
        );
556
557
        self::setIfNotNullOrEmpty($postParams, "user_id", $userId);
558
559
        if ($createUpdate && is_null($userId))
560
        {
561
            throw new \InvalidArgumentException("The user_id value must be set if an update is to be created");
562
        }
563
564
        $noteResult = self::sendPost($url, $postParams);
565
566
        return (new PulseNote($noteResult));
567
    }
568
569
    /**
570
     * Return all of the notes belonging to this project
571
     *
572
     * @api
573
     * @since  0.1.0
574
     * @return PulseNote[]
575
     */
576
    public function getNotes ()
577
    {
578
        $url = sprintf($this->urlSyntax, self::apiEndpoint(), $this->id, "notes");
579
580
        return self::fetchAndCastToObjectArray($url, "PulseNote");
581
    }
582
583
    // ================================================================================================================
584
    //   Updates functions
585
    // ================================================================================================================
586
587
    /**
588
     * Get all of the updates that belong to this Pulse in reverse chronological order
589
     *
590
     * @api
591
     *
592
     * @since 0.1.0
593
     *
594
     * @return PulseUpdate[]
595
     */
596 13
    public function getUpdates ()
597
    {
598 13
        $url = sprintf($this->urlSyntax, self::apiEndpoint(), $this->id, "updates");
599
600 13
        return self::fetchAndCastToObjectArray($url, "PulseUpdate");
601
    }
602
603
    /**
604
     * Create an update for the current Pulse
605
     *
606
     * @api
607
     *
608
     * @param  int|PulseUser $user
609
     * @param  string        $text
610
     * @param  null|bool     $announceToAll
611
     *
612
     * @since  0.2.2 A PulseUpdate object is returned containing the information of the newly created Update
613
     * @since  0.1.0
614
     *
615
     * @return PulseUpdate
616
     */
617
    public function createUpdate ($user, $text, $announceToAll = NULL)
618
    {
619
        return PulseUpdate::createUpdate($user, $this->getId(), $text, $announceToAll);
620
    }
621
622
    // ================================================================================================================
623
    //   Static functions
624
    // ================================================================================================================
625
626
    /**
627
     * Get all of the pulses that belong to the organization across all boards.
628
     *
629
     * To modify the amount of data returned with pagination, use the following values in the array to configure your
630
     * pagination or offsets.
631
     *
632
     * ```php
633
     * $params = array(
634
     *     "page"     => 1,          // (int) Page offset to fetch
635
     *     "per_page" => 10,         // (int) Number of results per page
636
     *     "offset"   => 5,          // (int) Instead of starting at result 0, start counting from result 5
637
     *     "order_by_latest" => true // (bool) Order the pulses with the most recent first
638
     * );
639
     * ```
640
     *
641
     * @api
642
     *
643
     * @param array $params GET parameters passed to with the query to modify the data returned.
644
     *
645
     * @since 0.1.0
646
     * @return Pulse[]
647
     */
648
    public static function getPulses ($params = array())
649
    {
650
        $url = sprintf("%s.json", self::apiEndpoint());
651
652
        return self::fetchAndCastToObjectArray($url, "Pulse", $params);
653
    }
654
}
655