Liturgical-Calendar / LiturgicalCalendarAPI

A PHP script / API endpoint that will generate the Roman Catholic liturgical calendar for any given year, calculating the mobile festivities and the precedence of solemnities, feasts, memorials...
Apache License 2.0
50 stars 11 forks source link

define resource paths #220

Open JohnRDOrazio opened 5 months ago

JohnRDOrazio commented 5 months ago

We now have routing in place. We need to define a clear resource path strategy.

Current situation

Currently we have the following working paths:

1) /api/dev/: will generate a calendar, whether General Roman, or a national calendar, or a diocesan calendar, based on params 2) /api/dev/metadata/: will generate the index of all the available calendars and related data 3) /api/dev/testsindex/: will generate the index of all available unit tests 4) /api/dev/allevents/: will generate a collection of all possible liturgical events that go to creating a given calendar (this is NOT the calendar, only the events that may be found in the calendar) 5) /api/dev/regionaldata/: will produce the data for a given national or diocesan calendar, that is used to generate the calendar; can also create new data / update existing data with PUT / PATCH requests 6) /api/dev/easter/: will generate all the dates of Easter from 1583 to 9999

New Path schema

Proposed schema moving forward (RFC):

N.B. for the purposes of this API, GET and POST methods are considered equivalent, they will both simply retrieve data, the first through query parameters and the second through the body of the request (which can in turn generally have a Content-Type of either application/x-www-form-urlencoded, application/json, or application/yml)

_A green checkmark :heavy_check_mark: will be placed next to the routes that have been implemented in the temporary v9 branch; those that are a work in progress will have a red exclamation point :heavy_exclamationmark:

Calendars (GET, POST) :heavy_check_mark:

This is the true perpetual calendar endpoint, it will retrieve the actual calculated liturgical calendar for a given year

1) /api/dev/calendars/: will generate the index of all the available calendars and related data 2) /api/dev/calendar/{YEAR}/: will generate the General Roman Calendar (aka Universal) for the year {YEAR} (if year is omitted, will default to the current year) 3) /api/dev/calendar/nation/{NATION}/{YEAR}/: will generate the national calendar for {NATION} for the year {YEAR} (if year is omitted, will default to the current year) 4) /api/dev/calendar/diocese/{DIOCESE}/{YEAR}/: will generate the diocesan calendar for {DIOCESE} for the year {YEAR} (if year is omitted, will default to the current year)

TODO: consider the possibility of adding other rites, such as the Ambrosian rite or Eastern Catholic rites such as Ruthenian or Melchite / Greek Catholic... How to handle these on the path? We would need a fuller understanding of how different the calendars are compared to the Roman Rite, for example do they follow the Gregorian date of Easter or the Julian date of Easter; are they adaptable at a local level; etc.

Roman Missals (GET, POST, PUT, PATCH, DELETE) :heavy_exclamation_mark:

5) /api/dev/missals/: will get the index of all Roman Missals for which data has been defined in the API 6) /api/dev/missal/{YEAR}: will get / update / create / delete sanctorale data for the Latin Roman Missal published in the year {YEAR} (if {YEAR} is omitted will get an array of all Latin Roman Missals published since 1969) 7) /api/dev/missal/nation/{NATION}/{YEAR}: will get / update / create / delete sanctorale data for the Missal of the nation {NATION} published in the year {YEAR} (if {YEAR} is omitted will get an array of all Missals for the given {NATION} published since 1969)

Decrees of the Congregation for Divine Worship (GET, POST, PUT, PATCH, DELETE) :heavy_exclamation_mark:

8) /api/dev/decrees/: will get the data of Decrees of the Congregation for Divine Worship that add new festivities, or resolve coincidences between festivities; or create a new decree if one is issued (we shouldn't really have to update anything, but let's say a mistake was made when creating a new decree, perhaps we can allow to PATCH it; DELETE shouldn't really be needed here)

Calendar data (GET, POST, PUT, PATCH, DELETE) :heavy_check_mark:

This is data that goes to generating a National or Diocesan calendar, that cannot be handled in the Missals data; generally consists of particular operations, or liturgical events that have had changes since a Missal was published...

9) /api/dev/data/: will get the index of all data files that have been defined for national or diocesan calendars 10) /api/dev/data/nation/{NATION}/: will get / update / create / delete the data that is used to generate the national calendar for {NATION} (only data that will modify the sanctorale data from the relative Missal for the nation, or add new festivities for a given year that were not in the Missal, or move festivities etc.) 11) /api/dev/data/diocese/{DIOCESE}: will get / update / create / delete the data that is used to generate the diocesan calendar for {DIOCESE} 12) /api/dev/data/widerregion/{WIDERREGION}: will get / update / create / delete the data that is used for the Wider Region that certain nations may belong to (e.g. "Europe" or "Americas"; this data will be included in the generation of a national calendar that belongs to the given Wider Region)

N.B. As regards DELETE requests:

  • {WIDERREGION} data cannot be deleted as long as there are National calendars that depend on it
  • {NATION} data cannot be deleted as long as there are Diocesan calendars that depend on it.

Dates of Easter (GET, POST) :heavy_check_mark:

13) /api/dev/easter/: will generate all the dates of Easter from 1583 to 9999

Liturgical events (GET, POST) :heavy_check_mark:

14) /api/dev/events/: will generate a collection of all possible liturgical events that go to creating the General Roman Calendar, whatever the year 15) /api/dev/events/nation/{NATION}/: will generate a collection of all possible liturgical events that go to creating the national calendar for {NATION}, whatever the year 16) /api/dev/events/diocese/{DIOCESE}: will generate a collection of all possible liturgical events that go to creating the diocesan calendar for {DIOCESE}, whatever the year

Unit Tests (GET, POST, PUT, PATCH, DELETE) :heavy_check_mark:

17) /api/dev/tests/: will generate the index of all available unit tests 18) /api/dev/test/{TEST}/: will get an existing test by ID, or create a new test / update / delete an existing test by ID

Please feel free to ask questions or contribute with ideas for better resource paths!

mkasberg commented 5 months ago

A few minor thoughts, take 'em or leave 'em.

Overall this looks great to me, I do like the new API schema better than the old one.

JohnRDOrazio commented 5 months ago

I agree with events in place of allevents.

As for singular or plural in the routes, I suppose you may be referring to Ruby on Rails, where often the resources will maintain the plural form, such as GET /photos/:id. However there can be cases where a singular form can be considered preferable: https://guides.rubyonrails.org/routing.html#singular-resources

"Sometimes, you have a resource that clients always look up without referencing an ID"

I figure, the base calendar is the General Roman Calendar. When retrieving a calendar resource you will always only retrieve a single calendar resource, and the "Calendar of calendars" is the General Roman Calendar which I'm thinking of making accessible simply at the path /api/dev/calendar/ rather than /api/dev/calendar/generalroman/. I don't know, I'll have to think about that, but I like the idea of hierarchy here: just plain /calendar/ is the General Roman calendar, any calendar underneath that will inherit from that.

Another question that I'm not sure how to deal with, is calendars for different rites. For example, here in Italy in the area around Milan, they use the "Ambrosian calendar", which I personally know nothing about. I'll need to find a liturgist from Milan who's available to explain it to me sooner or later. While the General Roman Calendar is defined in the Latin edition of the Roman Missal, how is the Ambrosian calendar defined? How similar or different is it from the General Roman Calendar? Can it be considered as inheriting from the General Roman Calendar? Could it be considered as a local / diocesan calendar?

What about other rites, such as the Melchite (Greek catholic) rite, or the Ruthenian catholic rite... Do they each have their own calendar? Do all eastern catholic rites inherit from a single calendar such as the "liturgy of John Chrysostom"? Since these rites are widespread over more than one country, I don't think they can be simply treated as "diocesan calendars", and I have no idea if they should descend hierarchically from the General Roman Calendar or if they are different enough that they should be treated in parallel to the General Roman Calendar. If they need to be treated in parallel, then we might have something like this:

In any case, I'm not very strongly opinionated about singular or plural. In a Ruby on Rails environment, you could use plural almost everywhere such that GET /calendars would be the index resource, and GET /calendars/:id would get a singular resource. If however, GET /calendars alone is the index resource with data about all available calendars, we might want to stick to GET /calendar for the General Roman Calendar; and consequently all other calendars that inherit from the General Roman would be under the same /calendar path. I personally kind of prefer to have the plural for the index, and the singular for a singular resource.

As for nation vs national, doesn't make much of a difference to me, I guess it's kind of where you put the meaning, if it's intended as an adjective referred to the calendar resource so (/calendar/national) would mean a national calendar as opposed to the General Roman Calendar; or if it's referring more to what comes immediately after, as in saying "which NATION do you want a calendar for? /nation/USA", or "which DIOCESE do you want a calendar for? /diocese/DIOCESEOFMANCHESTERNEWHAMPSHIRE". So /api/dev/calendar/nation/USA basically can be read as "Get the liturgical calendar for the nation USA".

When it comes to liturgical celebration, the calendar for the local diocese is always used (or for the religious congregation; the Franciscans have their own specific calendar, the Dominicans have their own specific calendar... That's something else to think of, how should calendars for religious communities be dealt with in a project that would like to become as much of a service as possible throughout the Church). In any case, you wouldn't really use a "national calendar" in a liturgical celebration. However the "national calendar" determines the diocesan calendar: all the dioceses of a given nation will inherit the calendar from the Roman Missal language edition for the nation in which the diocese is situated. I wouldn't even say that it's necessarily known or called a "national" calendar (that sounds kind of patriotic, so has almost more of a political nuance to it), it's simply the calendar as defined by the Bishops Conference for a given nation based on the language edition of the Roman Missal in that nation.

If we really wanted to respect the hierarchy of calendar data, /diocese should come under /nation, but that just might simply become too long of a path: /calendar/nation/NETHERLANDS/diocese/ROTTERDAM/{YEAR} starts to get a bit long. But that's kind of the idea in using nation or diocese: we're requesting the calendar as in use in the diocese nnn. It wouldn't quite work to do /calendar/national/NETHERLANDS/diocesan/ROTTERDAM/{YEAR}. But instead of creating paths that are too long, I think we can treat nation and diocese in parallel:

Only thing that will need some attention in this case, is avoiding conflicts between names of Dioceses. If more than one diocese throughout the world has the same name, more specificity will need to be added to the key that identifies one of these dioceses. For example, DIOCESISDECARTAGENA_ES and DIOCESISDECARTAGENA_CO to distinguish the diocese of Cartagena in Spain from the diocese of the same name in Colombia.

JohnRDOrazio commented 5 months ago

Starting working on this on the v9 branch. This branch has nothing to do with a "version 9", it's simply a placeholder since I have to use a value of v4 through v9 in order for the routing to work; the branch will be merged into dev when it is completed, tested and functional. And dev will probably become v4 at that point.

So will be testing routes at the address: https://litcal.johnromanodorazio.com/api/v9/ .

I have currently implemented the events endpoint, you can see it and play with it at https://litcal.johnromanodorazio.com/api/v9/events.

The locale param is available on the path https://litcal.johnromanodorazio.com/api/v9/events for the General Roman Calendar events:

You can also set the desired locale in the 'Accept-Language' header. Try in the devtools console (you will have to be on a page within the https://litcal.johnromanodorazio.com or https://litcal-staging.johnromanodorazio.com domains):

fetch('https://litcal.johnromanodorazio.com/api/v9/events', { headers: {'Accept-Language': 'nl'} })
  .then(response => response.json())
  .then(data => console.log(data));

You can also request a response content type of either application/json or application/yaml:

fetch('https://litcal.johnromanodorazio.com/api/v9/events', { headers: { 'Accept': 'application/yaml' } })
  .then(response => response.blob())
  .then(blob => blob.text())
  .then(data => console.log(data));

You can also try invalid paths or parameters to see how the API responds to invalid data.

JohnRDOrazio commented 5 months ago

I suppose another way of referring to the calendar for a given country, would be to refer to a Roman Missal. So rather than call it a "national calendar", seeing that the calendar in question is produced based on an edition of the Roman Missal as published in a certain country by the Bishops Conference (with the approval of the Congregation for Divine Worship), it could be referred to by the Missal, such as: /calendar/missal/USA in place of /calendar/nation/USA. Though this might be more correct in indicating where the data is coming from, I'm afraid it might be slightly less intuitive than simply referring to the geographical area as in /calendar/nation/USA. Where and when would the so called "national" calendar be used? It could be used to print a liturgical calendar that is distributed nation-wide, for example here in Italy Paulist Press distributes the liturgical calendar in Italian nation-wide. So there are no diocesan memorials in this printed calendar, only those that regard Italy (and consequently the wider region Europe). I suppose it could also be used on the website for the Bishops Conference. And it could be used for an smartphone app distributed on a nation-wide level, or for an Alexa skill distributed on a nation-wide level. I would envision a smartphone app distributed on a nation-wide level with the choice of all dioceses within the nation. Perhaps in the future we'll get to the point where each diocese could distribute it's own app, but I don't see that happening in the near future. It would be quite simple having the API and an example app on hand, but you'll probably only find a handfew of dioceses taking interest in producing and publishing the app. Same for an Alexa or Google Assistant skill.

JohnRDOrazio commented 5 months ago

I'm not going to use /calendar/missal/{NATION} as a path parameter to retrieve a calendar, I'm going to stick with /calendar/nation/{NATION}, because I think it might get confusing seeing that I'm working on another /missals / /missal path to retrieve or set Roman Missal sanctorale data for various nations. I'll update the proposed path schema above with the latest developments.