Add unit tests for advanced target duration parsing, goal range calculations, and Workfeed query normalization. Extend OpenAPI spec with updated schemas and examples.
This commit is contained in:
@@ -30,15 +30,9 @@ class workfeed implements workfeed_i
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function listEmployees(array $filters = []): object
|
||||
public function listEmployees(array $filters = []): array|object
|
||||
{
|
||||
return $this->sendApiRequest('GET', '/employees', $this->filterAllowed($filters, [
|
||||
'search',
|
||||
'departmentId',
|
||||
'includeInactive',
|
||||
'limit',
|
||||
'cursor',
|
||||
]));
|
||||
return $this->sendApiRequest('GET', '/employees');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -54,17 +48,11 @@ class workfeed implements workfeed_i
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function listShifts(array $filters = []): object
|
||||
public function listShifts(array $filters = []): array|object
|
||||
{
|
||||
return $this->sendApiRequest('GET', '/shifts', $this->filterAllowed($filters, [
|
||||
'from',
|
||||
'to',
|
||||
'departmentId',
|
||||
'employeeId',
|
||||
'status',
|
||||
'limit',
|
||||
'cursor',
|
||||
]));
|
||||
$normalizedFilters = $this->normalizeShiftFilters($filters);
|
||||
|
||||
return $this->sendApiRequest('GET', '/shifts', $normalizedFilters);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -80,28 +68,29 @@ class workfeed implements workfeed_i
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function listDepartments(array $filters = []): object
|
||||
public function listDepartments(array $filters = []): array|object
|
||||
{
|
||||
return $this->sendApiRequest('GET', '/departments', $this->filterAllowed($filters, [
|
||||
'search',
|
||||
'limit',
|
||||
'cursor',
|
||||
]));
|
||||
return $this->sendApiRequest('GET', '/departments');
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
private function sendApiRequest(string $method, string $path, array $query = []): object
|
||||
private function sendApiRequest(string $method, string $path, array $query = []): array|object
|
||||
{
|
||||
$this->requireModuleEnabled();
|
||||
$this->requireConfiguredApiUrl();
|
||||
$this->requireConfiguredApiKey();
|
||||
$companyId = $this->requireConfiguredCompanyId();
|
||||
|
||||
$url = $this->buildUrl($this->config->api_url->getVariableValue(), $path, $query);
|
||||
$url = $this->buildUrl(
|
||||
$this->config->api_url->getVariableValue(),
|
||||
'/companies/' . rawurlencode($companyId) . '/' . ltrim($path, '/'),
|
||||
$query
|
||||
);
|
||||
$headers = [
|
||||
'Accept: application/json',
|
||||
'Authorization: Bearer ' . trim((string)$this->config->api_key->getVariableValue()),
|
||||
'Authorization: ' . trim((string)$this->config->api_key->getVariableValue()),
|
||||
];
|
||||
|
||||
return $this->executeJsonRequest($method, $url, $headers);
|
||||
@@ -110,7 +99,7 @@ class workfeed implements workfeed_i
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
private function executeJsonRequest(string $method, string $url, array $headers): object
|
||||
private function executeJsonRequest(string $method, string $url, array $headers): array|object
|
||||
{
|
||||
$response = $this->executeRequest($method, $url, $headers);
|
||||
$decoded = json_decode($response['body']);
|
||||
@@ -123,12 +112,12 @@ class workfeed implements workfeed_i
|
||||
throw new Exception($this->extractErrorMessage($decoded, $response['status'], 'Workfeed API request failed'));
|
||||
}
|
||||
|
||||
if (is_object($decoded)) {
|
||||
if (is_object($decoded) || is_array($decoded)) {
|
||||
return $decoded;
|
||||
}
|
||||
|
||||
return (object)[
|
||||
'data' => $decoded,
|
||||
'value' => $decoded,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -208,6 +197,19 @@ class workfeed implements workfeed_i
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
private function requireConfiguredCompanyId(): string
|
||||
{
|
||||
$companyId = trim((string)$this->config->company_id->getVariableValue());
|
||||
if ($companyId === '') {
|
||||
throw new Exception('Invalid Workfeed CompanyID configured.');
|
||||
}
|
||||
|
||||
return $companyId;
|
||||
}
|
||||
|
||||
private function normalizeUrlForValidation(string $url): string
|
||||
{
|
||||
if (preg_match('#^https?://#i', $url)) {
|
||||
@@ -241,6 +243,71 @@ class workfeed implements workfeed_i
|
||||
return $filtered;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
private function normalizeShiftFilters(array $filters): array
|
||||
{
|
||||
$filtered = $this->filterAllowed($filters, [
|
||||
'startFrom',
|
||||
'startTo',
|
||||
'from',
|
||||
'to',
|
||||
'employeeID',
|
||||
'employeeId',
|
||||
'released',
|
||||
]);
|
||||
|
||||
if (!isset($filtered['startFrom']) && isset($filtered['from'])) {
|
||||
$filtered['startFrom'] = $filtered['from'];
|
||||
}
|
||||
if (!isset($filtered['startTo']) && isset($filtered['to'])) {
|
||||
$filtered['startTo'] = $filtered['to'];
|
||||
}
|
||||
if (!isset($filtered['employeeID']) && isset($filtered['employeeId'])) {
|
||||
$filtered['employeeID'] = $filtered['employeeId'];
|
||||
}
|
||||
|
||||
unset($filtered['from'], $filtered['to'], $filtered['employeeId']);
|
||||
|
||||
if (!isset($filtered['startFrom']) || trim((string)$filtered['startFrom']) === '') {
|
||||
throw new Exception('Workfeed shift query requires startFrom.');
|
||||
}
|
||||
|
||||
if (!isset($filtered['startTo']) || trim((string)$filtered['startTo']) === '') {
|
||||
throw new Exception('Workfeed shift query requires startTo.');
|
||||
}
|
||||
|
||||
if (isset($filtered['released'])) {
|
||||
$filtered['released'] = $this->normalizeBooleanQueryValue($filtered['released']);
|
||||
}
|
||||
|
||||
return $filtered;
|
||||
}
|
||||
|
||||
private function normalizeBooleanQueryValue(mixed $value): string
|
||||
{
|
||||
if (is_bool($value)) {
|
||||
return $value ? 'true' : 'false';
|
||||
}
|
||||
|
||||
if (is_string($value)) {
|
||||
$normalized = strtolower(trim($value));
|
||||
if (in_array($normalized, ['1', 'true', 'yes', 'on'], true)) {
|
||||
return 'true';
|
||||
}
|
||||
if (in_array($normalized, ['0', 'false', 'no', 'off'], true)) {
|
||||
return 'false';
|
||||
}
|
||||
}
|
||||
|
||||
if (is_int($value)) {
|
||||
return $value === 1 ? 'true' : 'false';
|
||||
}
|
||||
|
||||
return (string)$value;
|
||||
}
|
||||
|
||||
private function extractErrorMessage(mixed $decoded, int $statusCode, string $fallback): string
|
||||
{
|
||||
if (is_object($decoded)) {
|
||||
|
||||
Reference in New Issue
Block a user