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; |
||
292 | 6 | case 'Careercast': |
|
293 | return [ |
||
294 | 'keyword' => 'keyword', |
||
295 | 'location' => 'location', |
||
296 | 'pageNumber' => 'page', |
||
297 | 'perPage' => 'rows', |
||
298 | ]; |
||
299 | break; |
||
300 | 6 | case 'Careerjet': |
|
301 | return [ |
||
302 | 'keyword' => 'keywords', |
||
303 | 'location' => 'location', |
||
304 | 'pageNumber' => 'page', |
||
305 | 'perPage' => 'pagesize', |
||
306 | ]; |
||
307 | break; |
||
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; |
||
316 | 6 | case 'Github': |
|
317 | return [ |
||
318 | 4 | 'keyword' => 'search', |
|
319 | 4 | 'location' => 'location', |
|
320 | 4 | 'pageNumber' => 'getPageMinusOne', |
|
321 | 4 | ]; |
|
322 | break; |
||
323 | 4 | case 'Govt': |
|
324 | return [ |
||
325 | 3 | 'keyword' => 'getQueryWithKeywordAndLocation', |
|
326 | 3 | 'pageNumber' => 'getFrom', |
|
327 | 3 | 'perPage' => 'size', |
|
328 | 3 | ]; |
|
329 | break; |
||
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; |
||
338 | 3 | case 'Indeed': |
|
339 | return [ |
||
340 | 'keyword' => 'q', |
||
341 | 'location' => 'l', |
||
342 | 'pageNumber' => 'getStart', |
||
343 | 'perPage' => 'limit', |
||
344 | ]; |
||
345 | break; |
||
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; |
||
354 | 2 | case 'J2c': |
|
355 | return [ |
||
356 | 'keyword' => 'q', |
||
357 | 'location' => 'l', |
||
358 | 'pageNumber' => 'start', |
||
359 | 'perPage' => 'limit', |
||
360 | ]; |
||
361 | break; |
||
362 | 2 | case 'Juju': |
|
363 | return [ |
||
364 | 'keyword' => 'k', |
||
365 | 'location' => 'l', |
||
366 | 'pageNumber' => 'page', |
||
367 | 'perPage' => 'jpp', |
||
368 | ]; |
||
369 | break; |
||
370 | 2 | case 'Monster': |
|
371 | return [ |
||
372 | 2 | 'keyword' => 'q', |
|
373 | 2 | 'location' => 'where', |
|
374 | 2 | 'pageNumber' => 'page', |
|
375 | 2 | ]; |
|
376 | break; |
||
377 | 2 | case 'Stackoverflow': |
|
378 | return [ |
||
379 | 2 | 'keyword' => 'q', |
|
380 | 2 | 'location' => 'l', |
|
381 | 2 | 'pageNumber' => 'pg', |
|
382 | 2 | ]; |
|
383 | break; |
||
384 | case 'Usajobs': |
||
385 | return [ |
||
386 | 'keyword' => 'Keyword', |
||
387 | 'location' => 'LocationName', |
||
388 | 'pageNumber' => 'Page', |
||
389 | 'perPage' => 'ResultsPerPage', |
||
390 | ]; |
||
391 | break; |
||
392 | case 'Ziprecruiter': |
||
393 | return [ |
||
394 | 'keyword' => 'search', |
||
395 | 'location' => 'location', |
||
396 | 'pageNumber' => 'page', |
||
397 | 'perPage' => 'jobs_per_page', |
||
398 | ]; |
||
399 | break; |
||
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)) |
|
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: