Completed
Push — master ( 87209a...672fdc )
by Sergey
01:08
created

Response::getResponseData()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 8
rs 9.4285
cc 2
eloc 4
nc 2
nop 1
1
<?php
2
3
namespace seregazhuk\PinterestBot\Api;
4
5
use seregazhuk\PinterestBot\Api\Contracts\PaginatedResponse;
6
7
class Response implements PaginatedResponse
8
{
9
    /**
10
     * @var mixed
11
     */
12
    protected $data;
13
14
    /**
15
     * @var array|null
16
     */
17
    protected $lastError;
18
19
    public function __construct($data)
20
    {
21
        $this->data = $data;
22
23
        $this->lastError = $this->getValueByKey('resource_response.error', $this->data);
24
    }
25
26
    /**
27
     * Check if specified data exists in response.
28
     *
29
     * @param null  $key
30
     *
31
     * @return array|bool
32
     */
33
    public function getResponseData($key = null)
34
    {
35
        if ($this->hasErrors()) {
36
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type declared by the interface seregazhuk\PinterestBot\...sponse::getResponseData of type array.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
37
        }
38
39
        return $this->parseResponseData($key);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->parseResponseData($key); of type boolean|array adds the type boolean to the return on line 39 which is incompatible with the return type declared by the interface seregazhuk\PinterestBot\...sponse::getResponseData of type array.
Loading history...
40
    }
41
42
    /**
43
     * @param string $key
44
     * @param null $default
45
     * @return mixed
46
     */
47
    public function getData($key = '', $default = null)
48
    {
49
        return $this->getValueByKey($key, $this->data, $default);
50
    }
51
52
    /**
53
     * Parse data from Pinterest Api response.
54
     * Data is stored in ['resource_response']['data'] array.
55
     *
56
     * @param string $key
57
     *
58
     * @return bool|array
59
     */
60
    protected function parseResponseData($key)
61
    {
62
        $responseData = $this->getValueByKey('resource_response.data', $this->data);
63
        if(!$responseData) return false;
64
65
        return $key ?
66
            $this->getValueByKey($key, $responseData) :
67
            $responseData;
68
    }
69
70
    /**
71
     * @param string $key
72
     * @param array $data
73
     * @param bool $default
74
     * @return array|bool|mixed
75
     */
76
    protected function getValueByKey($key = '', array $data, $default = null)
77
    {
78
        if(empty($key)) return $data;
79
80
        $indexes = explode('.', $key);
81
        $value = $data;
82
83
        foreach ($indexes as $index) {
84
            if(!isset($value[$index])) return $default;
85
86
            $value = $value[$index];
87
        }
88
89
        return $value;
90
    }
91
92
    /**
93
     * Checks if response is empty.
94
     *
95
     * @return bool
96
     */
97
    public function isEmpty()
98
    {
99
        return empty($this->getResponseData());
100
    }
101
102
    /**
103
     * @return bool
104
     */
105
    public function isOk()
106
    {
107
        return !$this->hasErrors();
108
    }
109
110
    /**
111
     * @return bool
112
     */
113
    public function hasResponseData()
114
    {
115
        return (bool)$this->getValueByKey('resource_response.data', $this->data);
116
    }
117
118
    /**
119
     * Remove 'module' data from response.
120
     *
121
     * @return array mixed
122
     */
123
    public function clearResponseFromMetaData()
124
    {
125
        if (isset($this->data['data'][0]['type']) && $this->data['data'][0]['type'] == 'module') {
126
            array_shift($this->data['data']);
127
        }
128
129
        return $this->data;
130
    }
131
132
    /**
133
     * Check for error info in api response and save
134
     * it.
135
     *
136
     * @return bool
137
     */
138
    public function hasErrors()
139
    {
140
        return !is_null($this->lastError);
141
    }
142
143
    /**
144
     * Parse bookmarks from response.
145
     *
146
     * @return array
147
     */
148
    public function getBookmarks()
149
    {
150
        $bookmarks = $this->getValueByKey('resource.options.bookmarks', $this->data,  []);
0 ignored issues
show
Documentation introduced by
array() is of type array, but the function expects a boolean|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
151
        return empty($bookmarks) ? [] : [$bookmarks[0]];
152
    }
153
154
    /**
155
     * Checks Pinterest API paginated response, and parses data
156
     * with bookmarks info from it.
157
     *
158
     * @return array
159
     */
160
    public function getPaginationData()
161
    {
162
        if ($this->isEmpty() && $this->hasErrors()) {
163
            return [];
164
        }
165
166
        $bookmarks = $this->getBookmarks();
167
        if ($data = $this->getResponseData()) {
168
            return ['data' => $data, 'bookmarks' => $bookmarks];
169
        }
170
171
        return [];
172
    }
173
174
    /**
175
     * @return array
176
     */
177
    public function getLastError()
178
    {
179
        return $this->lastError;
180
    }
181
182
    /**
183
     * @return mixed
184
     */
185
    public function __toString()
186
    {
187
        return $this->data;
188
    }
189
190
}
191