RFC: Geolocation handling for nodes

Motivation

In almost every single project I've worked on in recent years, some kind of address node had to be displayed on a map, so in the background geocoding had to be performed.

Status quo

Since afaik PHP does not have any support for this (like a SPL location model), I've implemented a couple of Flow packages that can take care of the problem in general https://github.com/nezaniel/Nezaniel.GeographicLibrary https://github.com/nezaniel/Nezaniel.GeographicLibrary.GoogleMapsAdapter Now in every Neos project, I aspect into the node persistence process and perform the geocoding if the node is of the respective type and store the result in an invisible property with a proper geolocation ElasticSearch configuration. Works like a charm, but:

Why I consider this un-Neos-y

  1. I seriously want to get rid of that aspect. Not only is it a workaround, it also has no clue whether any of the really interesting address properties have been updated. It simply sends a new geocoding request each time such a node is created or updated, which is not a very desirable behaviour considering request limits (e.g. 2.5k/day with Google Maps at this date).
  2. Editors have no power over the location. While Google Maps is right most of the time, sometimes it isn’t and the editor has no possibility of reviewing the geocoding result in the inspector.
  3. It requires 3rd party packages, although they are my own

Proposition: Teaching geocoding and geolocation handling to Flow / the CR

I think it would be a great addition to the CR to have something like GeoCoordinates as an additional property type, perhaps based on the respective [Schema.org specification](http://schema.org/GeoCoordinates) which then can be used in address node types. A planned extension point could be implemented to do the geocoding on demand, if the CR is not supposed to even take care of such things itself. Neos could then build an inspector editor on top of this. I imagine having an editor where I can drag the location pin around on the map a geocoding adapter provides while also having latitude/longitude input fields that are kept in sync.

Open questions

I'm not sure which package structure would be ideal. Maybe the geolocation property type and geocoding adapter interface should go to the CR. Maybe it should be decoupled similar to the way TYPO3CR.Search is (the adapter structure there was the de-facto blueprint for the GeographicLibrary package structure, btw). I'm open for suggestions here. Maybe as the "domain expert" on CR stuff, you could provide some guidance here, @christianm .
1 Like

I am very hesitant to add that directly to the CR, but I like the idea and see the need for something like this.

Maybe we could talk about the necessary extension points needed to make this possible in an add-on package.
I guess a custon node implementation could already be a way to go. Happy to discuss this. Also with the pull request linked below we have the possibility to relate to any object which should also help.

I think we need to discuss at some point if we rather want to define a set of property types for nodes (like GeoCoordinates) and define interfaces for people to implement them (maybe not even needed) OR if we just allow any object as the change below does and so make it pretty open.

I don’t think this is common enough, it’s rarely something I use in projects, to justify adding it in the core for the team to maintain. Additionally it’s a pretty opinionated topic and can be done in so many different ways.

To me this is a clear external package concern, but it of course needs to be possible as such in a good way.

Not sure why you’re not using the node signals and only request it when the address property actually changes.

And you can easily provide a custom inspector editor using google maps and store the value as an array.

I fail to see the benefit of CR having a GeoCoordinates property type, maybe you can explain further?

1 Like

I tried to see a certain perspective and you could make a point of having the CR predefine possible datatypes for node properties instead of allowing any PHP type. But that’s why I mean in my post. Do we want that? If yes an integrated GeoCoordinates type would make more sense.
I am thinking of contentful for example that predefines possible types for fields (properties for us):
https://www.contentful.com/developers/docs/references/content-management-api/#/reference/content-types

It could, if there’s a benefit from it making it a standard type to help interoperability. Location is the only one Contentful has that Neos doesn’t already have, but as said I fail to see the benefit of it since you can define an array data type that allows for an “object” like {"lat":"52.5018616","lon":"13.4112619"}.

One way to think of it would be to say there would be a benefit to have a predefined format for location, which several location data handlers (inspector editors / service side hooks) could deal with. But that could also easily work without it if people just stick to the same format anyway.

What other data types should be provided? As said I think they need to be very basic/very common and help interoperability to be justified.

1 Like

IMHO that is a whole separate discussion that I would like to have, but just partly belongs here. (The question if we should bedefine data types or not).

Basically I’d suggest to add something like a very basic GeoLocation type (lat / lon) type so we can structure node properties in a better way. This could be done by a separate package that can also provide an inspector editor for this case (e.g. with Google Maps / OpenStreetMap selector). I think we need https://github.com/neos/neos-development-collection/pull/102 merged for that to implement an extensible serialization of node property types.

Regarding the Aspect I’d say that we add a core feature to the CR to subscribe to node property changes (there’s a signal Node::nodeUpdated for that already) and receive some information about changed properties. I think that’s a very generic use case for many transformations and other tasks that should be performed after changing specific node properties.