Skip to content

Commit 1c7581d

Browse files
committed
fix last few errors for PUT national calendar
- LitLocale::$AllAvailableLocales must be initialized - do not verify `key` for PUT requests - do not verify `locale` for PUT requests - handleRequestParams must differentiate between DIOCESANCALENDAR and NATIONALCALENDAR requests
1 parent 571e276 commit 1c7581d

File tree

4 files changed

+120
-52
lines changed

4 files changed

+120
-52
lines changed

jsondata/schemas/NationalCalendar.json

+22
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,28 @@
3434
},
3535
"metadata": {
3636
"$ref": "#/definitions/NationalCalendarMetadata"
37+
},
38+
"i18n": {
39+
"type": "object",
40+
"description": "A JSON object of the form { \"locale\": { \"key\": \"value\" } }, used only in PUT and PATCH requests.",
41+
"additionalProperties": false,
42+
"propertyNames": {
43+
"$ref": "https://litcal.johnromanodorazio.com/api/dev/jsondata/schemas/CommonDef.json#/definitions/Locale"
44+
},
45+
"patternProperties": {
46+
"": {
47+
"type": "object",
48+
"additionalProperties": false,
49+
"propertyNames": {
50+
"$ref": "https://litcal.johnromanodorazio.com/api/dev/jsondata/schemas/CommonDef.json#/definitions/EventKey"
51+
},
52+
"patternProperties": {
53+
"": {
54+
"type": "string"
55+
}
56+
}
57+
}
58+
}
3759
}
3860
},
3961
"required": [

src/Enum/LitLocale.php

+16-5
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,7 @@ class LitLocale
1818
*/
1919
public static function isValid($value)
2020
{
21-
if (null === self::$AllAvailableLocales) {
22-
self::$AllAvailableLocales = array_filter(\ResourceBundle::getLocales(''), function ($value) {
23-
return strpos($value, 'POSIX') === false;
24-
});
25-
}
21+
self::init();
2622
return in_array($value, self::$values) || in_array($value, self::$AllAvailableLocales);
2723
}
2824

@@ -41,4 +37,19 @@ public static function areValid(array $values)
4137
}
4238
return true;
4339
}
40+
41+
/**
42+
* Initializes the list of available locales.
43+
*
44+
* This method loads the list of locales from the ICU data available in PHP.
45+
* It then filters out the "POSIX" locale, which is not a valid regional locale.
46+
*/
47+
public static function init()
48+
{
49+
if (null === self::$AllAvailableLocales) {
50+
self::$AllAvailableLocales = array_filter(\ResourceBundle::getLocales(''), function ($value) {
51+
return strpos($value, 'POSIX') === false;
52+
});
53+
}
54+
}
4455
}

src/Params/RegionalDataParams.php

+31-28
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ public function __construct()
5353
$this->calendars = $metadata->litcal_metadata;
5454
}
5555
}
56+
57+
// Initialize the list of available locales
58+
LitLocale::init();
5659
}
5760

5861
/**
@@ -76,16 +79,15 @@ public function __construct()
7679
private function checkNationalCalendarConditions(object $data): string
7780
{
7881
if (RegionalData::$Core->getRequestMethod() === RequestMethod::PUT) {
79-
// Cannot PUT a National calendar data if it already exists
82+
// Cannot PUT National calendar data if it already exists
8083
if (in_array($data->key, $this->calendars->national_calendars_keys)) {
8184
RegionalData::produceErrorResponse(
8285
StatusCode::BAD_REQUEST,
8386
"Cannot PUT National Calendar data if it already exists."
8487
);
8588
}
86-
$uniqueRegions = array_unique(array_map(function (string $locale) {
87-
return \Locale::getRegion($locale) !== '';
88-
}, LitLocale::$AllAvailableLocales));
89+
90+
$uniqueRegions = array_unique(array_map(fn (string $locale) => \Locale::getRegion($locale) !== '', LitLocale::$AllAvailableLocales));
8991
if (false === in_array($data->key, $uniqueRegions)) {
9092
RegionalData::produceErrorResponse(
9193
StatusCode::BAD_REQUEST,
@@ -103,34 +105,37 @@ private function checkNationalCalendarConditions(object $data): string
103105
);
104106
}
105107
}
106-
} elseif (
107-
false === in_array($data->key, $this->calendars->national_calendars_keys)
108-
) {
109-
$validVals = implode(', ', $this->calendars->national_calendars_keys);
110-
RegionalData::produceErrorResponse(
111-
StatusCode::BAD_REQUEST,
112-
"Invalid value {$data->key} for param `key`, valid values are: {$validVals}"
113-
);
114108
}
115109

116-
$currentNation = array_values(array_filter($this->calendars->national_calendars, fn ($el) => $el->calendar_id === $data->key));
117-
if (empty($currentNation)) {
118-
RegionalData::produceErrorResponse(
119-
StatusCode::BAD_REQUEST,
120-
"Invalid value {$data->key} for param `key`, valid values are: "
121-
. implode(', ', $this->calendars->national_calendars_keys) . "\n\n"
122-
. json_encode($this->calendars->national_calendars, JSON_PRETTY_PRINT)
123-
);
110+
// We must verify the `key` parameter for any request that is not PUT
111+
if (RegionalData::$Core->getRequestMethod() !== RequestMethod::PUT) {
112+
if (false === in_array($data->key, $this->calendars->national_calendars_keys)) {
113+
$validVals = implode(', ', $this->calendars->national_calendars_keys);
114+
RegionalData::produceErrorResponse(
115+
StatusCode::BAD_REQUEST,
116+
"Invalid value {$data->key} for param `key`, valid values are: {$validVals}"
117+
);
118+
} else {
119+
$currentNation = array_values(array_filter($this->calendars->national_calendars, fn ($el) => $el->calendar_id === $data->key));
120+
if (empty($currentNation)) {
121+
RegionalData::produceErrorResponse(
122+
StatusCode::BAD_REQUEST,
123+
"Invalid value {$data->key} for param `key`, valid values are: "
124+
. implode(', ', $this->calendars->national_calendars_keys) . "\n\n"
125+
. json_encode($this->calendars->national_calendars, JSON_PRETTY_PRINT)
126+
);
127+
}
128+
}
124129
}
125130

126-
// we don't care about locale for DELETE requests
127-
if (RegionalData::$Core->getRequestMethod() !== RequestMethod::DELETE) {
131+
132+
// we don't care about locale for DELETE or PUT requests
133+
if (false === in_array(RegionalData::$Core->getRequestMethod(), [RequestMethod::DELETE, RequestMethod::PUT], true)) {
128134
$validLangs = $currentNation[0]->locales;
129135
if (property_exists($data, 'locale')) {
130136
$data->locale = \Locale::canonicalize($data->locale);
131137
if (
132-
RegionalData::$Core->getRequestMethod() === RequestMethod::PUT // short circuit for PUT requests that don't need to validate against existing locales
133-
|| null !== $this->i18nRequest // short circuit for i18n requests
138+
null !== $this->i18nRequest // short circuit for i18n requests
134139
|| in_array($data->locale, $validLangs, true)
135140
) {
136141
$this->locale = $data->locale;
@@ -142,8 +147,7 @@ private function checkNationalCalendarConditions(object $data): string
142147
} elseif (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
143148
$value = \Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE']);
144149
if (
145-
RegionalData::$Core->getRequestMethod() === RequestMethod::PUT // short circuit for PUT requests that don't need to validate against existing locales
146-
|| null !== $this->i18nRequest // short circuit for i18n requests
150+
null !== $this->i18nRequest // short circuit for i18n requests
147151
|| in_array($value, $validLangs, true)
148152
) {
149153
$this->locale = $value;
@@ -157,7 +161,6 @@ private function checkNationalCalendarConditions(object $data): string
157161
}
158162
}
159163

160-
161164
return $data->key;
162165
}
163166

@@ -392,7 +395,7 @@ public function setData(object $data): bool
392395
if (false === property_exists($data, 'category') || false === property_exists($data, 'key')) {
393396
RegionalData::produceErrorResponse(
394397
StatusCode::BAD_REQUEST,
395-
"Expected params `category` and `key` but either one or both not present"
398+
"Expected params `category` and `key` but either one or both not present."
396399
);
397400
}
398401

src/Paths/RegionalData.php

+51-19
Original file line numberDiff line numberDiff line change
@@ -971,29 +971,61 @@ private function handleRequestParams(array $requestPathParts = []): void
971971

972972
// In the case of a PUT request, we expect only one PATH parameter, we only retrieve the payload from the request body
973973
if (self::$Core->getRequestMethod() === RequestMethod::PUT) {
974-
if (
975-
!property_exists($data, 'payload')
976-
|| $data->payload === null
977-
|| !property_exists($data->payload, 'litcal')
978-
|| !property_exists($data->payload, 'i18n')
979-
|| !property_exists($data->payload, 'metadata')
980-
|| !property_exists($data->payload->metadata, 'diocese_id')
981-
) {
982-
self::produceErrorResponse(StatusCode::BAD_REQUEST, "Invalid payload in request. Must receive non empty payload in body of request, in JSON or YAML or form encoded format, with properties `payload`, `payload.litcal`, `payload.i18n`, `payload.metadata`, and `payload.metadata.diocese_id`");
983-
} else {
984-
$data->key = $data->payload->metadata->diocese_id;
974+
switch ($data->category) {
975+
case 'DIOCESANCALENDAR':
976+
if (
977+
!property_exists($data, 'payload')
978+
|| $data->payload === null
979+
|| !property_exists($data->payload, 'litcal')
980+
|| !property_exists($data->payload, 'i18n')
981+
|| !property_exists($data->payload, 'metadata')
982+
|| !property_exists($data->payload->metadata, 'diocese_id')
983+
) {
984+
self::produceErrorResponse(StatusCode::BAD_REQUEST, "Invalid payload in request. Must receive non empty payload in body of request, in JSON or YAML or form encoded format, with properties `payload`, `payload.litcal`, `payload.i18n`, `payload.metadata`, and `payload.metadata.diocese_id`, instead payload was: " . json_encode($data->payload));
985+
} else {
986+
$data->key = $data->payload->metadata->diocese_id;
987+
}
988+
break;
989+
case 'NATIONALCALENDAR':
990+
if (
991+
!property_exists($data, 'payload')
992+
|| $data->payload === null
993+
|| !property_exists($data->payload, 'litcal')
994+
|| !property_exists($data->payload, 'i18n')
995+
|| !property_exists($data->payload, 'metadata')
996+
|| !property_exists($data->payload, 'settings')
997+
|| !property_exists($data->payload->metadata, 'nation')
998+
) {
999+
self::produceErrorResponse(StatusCode::BAD_REQUEST, "Invalid payload in request. Must receive non empty payload in body of request, in JSON or YAML or form encoded format, with properties `payload`, `payload.litcal`, `payload.i18n`, `payload.metadata`, `payload.settings`, and `payload.metadata.nation`, instead payload was: " . json_encode($data->payload));
1000+
} else {
1001+
$data->key = $data->payload->metadata->nation;
1002+
}
1003+
break;
1004+
case 'WIDERREGIONCALENDAR':
1005+
// TODO: define shape of wider region payload
1006+
break;
9851007
}
9861008
}
9871009

9881010
if (self::$Core->getRequestMethod() === RequestMethod::PATCH) {
989-
if (
990-
!property_exists($data, 'payload')
991-
|| $data->payload === null
992-
|| !property_exists($data->payload, 'litcal')
993-
|| !property_exists($data->payload, 'i18n')
994-
|| !property_exists($data->payload, 'metadata')
995-
) {
996-
self::produceErrorResponse(StatusCode::BAD_REQUEST, "Invalid payload in request. Must receive non empty payload in body of request, in JSON or YAML or form encoded format, with properties `payload`, `payload.litcal`, `payload.i18n`, and `payload.metadata`");
1011+
switch ($data->category) {
1012+
case 'DIOCESANCALENDAR':
1013+
if (
1014+
!property_exists($data, 'payload')
1015+
|| $data->payload === null
1016+
|| !property_exists($data->payload, 'litcal')
1017+
|| !property_exists($data->payload, 'i18n')
1018+
|| !property_exists($data->payload, 'metadata')
1019+
) {
1020+
self::produceErrorResponse(StatusCode::BAD_REQUEST, "Invalid payload in request. Must receive non empty payload in body of request, in JSON or YAML or form encoded format, with properties `payload`, `payload.litcal`, `payload.i18n`, and `payload.metadata`");
1021+
}
1022+
break;
1023+
case 'NATIONALCALENDAR':
1024+
// TODO: define shape of nation payload
1025+
break;
1026+
case 'WIDERREGIONCALENDAR':
1027+
// TODO: define shape of wider region payload
1028+
break;
9971029
}
9981030
}
9991031

0 commit comments

Comments
 (0)