Add support for weekday-specific and time-of-day progress alerts in goals_criteria
- Introduce `progress_alert_weekdays` and `progress_alert_time_of_day` fields with parsing, validation, and sanitization logic. - Add `goals_criteria_progress_alert_weekday` enum for supported weekdays. - Update `toArray` and OpenAPI specification to support new fields and maintain backward compatibility.
This commit is contained in:
@@ -6166,6 +6166,27 @@ components:
|
||||
Max length depends on destination: 160 characters for SMS; 1024 characters for EMAIL/SLACK/other.
|
||||
The canonical field name is snake_case `progress_alert_format`.
|
||||
For backward-compatibility the API also accepts camelCase `progressAlertFormat` on input.
|
||||
progress_alert_weekdays:
|
||||
type: array
|
||||
description: |
|
||||
Weekdays on which progress alerts should be sent.
|
||||
Use one or more of: MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY.
|
||||
The canonical field name is snake_case `progress_alert_weekdays`.
|
||||
For backward-compatibility the API also accepts camelCase `progressAlertWeekdays` on input.
|
||||
items:
|
||||
type: string
|
||||
enum: [MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY]
|
||||
example: [MONDAY, WEDNESDAY, FRIDAY]
|
||||
progress_alert_time_of_day:
|
||||
type: string
|
||||
nullable: true
|
||||
description: |
|
||||
Time of day (with timezone) when progress alerts should be sent.
|
||||
Format: `HH:MMZ` or `HH:MM±HH:MM` (24-hour clock with UTC offset). Examples: `14:30Z`, `09:15+02:00`, `18:45-05:00`.
|
||||
The canonical field name is snake_case `progress_alert_time_of_day`.
|
||||
For backward-compatibility the API also accepts camelCase `progressAlertTimeOfDay` on input.
|
||||
pattern: '^([01]\d|2[0-3]):[0-5]\d(?:Z|[+-](?:[01]\d|2[0-3]):?[0-5]\d)$'
|
||||
example: "14:30+02:00"
|
||||
|
||||
DepartmentGoal:
|
||||
type: object
|
||||
|
||||
@@ -8,6 +8,7 @@ use goals\helpers\goals_criteria_progress_alert_frequency;
|
||||
use goals\helpers\goals_criteria_progress_alert_destination;
|
||||
use goals\helpers\goals_criteria_progress_alert_progress_type;
|
||||
use goals\helpers\goals_criteria_progress_alert_style;
|
||||
use goals\helpers\goals_criteria_progress_alert_weekday;
|
||||
use goals\interfaces\goals_criteria_i;
|
||||
use goals\traits\goals_result_parser_t;
|
||||
use goals\traits\goals_target_t;
|
||||
@@ -66,6 +67,16 @@ class goals_criteria implements goals_criteria_i
|
||||
* @var string|null $progress_alert_format
|
||||
*/
|
||||
public ?string $progress_alert_format = null;
|
||||
/**
|
||||
* Weekdays on which progress alerts should be sent
|
||||
* @var goals_criteria_progress_alert_weekday[] $progress_alert_weekdays
|
||||
*/
|
||||
public array $progress_alert_weekdays = [];
|
||||
/**
|
||||
* Time of day (with timezone) when progress alerts should be sent, formatted as HH:MM with timezone (e.g., 14:30Z or 14:30+02:00)
|
||||
* @var string|null $progress_alert_time_of_day
|
||||
*/
|
||||
public ?string $progress_alert_time_of_day = null;
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
@@ -182,6 +193,46 @@ class goals_criteria implements goals_criteria_i
|
||||
$criteria->progress_alert_format = trim((string)$data['progressAlertFormat']);
|
||||
}
|
||||
|
||||
// Parse progress alert weekdays (array of strings)
|
||||
if (isset($data['progress_alert_weekdays']) && is_array($data['progress_alert_weekdays'])) {
|
||||
$seen = [];
|
||||
$weekdays = [];
|
||||
foreach ($data['progress_alert_weekdays'] as $wd) {
|
||||
if (!is_string($wd)) { continue; }
|
||||
$e = goals_criteria_progress_alert_weekday::tryFrom($wd);
|
||||
if ($e !== null) {
|
||||
$key = $e->name;
|
||||
if (!isset($seen[$key])) {
|
||||
$seen[$key] = true;
|
||||
$weekdays[] = $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
$criteria->progress_alert_weekdays = $weekdays;
|
||||
} elseif (isset($data['progressAlertWeekdays']) && is_array($data['progressAlertWeekdays'])) {
|
||||
$seen = [];
|
||||
$weekdays = [];
|
||||
foreach ($data['progressAlertWeekdays'] as $wd) {
|
||||
if (!is_string($wd)) { continue; }
|
||||
$e = goals_criteria_progress_alert_weekday::tryFrom($wd);
|
||||
if ($e !== null) {
|
||||
$key = $e->name;
|
||||
if (!isset($seen[$key])) {
|
||||
$seen[$key] = true;
|
||||
$weekdays[] = $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
$criteria->progress_alert_weekdays = $weekdays;
|
||||
}
|
||||
|
||||
// Parse progress alert time of day (string with timezone)
|
||||
if (isset($data['progress_alert_time_of_day']) && is_string($data['progress_alert_time_of_day'])) {
|
||||
$criteria->progress_alert_time_of_day = trim((string)$data['progress_alert_time_of_day']);
|
||||
} elseif (isset($data['progressAlertTimeOfDay']) && is_string($data['progressAlertTimeOfDay'])) {
|
||||
$criteria->progress_alert_time_of_day = trim((string)$data['progressAlertTimeOfDay']);
|
||||
}
|
||||
|
||||
// Parse timeframe with validation
|
||||
if (isset($data['start']) && is_string($data['start'])) {
|
||||
try {
|
||||
@@ -328,6 +379,8 @@ class goals_criteria implements goals_criteria_i
|
||||
'progress_alert_progress_type' => $this->progress_alert_progress_type?->name ?? goals_criteria_progress_alert_progress_type::NONE->name,
|
||||
'progress_alert_style' => $this->progress_alert_style?->name ?? goals_criteria_progress_alert_style::NONE->name,
|
||||
'progress_alert_format' => $this->progress_alert_format,
|
||||
'progress_alert_weekdays' => array_map(fn($e) => ($e instanceof goals_criteria_progress_alert_weekday) ? $e->name : (string)$e, $this->progress_alert_weekdays ?? []),
|
||||
'progress_alert_time_of_day' => $this->progress_alert_time_of_day,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -480,5 +533,57 @@ class goals_criteria implements goals_criteria_i
|
||||
$this->progress_alert_format = $fmt === '' ? null : $fmt;
|
||||
}
|
||||
}
|
||||
|
||||
// Sanitize weekdays: keep only valid enum values, dedupe, and normalize order (Mon..Sun)
|
||||
if (is_array($this->progress_alert_weekdays)) {
|
||||
$seen = [];
|
||||
$clean = [];
|
||||
foreach ($this->progress_alert_weekdays as $wd) {
|
||||
$enum = $wd instanceof goals_criteria_progress_alert_weekday
|
||||
? $wd
|
||||
: (is_string($wd) ? goals_criteria_progress_alert_weekday::tryFrom($wd) : null);
|
||||
if ($enum !== null) {
|
||||
$k = $enum->name;
|
||||
if (!isset($seen[$k])) {
|
||||
$seen[$k] = true;
|
||||
$clean[] = $enum;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Order by weekday index
|
||||
$order = [
|
||||
'MONDAY' => 1,
|
||||
'TUESDAY' => 2,
|
||||
'WEDNESDAY' => 3,
|
||||
'THURSDAY' => 4,
|
||||
'FRIDAY' => 5,
|
||||
'SATURDAY' => 6,
|
||||
'SUNDAY' => 7,
|
||||
];
|
||||
usort($clean, function ($a, $b) use ($order) {
|
||||
$an = $a->name ?? (string)$a;
|
||||
$bn = $b->name ?? (string)$b;
|
||||
return ($order[$an] ?? 99) <=> ($order[$bn] ?? 99);
|
||||
});
|
||||
$this->progress_alert_weekdays = $clean;
|
||||
}
|
||||
|
||||
// Sanitize time of day with timezone (HH:MMZ or HH:MM±HH:MM)
|
||||
if (is_string($this->progress_alert_time_of_day)) {
|
||||
$time = trim($this->progress_alert_time_of_day);
|
||||
// Accept Z, +HH:MM, -HH:MM (offset colon optional: +HHMM)
|
||||
$pattern = '/^([01]\d|2[0-3]):[0-5]\d(?:Z|[+-](?:[01]\d|2[0-3]):?[0-5]\d)$/';
|
||||
if (!preg_match($pattern, $time)) {
|
||||
// Try to normalize offsets like +HHMM to +HH:MM
|
||||
if (preg_match('/^([01]\d|2[0-3]):([0-5]\d)([+-])(\d{2})(\d{2})$/', $time, $m)) {
|
||||
$time = sprintf('%s:%s%s%s:%s', $m[1], $m[2], $m[3], $m[4], $m[5]);
|
||||
}
|
||||
}
|
||||
if (preg_match($pattern, $time)) {
|
||||
$this->progress_alert_time_of_day = $time;
|
||||
} else {
|
||||
$this->progress_alert_time_of_day = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace goals\helpers;
|
||||
|
||||
enum goals_criteria_progress_alert_weekday
|
||||
{
|
||||
case MONDAY;
|
||||
case TUESDAY;
|
||||
case WEDNESDAY;
|
||||
case THURSDAY;
|
||||
case FRIDAY;
|
||||
case SATURDAY;
|
||||
case SUNDAY;
|
||||
|
||||
public static function tryFrom(string $param): ?goals_criteria_progress_alert_weekday
|
||||
{
|
||||
return match (strtoupper($param)) {
|
||||
'MON', 'MONDAY' => self::MONDAY,
|
||||
'TUE', 'TUES', 'TUESDAY' => self::TUESDAY,
|
||||
'WED', 'WEDNESDAY' => self::WEDNESDAY,
|
||||
'THU', 'THUR', 'THURS', 'THURSDAY' => self::THURSDAY,
|
||||
'FRI', 'FRIDAY' => self::FRIDAY,
|
||||
'SAT', 'SATURDAY' => self::SATURDAY,
|
||||
'SUN', 'SUNDAY' => self::SUNDAY,
|
||||
default => null,
|
||||
};
|
||||
}
|
||||
|
||||
public function equals(goals_criteria_progress_alert_weekday $param): bool
|
||||
{
|
||||
return $this === $param;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user