177 lines
5.1 KiB
PHP
177 lines
5.1 KiB
PHP
<?php
|
|
|
|
namespace App\Services\JobApi\Clients;
|
|
|
|
use App\Services\JobApi\DTO\JobData;
|
|
use App\Services\JobApi\Exceptions\ApiException;
|
|
use App\Services\JobApi\Transformers\AdzunaTransformer;
|
|
use App\Services\JobApi\Transformers\JobTransformer;
|
|
use Illuminate\Http\Client\PendingRequest;
|
|
|
|
class AdzunaClient extends JobApiClient
|
|
{
|
|
private string $appId;
|
|
private string $appKey;
|
|
private string $country = 'us'; // Default to US
|
|
|
|
protected function getTransformer(): JobTransformer
|
|
{
|
|
return new AdzunaTransformer();
|
|
}
|
|
|
|
protected function attachAuthentication(PendingRequest $client): PendingRequest
|
|
{
|
|
// Parse API key as "app_id:app_key"
|
|
if ($this->source->api_key && str_contains($this->source->api_key, ':')) {
|
|
[$this->appId, $this->appKey] = explode(':', $this->source->api_key, 2);
|
|
} else {
|
|
throw new ApiException(
|
|
'Adzuna API key must be in format "app_id:app_key"',
|
|
$this->source->name
|
|
);
|
|
}
|
|
|
|
// Extract country from configuration if set
|
|
if (!empty($this->source->configuration['country'])) {
|
|
$this->country = $this->source->configuration['country'];
|
|
}
|
|
|
|
return $client;
|
|
}
|
|
|
|
/**
|
|
* Fetch jobs from Adzuna API
|
|
*
|
|
* @param array $params [
|
|
* 'what' => string, // Job title or keywords
|
|
* 'where' => string, // Location
|
|
* 'results_per_page' => int,
|
|
* 'page' => int,
|
|
* 'category' => string,
|
|
* 'full_time' => int, // 1 for full-time only
|
|
* 'part_time' => int, // 1 for part-time only
|
|
* 'contract' => int, // 1 for contract only
|
|
* 'max_days_old' => int, // Jobs posted within last N days
|
|
* ]
|
|
* @return array<JobData>
|
|
*/
|
|
public function fetchJobs(array $params = []): array
|
|
{
|
|
try {
|
|
$queryParams = $this->buildQueryParams($params);
|
|
|
|
// Adzuna API endpoint structure: /v1/api/jobs/{country}/search/{page}
|
|
$page = $queryParams['page'] ?? 1;
|
|
unset($queryParams['page']);
|
|
|
|
$endpoint = "search/{$page}";
|
|
|
|
$response = $this->makeRequest('GET', $endpoint, $queryParams);
|
|
|
|
$data = $response->json();
|
|
|
|
if (!isset($data['results']) || !is_array($data['results'])) {
|
|
throw new ApiException(
|
|
'Invalid response structure from Adzuna API',
|
|
$this->source->name,
|
|
['response' => $data]
|
|
);
|
|
}
|
|
|
|
$this->updateLastFetched();
|
|
|
|
return $this->transformer->transformMany($data['results']);
|
|
|
|
} catch (ApiException $e) {
|
|
throw $e;
|
|
} catch (\Throwable $e) {
|
|
throw new ApiException(
|
|
'Failed to fetch jobs from Adzuna',
|
|
$this->source->name,
|
|
['error' => $e->getMessage()],
|
|
0,
|
|
$e
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Build query parameters for the API request
|
|
*/
|
|
private function buildQueryParams(array $params): array
|
|
{
|
|
$queryParams = [
|
|
'app_id' => $this->appId,
|
|
'app_key' => $this->appKey,
|
|
'results_per_page' => min($params['results_per_page'] ?? 20, 50),
|
|
'page' => $params['page'] ?? 1,
|
|
];
|
|
|
|
if (!empty($params['what'])) {
|
|
$queryParams['what'] = $params['what'];
|
|
}
|
|
|
|
if (!empty($params['where'])) {
|
|
$queryParams['where'] = $params['where'];
|
|
}
|
|
|
|
if (isset($params['category'])) {
|
|
$queryParams['category'] = $params['category'];
|
|
}
|
|
|
|
if (isset($params['full_time'])) {
|
|
$queryParams['full_time'] = (int) $params['full_time'];
|
|
}
|
|
|
|
if (isset($params['part_time'])) {
|
|
$queryParams['part_time'] = (int) $params['part_time'];
|
|
}
|
|
|
|
if (isset($params['contract'])) {
|
|
$queryParams['contract'] = (int) $params['contract'];
|
|
}
|
|
|
|
if (isset($params['max_days_old'])) {
|
|
$queryParams['max_days_old'] = (int) $params['max_days_old'];
|
|
}
|
|
|
|
return $queryParams;
|
|
}
|
|
|
|
/**
|
|
* Override buildUrl to include country in path
|
|
*/
|
|
protected function buildUrl(string $endpoint): string
|
|
{
|
|
$baseUrl = rtrim($this->source->api_url, '/');
|
|
$endpoint = ltrim($endpoint, '/');
|
|
return "{$baseUrl}/{$this->country}/{$endpoint}";
|
|
}
|
|
|
|
/**
|
|
* Get supported countries
|
|
*/
|
|
public function getSupportedCountries(): array
|
|
{
|
|
return [
|
|
'au' => 'Australia',
|
|
'at' => 'Austria',
|
|
'br' => 'Brazil',
|
|
'ca' => 'Canada',
|
|
'fr' => 'France',
|
|
'de' => 'Germany',
|
|
'in' => 'India',
|
|
'it' => 'Italy',
|
|
'nl' => 'Netherlands',
|
|
'nz' => 'New Zealand',
|
|
'pl' => 'Poland',
|
|
'ru' => 'Russia',
|
|
'sg' => 'Singapore',
|
|
'za' => 'South Africa',
|
|
'ch' => 'Switzerland',
|
|
'gb' => 'United Kingdom',
|
|
'us' => 'United States',
|
|
];
|
|
}
|
|
}
|