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 namespace JobApis\Jobs\Client; |
||
2 | |||
3 | use JobApis\Jobs\Client\Providers\AbstractProvider; |
||
4 | use JobApis\Jobs\Client\Queries\AbstractQuery; |
||
5 | |||
6 | class JobsMulti |
||
7 | { |
||
8 | /** |
||
9 | * Search keyword |
||
10 | * |
||
11 | * @var string |
||
12 | */ |
||
13 | protected $keyword; |
||
14 | |||
15 | /** |
||
16 | * Search location |
||
17 | * |
||
18 | * @var string |
||
19 | */ |
||
20 | protected $location; |
||
21 | |||
22 | /** |
||
23 | * Maximum age of results (in days) |
||
24 | * |
||
25 | * @var integer |
||
26 | */ |
||
27 | protected $maxAge; |
||
28 | |||
29 | /** |
||
30 | * Maximum number of results to return in all results |
||
31 | * |
||
32 | * @var integer |
||
33 | */ |
||
34 | protected $maxResults; |
||
35 | |||
36 | /** |
||
37 | * Order of results |
||
38 | * |
||
39 | * @var string |
||
40 | */ |
||
41 | protected $order; |
||
42 | |||
43 | /** |
||
44 | * Field to order results by |
||
45 | * |
||
46 | * @var string |
||
47 | */ |
||
48 | protected $orderBy; |
||
49 | |||
50 | /** |
||
51 | * Results page number |
||
52 | * |
||
53 | * @var integer |
||
54 | */ |
||
55 | protected $pageNumber; |
||
56 | |||
57 | /** |
||
58 | * Results per page |
||
59 | * |
||
60 | * @var integer |
||
61 | */ |
||
62 | protected $perPage; |
||
63 | |||
64 | /** |
||
65 | * Job board API providers |
||
66 | * |
||
67 | * @var array |
||
68 | */ |
||
69 | protected $providers = []; |
||
70 | |||
71 | /** |
||
72 | * Job board API query objects |
||
73 | * |
||
74 | * @var array |
||
75 | */ |
||
76 | protected $queries = []; |
||
77 | |||
78 | /** |
||
79 | * Creates query objects for each provider and creates this unified client. |
||
80 | * |
||
81 | * @param array $providers |
||
82 | */ |
||
83 | 20 | public function __construct($providers = []) |
|
84 | { |
||
85 | 20 | $this->setProviders($providers); |
|
86 | 20 | } |
|
87 | |||
88 | /** |
||
89 | * Gets jobs from all providers in a single go and returns a MultiCollection |
||
90 | * |
||
91 | * @return Collection |
||
92 | */ |
||
93 | 2 | public function getAllJobs($options = []) |
|
94 | { |
||
95 | // Set options that are passed in |
||
96 | 2 | $this->setOptions($options); |
|
97 | |||
98 | // Create a new Collection |
||
99 | 2 | $collection = new Collection(); |
|
100 | 2 | foreach ($this->providers as $providerName => $options) { |
|
101 | 2 | $collection->addCollection($this->getJobsByProvider($providerName)); |
|
102 | 2 | } |
|
103 | |||
104 | // Apply sorting and ordering options and return the collection |
||
105 | 2 | return $this->applyOptions($collection); |
|
106 | } |
||
107 | |||
108 | /** |
||
109 | * Gets jobs from a single provider and hydrates a new jobs collection. |
||
110 | * |
||
111 | * @var $name string Provider name. |
||
112 | * |
||
113 | * @return \JobApis\Jobs\Client\Collection |
||
114 | */ |
||
115 | 8 | public function getJobsByProvider($name = null, $options = []) |
|
116 | { |
||
117 | // Set options that are passed in |
||
118 | 8 | $this->setOptions($options); |
|
119 | |||
120 | try { |
||
121 | // Instantiate the query with all our parameters |
||
122 | 8 | $query = $this->instantiateQuery($name); |
|
123 | |||
124 | // Instantiate the provider |
||
125 | 5 | $provider = $this->instantiateProvider($name, $query); |
|
126 | |||
127 | // Apply sorting and ordering options and return the collection |
||
128 | 5 | return $this->applyOptions($provider->getJobs()); |
|
129 | 5 | } catch (\Exception $e) { |
|
130 | 5 | return (new Collection())->addError($e->getMessage()); |
|
131 | } |
||
132 | } |
||
133 | |||
134 | /** |
||
135 | * Sets a keyword on the query. |
||
136 | * |
||
137 | * @param $keyword string |
||
138 | * |
||
139 | * @return $this |
||
140 | */ |
||
141 | 8 | public function setKeyword($keyword = null) |
|
142 | { |
||
143 | 8 | $this->keyword = $keyword; |
|
144 | |||
145 | 8 | return $this; |
|
146 | } |
||
147 | |||
148 | /** |
||
149 | * Sets a location on the query for each provider. |
||
150 | * |
||
151 | * @param $location |
||
152 | * |
||
153 | * @return $this |
||
154 | */ |
||
155 | 8 | public function setLocation($location = null) |
|
156 | { |
||
157 | 8 | if (!$this->isValidLocation($location)) { |
|
158 | 2 | throw new \OutOfBoundsException("Location parameter must follow the pattern 'City, ST'."); |
|
159 | } |
||
160 | 6 | $this->location = $location; |
|
161 | |||
162 | 6 | return $this; |
|
163 | } |
||
164 | |||
165 | /** |
||
166 | * Sets the options used for the resulting collection |
||
167 | * |
||
168 | * @param array $options |
||
169 | * |
||
170 | * @return $this |
||
171 | */ |
||
172 | 10 | public function setOptions($options = []) |
|
173 | { |
||
174 | 10 | if (isset($options['maxAge'])) { |
|
175 | 4 | $this->maxAge = $options['maxAge']; |
|
176 | 4 | } |
|
177 | 10 | if (isset($options['maxResults'])) { |
|
178 | 4 | $this->maxResults = $options['maxResults']; |
|
179 | 4 | } |
|
180 | 10 | if (isset($options['order'])) { |
|
181 | 4 | $this->order = $options['order']; |
|
182 | 4 | } |
|
183 | 10 | if (isset($options['orderBy'])) { |
|
184 | 4 | $this->orderBy = $options['orderBy']; |
|
185 | 4 | } |
|
186 | |||
187 | 10 | return $this; |
|
188 | } |
||
189 | |||
190 | /** |
||
191 | * Sets a page number and number of results per page for each provider. |
||
192 | * |
||
193 | * @param $pageNumber integer |
||
194 | * @param $perPage integer |
||
195 | * |
||
196 | * @return $this |
||
197 | */ |
||
198 | 6 | public function setPage($pageNumber = 1, $perPage = 10) |
|
199 | { |
||
200 | 6 | $this->pageNumber = $pageNumber; |
|
201 | 6 | $this->perPage = $perPage; |
|
202 | |||
203 | 6 | return $this; |
|
204 | } |
||
205 | |||
206 | /** |
||
207 | * Sets an array of providers. |
||
208 | * |
||
209 | * @param $providers array |
||
210 | * |
||
211 | * @return $this |
||
212 | */ |
||
213 | 20 | public function setProviders($providers = []) |
|
214 | { |
||
215 | 20 | $this->providers = $providers; |
|
216 | |||
217 | 20 | return $this; |
|
218 | } |
||
219 | |||
220 | /** |
||
221 | * Apply the options for this JobsMulti object to the Collection |
||
222 | * |
||
223 | * @param Collection $collection |
||
224 | * |
||
225 | * @return Collection |
||
226 | */ |
||
227 | 5 | protected function applyOptions(Collection $collection) |
|
228 | { |
||
229 | // Order the results |
||
230 | 5 | if ($this->orderBy && $this->order) { |
|
231 | 2 | $collection->orderBy($this->orderBy, $this->order); |
|
232 | 2 | } |
|
233 | |||
234 | // Filter older listings out |
||
235 | 5 | if ($this->maxAge) { |
|
236 | 2 | $collection->filter( |
|
237 | 2 | 'datePosted', |
|
238 | 2 | new \DateTime($this->maxAge.' days ago'), |
|
0 ignored issues
–
show
|
|||
239 | '>' |
||
240 | 2 | ); |
|
241 | 2 | } |
|
242 | |||
243 | // Truncate to the maximum results (all by default) |
||
244 | 5 | if ($this->maxResults) { |
|
245 | 2 | $collection->truncate($this->maxResults); |
|
246 | 2 | } |
|
247 | |||
248 | 5 | return $collection; |
|
249 | } |
||
250 | |||
251 | /** |
||
252 | * Gets an array of options from a translator array |
||
253 | * |
||
254 | * @param array $translator |
||
255 | * |
||
256 | * @return array |
||
257 | */ |
||
258 | 6 | protected function getOptionsFromTranslator($translator = []) |
|
259 | { |
||
260 | 6 | $options = []; |
|
261 | 6 | foreach ($translator as $standardKey => $providerKey) { |
|
262 | 6 | if (method_exists($this, $providerKey)) { |
|
263 | 6 | $options = array_merge( |
|
264 | 6 | $options, |
|
265 | 6 | $this->$providerKey($this->{$standardKey}) |
|
266 | 6 | ); |
|
267 | 6 | } else { |
|
268 | 6 | $options[$providerKey] = $this->{$standardKey}; |
|
269 | } |
||
270 | 6 | } |
|
271 | 6 | return $options; |
|
272 | } |
||
273 | |||
274 | /** |
||
275 | * Gets the options array based on the provider name. |
||
276 | * |
||
277 | * @param $name |
||
278 | * |
||
279 | * @return array |
||
280 | */ |
||
281 | 6 | protected function getTranslatorForProvider($name) |
|
282 | { |
||
283 | switch ($name) { |
||
284 | 6 | case 'Careerbuilder': |
|
285 | return [ |
||
286 | 'keyword' => 'Keywords', |
||
287 | 'location' => 'Location', |
||
288 | 'pageNumber' => 'PageNumber', |
||
289 | 'perPage' => 'PerPage', |
||
290 | ]; |
||
291 | break; |
||
0 ignored issues
–
show
break is not strictly necessary here and could be removed.
The break statement is not necessary if it is preceded for example by a return statement: switch ($x) {
case 1:
return 'foo';
break; // This break is not necessary and can be left off.
}
If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive. ![]() |
|||
292 | 6 | case 'Careercast': |
|
293 | return [ |
||
294 | 'keyword' => 'keyword', |
||
295 | 'location' => 'location', |
||
296 | 'pageNumber' => 'page', |
||
297 | 'perPage' => 'rows', |
||
298 | ]; |
||
299 | break; |
||
0 ignored issues
–
show
break is not strictly necessary here and could be removed.
The break statement is not necessary if it is preceded for example by a return statement: switch ($x) {
case 1:
return 'foo';
break; // This break is not necessary and can be left off.
}
If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive. ![]() |
|||
300 | 6 | case 'Careerjet': |
|
301 | return [ |
||
302 | 'keyword' => 'keywords', |
||
303 | 'location' => 'location', |
||
304 | 'pageNumber' => 'page', |
||
305 | 'perPage' => 'pagesize', |
||
306 | ]; |
||
307 | break; |
||
0 ignored issues
–
show
break is not strictly necessary here and could be removed.
The break statement is not necessary if it is preceded for example by a return statement: switch ($x) {
case 1:
return 'foo';
break; // This break is not necessary and can be left off.
}
If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive. ![]() |
|||
308 | 6 | case 'Dice': |
|
309 | return [ |
||
310 | 2 | 'keyword' => 'text', |
|
311 | 2 | 'location' => 'getCityAndState', |
|
312 | 2 | 'pageNumber' => 'page', |
|
313 | 2 | 'perPage' => 'pgcnt', |
|
314 | 2 | ]; |
|
315 | break; |
||
0 ignored issues
–
show
break is not strictly necessary here and could be removed.
The break statement is not necessary if it is preceded for example by a return statement: switch ($x) {
case 1:
return 'foo';
break; // This break is not necessary and can be left off.
}
If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive. ![]() |
|||
316 | 6 | case 'Github': |
|
317 | return [ |
||
318 | 4 | 'keyword' => 'search', |
|
319 | 4 | 'location' => 'location', |
|
320 | 4 | 'pageNumber' => 'getPageMinusOne', |
|
321 | 4 | ]; |
|
322 | break; |
||
0 ignored issues
–
show
break is not strictly necessary here and could be removed.
The break statement is not necessary if it is preceded for example by a return statement: switch ($x) {
case 1:
return 'foo';
break; // This break is not necessary and can be left off.
}
If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive. ![]() |
|||
323 | 4 | case 'Govt': |
|
324 | return [ |
||
325 | 3 | 'keyword' => 'getQueryWithKeywordAndLocation', |
|
326 | 3 | 'pageNumber' => 'getFrom', |
|
327 | 3 | 'perPage' => 'size', |
|
328 | 3 | ]; |
|
329 | break; |
||
0 ignored issues
–
show
break is not strictly necessary here and could be removed.
The break statement is not necessary if it is preceded for example by a return statement: switch ($x) {
case 1:
return 'foo';
break; // This break is not necessary and can be left off.
}
If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive. ![]() |
|||
330 | 3 | case 'Ieee': |
|
331 | return [ |
||
332 | 2 | 'keyword' => 'keyword', |
|
333 | 2 | 'location' => 'location', |
|
334 | 2 | 'pageNumber' => 'page', |
|
335 | 2 | 'perPage' => 'rows', |
|
336 | 2 | ]; |
|
337 | break; |
||
0 ignored issues
–
show
break is not strictly necessary here and could be removed.
The break statement is not necessary if it is preceded for example by a return statement: switch ($x) {
case 1:
return 'foo';
break; // This break is not necessary and can be left off.
}
If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive. ![]() |
|||
338 | 3 | case 'Indeed': |
|
339 | return [ |
||
340 | 'keyword' => 'q', |
||
341 | 'location' => 'l', |
||
342 | 'pageNumber' => 'getStart', |
||
343 | 'perPage' => 'limit', |
||
344 | ]; |
||
345 | break; |
||
0 ignored issues
–
show
break is not strictly necessary here and could be removed.
The break statement is not necessary if it is preceded for example by a return statement: switch ($x) {
case 1:
return 'foo';
break; // This break is not necessary and can be left off.
}
If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive. ![]() |
|||
346 | 3 | case 'Jobinventory': |
|
347 | return [ |
||
348 | 3 | 'keyword' => 'q', |
|
349 | 3 | 'location' => 'l', |
|
350 | 3 | 'pageNumber' => 'getStart', |
|
351 | 3 | 'perPage' => 'limit', |
|
352 | 3 | ]; |
|
353 | break; |
||
0 ignored issues
–
show
break is not strictly necessary here and could be removed.
The break statement is not necessary if it is preceded for example by a return statement: switch ($x) {
case 1:
return 'foo';
break; // This break is not necessary and can be left off.
}
If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive. ![]() |
|||
354 | 2 | case 'J2c': |
|
355 | return [ |
||
356 | 'keyword' => 'q', |
||
357 | 'location' => 'l', |
||
358 | 'pageNumber' => 'start', |
||
359 | 'perPage' => 'limit', |
||
360 | ]; |
||
361 | break; |
||
0 ignored issues
–
show
break is not strictly necessary here and could be removed.
The break statement is not necessary if it is preceded for example by a return statement: switch ($x) {
case 1:
return 'foo';
break; // This break is not necessary and can be left off.
}
If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive. ![]() |
|||
362 | 2 | case 'Juju': |
|
363 | return [ |
||
364 | 'keyword' => 'k', |
||
365 | 'location' => 'l', |
||
366 | 'pageNumber' => 'page', |
||
367 | 'perPage' => 'jpp', |
||
368 | ]; |
||
369 | break; |
||
0 ignored issues
–
show
break is not strictly necessary here and could be removed.
The break statement is not necessary if it is preceded for example by a return statement: switch ($x) {
case 1:
return 'foo';
break; // This break is not necessary and can be left off.
}
If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive. ![]() |
|||
370 | 2 | case 'Monster': |
|
371 | return [ |
||
372 | 2 | 'keyword' => 'q', |
|
373 | 2 | 'location' => 'where', |
|
374 | 2 | 'pageNumber' => 'page', |
|
375 | 2 | ]; |
|
376 | break; |
||
0 ignored issues
–
show
break is not strictly necessary here and could be removed.
The break statement is not necessary if it is preceded for example by a return statement: switch ($x) {
case 1:
return 'foo';
break; // This break is not necessary and can be left off.
}
If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive. ![]() |
|||
377 | 2 | case 'Stackoverflow': |
|
378 | return [ |
||
379 | 2 | 'keyword' => 'q', |
|
380 | 2 | 'location' => 'l', |
|
381 | 2 | 'pageNumber' => 'pg', |
|
382 | 2 | ]; |
|
383 | break; |
||
0 ignored issues
–
show
break is not strictly necessary here and could be removed.
The break statement is not necessary if it is preceded for example by a return statement: switch ($x) {
case 1:
return 'foo';
break; // This break is not necessary and can be left off.
}
If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive. ![]() |
|||
384 | case 'Usajobs': |
||
385 | return [ |
||
386 | 'keyword' => 'Keyword', |
||
387 | 'location' => 'LocationName', |
||
388 | 'pageNumber' => 'Page', |
||
389 | 'perPage' => 'ResultsPerPage', |
||
390 | ]; |
||
391 | break; |
||
0 ignored issues
–
show
break is not strictly necessary here and could be removed.
The break statement is not necessary if it is preceded for example by a return statement: switch ($x) {
case 1:
return 'foo';
break; // This break is not necessary and can be left off.
}
If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive. ![]() |
|||
392 | case 'Ziprecruiter': |
||
393 | return [ |
||
394 | 'keyword' => 'search', |
||
395 | 'location' => 'location', |
||
396 | 'pageNumber' => 'page', |
||
397 | 'perPage' => 'jobs_per_page', |
||
398 | ]; |
||
399 | break; |
||
0 ignored issues
–
show
break is not strictly necessary here and could be removed.
The break statement is not necessary if it is preceded for example by a return statement: switch ($x) {
case 1:
return 'foo';
break; // This break is not necessary and can be left off.
}
If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive. ![]() |
|||
400 | default: |
||
401 | throw new \Exception("Provider {$name} not found"); |
||
402 | } |
||
403 | } |
||
404 | |||
405 | /** |
||
406 | * Instantiates a provider using a query object. |
||
407 | * |
||
408 | * @param null $name |
||
409 | * @param AbstractQuery $query |
||
410 | * |
||
411 | * @return AbstractProvider |
||
412 | */ |
||
413 | 5 | protected function instantiateProvider($name, AbstractQuery $query) |
|
414 | { |
||
415 | 5 | $path = 'JobApis\\Jobs\\Client\\Providers\\' . $name . 'Provider'; |
|
416 | |||
417 | 5 | return new $path($query); |
|
418 | } |
||
419 | |||
420 | /** |
||
421 | * Instantiates a query using a client name. |
||
422 | * |
||
423 | * @param null $name |
||
424 | * |
||
425 | * @return AbstractQuery |
||
426 | */ |
||
427 | 8 | protected function instantiateQuery($name) |
|
428 | { |
||
429 | 8 | $path = 'JobApis\\Jobs\\Client\\Queries\\' . $name . 'Query'; |
|
430 | |||
431 | 8 | $options = array_merge( |
|
432 | 8 | $this->providers[$name], |
|
433 | 6 | $this->getOptionsFromTranslator($this->getTranslatorForProvider($name)) |
|
0 ignored issues
–
show
It seems like
$this->getTranslatorForProvider($name) targeting JobApis\Jobs\Client\Jobs...TranslatorForProvider() can also be of type null ; however, JobApis\Jobs\Client\Jobs...OptionsFromTranslator() does only seem to accept array , maybe add an additional type check?
This check looks at variables that 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. ![]() |
|||
434 | 6 | ); |
|
435 | |||
436 | 6 | return new $path($options); |
|
437 | } |
||
438 | |||
439 | /** |
||
440 | * Get the city and state as an array from a location string. |
||
441 | * |
||
442 | * @return array |
||
443 | */ |
||
444 | 2 | private function getCityAndState() |
|
445 | { |
||
446 | 2 | if ($this->location) { |
|
447 | 2 | $locationArr = explode(', ', $this->location); |
|
448 | return [ |
||
449 | 2 | 'city' => $locationArr[0], |
|
450 | 2 | 'state' => $locationArr[1], |
|
451 | 2 | ]; |
|
452 | } |
||
453 | return []; |
||
454 | } |
||
455 | |||
456 | /** |
||
457 | * Gets a from value. |
||
458 | * |
||
459 | * @return array |
||
460 | */ |
||
461 | 3 | private function getFrom() |
|
462 | { |
||
463 | 3 | if ($this->pageNumber && $this->perPage) { |
|
464 | return [ |
||
465 | 2 | 'from' => ($this->pageNumber * $this->perPage) - $this->perPage, |
|
466 | 2 | ]; |
|
467 | } |
||
468 | 1 | return []; |
|
469 | } |
||
470 | |||
471 | /** |
||
472 | * Gets page number minus 1. |
||
473 | * |
||
474 | * @return array |
||
475 | */ |
||
476 | 4 | private function getPageMinusOne() |
|
477 | { |
||
478 | 4 | if ($this->pageNumber) { |
|
479 | return [ |
||
480 | 3 | 'page' => $this->pageNumber - 1, |
|
481 | 3 | ]; |
|
482 | } |
||
483 | 1 | return []; |
|
484 | } |
||
485 | |||
486 | /** |
||
487 | * Get the query with keyword and location. |
||
488 | * |
||
489 | * @return array |
||
490 | */ |
||
491 | 3 | private function getQueryWithKeywordAndLocation() |
|
492 | { |
||
493 | 3 | $queryString = $this->keyword; |
|
494 | |||
495 | 3 | if ($this->location) { |
|
496 | 2 | $queryString .= ' in '.$this->location; |
|
497 | 2 | } |
|
498 | |||
499 | return [ |
||
500 | 3 | 'query' => $queryString, |
|
501 | 3 | ]; |
|
502 | } |
||
503 | |||
504 | /** |
||
505 | * Gets a start at value. |
||
506 | * |
||
507 | * @return array |
||
508 | */ |
||
509 | 3 | private function getStart() |
|
510 | { |
||
511 | 3 | if ($this->pageNumber && $this->perPage) { |
|
512 | return [ |
||
513 | 3 | 'start' => ($this->pageNumber * $this->perPage) - $this->perPage, |
|
514 | 3 | ]; |
|
515 | } |
||
516 | return []; |
||
517 | } |
||
518 | |||
519 | /** |
||
520 | * Tests whether location string follows valid convention (City, ST). |
||
521 | * |
||
522 | * @param string $location |
||
523 | * |
||
524 | * @return bool |
||
525 | */ |
||
526 | 8 | private function isValidLocation($location = null) |
|
527 | { |
||
528 | 8 | preg_match("/([^,]+),\s*(\w{2})/", $location, $matches); |
|
529 | 8 | return isset($matches[1]) && isset($matches[2]) ? true : false; |
|
530 | } |
||
531 | } |
||
532 |
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: