This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | /** smtech\CanvasPest\CanvasPest */ |
||
4 | |||
5 | namespace smtech\CanvasPest; |
||
6 | |||
7 | /** |
||
8 | * An object to handle interactions with the Canvas API. |
||
9 | * |
||
10 | * For more information on the Canvas API refer to the offical |
||
11 | * {@link https://canvas.instructure.com/doc/api/ Canvas API documentation} or |
||
12 | * to the (slightly more up-to-date and pleasingly interactive) |
||
13 | * {@link https://canvas.instructure.com/doc/api/live live documentation}. |
||
14 | * |
||
15 | * You can access the live documentation for your own Canvas instance and make |
||
16 | * actual API calls to it at `https://<path-to-your-instance>/doc/api/live` |
||
17 | * |
||
18 | * @author Seth Battis <[email protected]> |
||
19 | **/ |
||
20 | class CanvasPest extends \Battis\Educoder\Pest |
||
21 | { |
||
22 | |||
23 | /** Name of the parameter controlling the number of responses per page */ |
||
24 | const PARAM_PER_PAGE = 'per_page'; |
||
25 | |||
26 | /** @var string[] $headers Additional headers to be passed to the API with each call */ |
||
27 | protected $headers; |
||
28 | |||
29 | /** |
||
30 | * Construct a new CanvasPest |
||
31 | * |
||
32 | * @api |
||
33 | * |
||
34 | * @param string $apiInstanceUrl URL of the API instance (e.g. |
||
35 | * `'https://canvas.instructure.com/api/v1'`) |
||
36 | * @param string $apiAuthorizationToken (Optional) API access token for the |
||
37 | * API instance (if not provided now, it will need to be provided later) |
||
38 | * |
||
39 | * @see CanvasPest::setupToken() To configure the API access token later |
||
40 | **/ |
||
41 | 14 | public function __construct($apiInstanceUrl, $apiAuthorizationToken = null) |
|
42 | { |
||
43 | 14 | parent::__construct($apiInstanceUrl); |
|
44 | 14 | if (!empty($apiAuthorizationToken)) { |
|
45 | 12 | $this->setupToken($apiAuthorizationToken); |
|
46 | 12 | } |
|
47 | 14 | } |
|
48 | |||
49 | /** |
||
50 | * Set up a new API access token to access this instance |
||
51 | * |
||
52 | * @param string $token API access token |
||
53 | * |
||
54 | * @return boolean |
||
55 | * |
||
56 | * @throws CanvasPest_Exception INVALID_TOKEN on an empty or non-string token value |
||
57 | **/ |
||
58 | 14 | public function setupToken($token) |
|
59 | { |
||
60 | 14 | if (!empty($token)) { |
|
61 | 12 | $this->headers['Authorization'] = "Bearer $token"; |
|
62 | 12 | return true; |
|
63 | } else { |
||
64 | 2 | if ($this->throw_exceptions) { |
|
65 | 1 | throw new CanvasPest_Exception( |
|
66 | 1 | 'API authorization token must be a non-zero-length string', |
|
67 | CanvasPest_Exception::INVALID_TOKEN |
||
68 | 1 | ); |
|
69 | } |
||
70 | 2 | return false; |
|
71 | } |
||
72 | } |
||
73 | |||
74 | /** |
||
75 | * Preprocess API call parameters before use |
||
76 | * |
||
77 | * Force maximum response page size, if not already defined. |
||
78 | * |
||
79 | * @param string[] $data Array of parameters for the next API call |
||
80 | * |
||
81 | * @return string[] Updated array of parameters |
||
82 | * |
||
83 | * @see CanvasArray::MAXIMUM_PER_PAGE Maximum number of responses per page |
||
84 | * @see CanvasPest::PARAM_PER_PAGE Page size parameter |
||
85 | **/ |
||
86 | 18 | private function preprocessData($data) |
|
87 | { |
||
88 | 18 | if (is_array($data) && !array_key_exists(self::PARAM_PER_PAGE, $data)) { |
|
89 | 13 | $data[self::PARAM_PER_PAGE] = CanvasArray::MAXIMUM_PER_PAGE; |
|
90 | 13 | } |
|
91 | 18 | return $data; |
|
92 | } |
||
93 | |||
94 | /** |
||
95 | * Prepare API request headers |
||
96 | * |
||
97 | * Flatten headers from an associative array to a numerically indexed array |
||
98 | * of `"Name: Value"` style entries like `CURLOPT_HTTPHEADER` expects. |
||
99 | * Numerically indexed arrays are not modified. |
||
100 | * |
||
101 | * Extended by CanvasPest to include the API access token in the |
||
102 | * `Authorization` header. |
||
103 | * |
||
104 | * @param string[] $headers |
||
105 | * @return string[] |
||
106 | **/ |
||
107 | 20 | protected function prepHeaders($headers) |
|
108 | { |
||
109 | 20 | return parent::prepHeaders(array_merge($this->headers, $headers)); |
|
110 | } |
||
111 | |||
112 | /** |
||
113 | * Parse the API response into an object (or collection of objects). |
||
114 | * |
||
115 | * For queries to individually identified endpoints (e.g. |
||
116 | * `accounts/1/users/123`), return a CanvasObject representing the API response |
||
117 | * describing _that_ individually identified object affected by the query. |
||
118 | * |
||
119 | * For queries to generic endpoints (e.g. `accounts/1/users`), return a |
||
120 | * traversable CanvasArray (of CanvasObjects) representing the API response |
||
121 | * describing the list of objects affected by the query. |
||
122 | * |
||
123 | * @param string $response JSON-encoded response from the API |
||
124 | * |
||
125 | * @return CanvasObject|CanvasArray|false |
||
126 | * |
||
127 | * @throws CanvasPest_Exception INVALID_JSON_RESPONSE if an |
||
128 | * non-JSON-formatted response is received (and |
||
129 | * $this->throw_exceptions is true -- otherwise it returns false) |
||
130 | **/ |
||
131 | 20 | protected function postprocessResponse($response) |
|
132 | { |
||
133 | 20 | if (substr($response, 0, 1) == '{') { |
|
134 | 11 | return new CanvasObject($response); |
|
135 | 9 | } elseif (substr($response, 0, 1) == '[') { |
|
136 | 7 | return new CanvasArray($response, $this); |
|
137 | } else { |
||
138 | 2 | if ($this->throw_exceptions) { |
|
139 | 1 | throw new CanvasPest_Exception( |
|
140 | 1 | $response, |
|
141 | CanvasPest_Exception::INVALID_JSON_RESPONSE |
||
142 | 1 | ); |
|
143 | } |
||
144 | 1 | return false; |
|
145 | } |
||
146 | } |
||
147 | |||
148 | /** |
||
149 | * Reformat query parameters for Canvas |
||
150 | * |
||
151 | * Specifically, Canvas expects no numeric indices for base array parameters. |
||
152 | * |
||
153 | * @param mixed $data |
||
154 | * |
||
155 | * @return string |
||
156 | * @codingStandardsIgnoreStart |
||
157 | **/ |
||
158 | 20 | protected function http_build_query($data) |
|
159 | { |
||
160 | // @codingStandardsIgnoreEnd |
||
161 | 20 | return preg_replace('/%5B\d+%5D/simU', '[]', http_build_query($data)); |
|
162 | } |
||
163 | |||
164 | /** |
||
165 | * Make a GET call to the API |
||
166 | * |
||
167 | * For queries to individually identified endpoints (e.g. |
||
168 | * `accounts/1/users/123`), return a CanvasObject representing the API response |
||
169 | * describing _that_ individually identified object affected by the query. |
||
170 | * |
||
171 | * For queries to generic endpoints (e.g. `accounts/1/users`), return a |
||
172 | * traversable CanvasArray (of CanvasObjects) representing the API response |
||
173 | * describing the list of objects affected by the query. |
||
174 | * |
||
175 | * @api |
||
176 | * |
||
177 | * @param string $path Path to the API endpoint of this call |
||
178 | * @param string|string[] $data (Optional) Query parameters for this call |
||
179 | * @param string|string[] $headers (Optional) Any additional HTTP headers for this call |
||
180 | * |
||
181 | * @return CanvasObject|CanvasArray|false |
||
182 | **/ |
||
183 | 12 | public function get($path, $data = array(), $headers = array()) |
|
184 | { |
||
185 | 12 | return $this->postprocessResponse( |
|
0 ignored issues
–
show
|
|||
186 | 12 | parent::get($path, $this->preprocessData($data), $headers) |
|
0 ignored issues
–
show
It seems like
$data defined by parameter $data on line 183 can also be of type string ; however, smtech\CanvasPest\CanvasPest::preprocessData() does only seem to accept array<integer,string> , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble. ![]() It seems like
$headers defined by parameter $headers on line 183 can also be of type string ; however, Battis\Educoder\Pest::get() does only seem to accept array , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble. ![]() |
|||
187 | 12 | ); |
|
188 | } |
||
189 | |||
190 | /** |
||
191 | * Make a POST call to the API |
||
192 | * |
||
193 | * For queries to individually identified endpoints (e.g. |
||
194 | * `accounts/1/users/123`), return a CanvasObject representing the API response |
||
195 | * describing _that_ individually identified object affected by the query. |
||
196 | * |
||
197 | * @api |
||
198 | * |
||
199 | * @param string $path Path to the API endpoint of this call |
||
200 | * @param string|string[] $data (Optional) Query parameters for this call |
||
201 | * @param string|string[] $headers (Optional) Any additional HTTP headers for this call |
||
202 | * |
||
203 | * @return CanvasObject|false |
||
204 | **/ |
||
205 | 4 | public function post($path, $data = array(), $headers = array()) |
|
206 | { |
||
207 | 4 | return $this->postprocessResponse( |
|
0 ignored issues
–
show
The return type of
return $this->postproces...ata($data), $headers)); (smtech\CanvasPest\Canvas...sPest\CanvasArray|false ) is incompatible with the return type of the parent method Battis\Educoder\Pest::post of type string .
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 ![]() |
|||
208 | 4 | parent::post($path, $this->preprocessData($data), $headers) |
|
0 ignored issues
–
show
It seems like
$data defined by parameter $data on line 205 can also be of type string ; however, smtech\CanvasPest\CanvasPest::preprocessData() does only seem to accept array<integer,string> , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble. ![]() It seems like
$headers defined by parameter $headers on line 205 can also be of type string ; however, Battis\Educoder\Pest::post() does only seem to accept array , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble. ![]() |
|||
209 | 4 | ); |
|
210 | } |
||
211 | |||
212 | /** |
||
213 | * Make a PUT call to the API |
||
214 | * |
||
215 | * For queries to individually identified endpoints (e.g. |
||
216 | * `accounts/1/users/123`), return a CanvasObject representing the API response |
||
217 | * describing _that_ individually identified object affected by the query. |
||
218 | * |
||
219 | * @api |
||
220 | * |
||
221 | * @param string $path Path to the API endpoint of this call |
||
222 | * @param string|string[] $data (Optional) Query parameters for this call |
||
223 | * @param string|string[] $headers (Optional) Any additional HTTP headers for this call |
||
224 | * |
||
225 | * @return CanvasObject|false |
||
226 | **/ |
||
227 | 2 | public function put($path, $data = array(), $headers = array()) |
|
228 | { |
||
229 | 2 | return $this->postprocessResponse( |
|
0 ignored issues
–
show
The return type of
return $this->postproces...ata($data), $headers)); (smtech\CanvasPest\Canvas...sPest\CanvasArray|false ) is incompatible with the return type of the parent method Battis\Educoder\Pest::put of type string .
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 ![]() |
|||
230 | 2 | parent::put($path, $this->preprocessData($data), $headers) |
|
0 ignored issues
–
show
It seems like
$data defined by parameter $data on line 227 can also be of type string ; however, smtech\CanvasPest\CanvasPest::preprocessData() does only seem to accept array<integer,string> , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble. ![]() It seems like
$headers defined by parameter $headers on line 227 can also be of type string ; however, Battis\Educoder\Pest::put() does only seem to accept array , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble. ![]() |
|||
231 | 2 | ); |
|
232 | } |
||
233 | |||
234 | /** |
||
235 | * Make a DELETE call to the API |
||
236 | * |
||
237 | * For queries to individually identified endpoints (e.g. |
||
238 | * `accounts/1/users/123`), return a CanvasObject representing the API |
||
239 | * response describing _that_ individually identified object affected by |
||
240 | * the query. |
||
241 | * |
||
242 | * @api |
||
243 | * |
||
244 | * @param string $path Path to the API endpoint of this call |
||
245 | * @param string|string[] $data (Optional) Query parameters for this call |
||
246 | * @param string|string[] $headers (Optional) Any additional HTTP headers for this call |
||
247 | * |
||
248 | * @return CanvasObject|false |
||
249 | **/ |
||
250 | 4 | public function delete($path, $data = array(), $headers = array()) |
|
251 | { |
||
252 | 4 | if (!empty($data)) { |
|
253 | 4 | $pathData = []; |
|
254 | 4 | $pos = strpos($path, '?'); |
|
255 | 4 | if ($pos !== false) { |
|
256 | 2 | parse_str(substr($path, $pos + 1), $pathData); |
|
257 | 2 | $path = substr($path, 0, $pos); |
|
258 | 2 | } |
|
259 | 4 | $path .= '?' . $this->http_build_query(array_merge($pathData, $data)); |
|
260 | 4 | } |
|
261 | 4 | return $this->postprocessResponse( |
|
0 ignored issues
–
show
The return type of
return $this->postproces...lete($path, $headers)); (smtech\CanvasPest\Canvas...sPest\CanvasArray|false ) is incompatible with the return type of the parent method Battis\Educoder\Pest::delete of type string .
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 ![]() |
|||
262 | 4 | parent::delete($path, $headers) |
|
0 ignored issues
–
show
It seems like
$headers defined by parameter $headers on line 250 can also be of type string ; however, Battis\Educoder\Pest::delete() does only seem to accept array , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble. ![]() |
|||
263 | 4 | ); |
|
264 | } |
||
265 | |||
266 | /** |
||
267 | * Make a PATCH call to the API |
||
268 | * |
||
269 | * @deprecated The Canvas API does not currently support PATCH calls |
||
270 | * |
||
271 | * @param string $path Path to the API endpoint of this call |
||
272 | * @param string|string[] $data (Optional) Query parameters for this call |
||
273 | * @param string|string[] $headers (Optional) Any additional HTTP headers for this call |
||
274 | * |
||
275 | * @return false |
||
276 | * |
||
277 | * @throws CanvasPest_Exception UNSUPPORTED_METHOD All calls to this method will cause an exception |
||
278 | **/ |
||
279 | 2 | public function patch($path, $data = array(), $headers = array()) |
|
280 | { |
||
281 | 2 | if ($this->throw_exceptions) { |
|
282 | 1 | throw new CanvasPest_Exception( |
|
283 | 1 | 'The Canvas API does not support the PATCH method', |
|
284 | CanvasPest_Exception::UNSUPPORTED_METHOD |
||
285 | 1 | ); |
|
286 | } |
||
287 | 1 | return false; |
|
0 ignored issues
–
show
The return type of
return false; (false ) is incompatible with the return type of the parent method Battis\Educoder\Pest::patch of type string .
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 ![]() |
|||
288 | } |
||
289 | } |
||
290 |
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:
Our function
my_function
expects aPost
object, and outputs the author of the post. The base classPost
returns a simple string and outputting a simple string will work just fine. However, the child classBlogPost
which is a sub-type ofPost
instead decided to return anobject
, and is therefore violating the SOLID principles. If aBlogPost
were passed tomy_function
, PHP would not complain, but ultimately fail when executing thestrtoupper
call in its body.