---
title: "Important: The map leaves out partners without coordinates"
manual: "Academic Partners"
version: "main"
source: "Changelog/3.0/Important-PartnerMapSkipsPartnersWithoutCoordinates.rst"
modified: "2026-09-17T07:34:13+00:00"
---

# Important: The map leaves out partners without coordinates

## Description

`Controller\PartnerController::mapAction()` fed the map from
`Domain\Repository\PartnerRepository::findByDemand()`, which carries no
geocode constraint. A partner page that was never geocoded - or whose geocoding
failed - therefore reached the map template, and `\Domain\Model\Partner`
types both coordinates as non-nullable `float` defaulting to `0`:

```php
protected float $geocodeLongitude = 0;
protected float $geocodeLatitude = 0;
```

So a missing coordinate arrived in the template as a perfectly valid one:

```html
<li class="map-partner" data-lat="0" data-lng="0" …>
```

`Resources/Private/TypeScript/frontend/map.ts` guarded the values with
`Number.isNaN()`, which `0` passes, and the marker was drawn at 0/0 - open
ocean south of Ghana. The guard could not catch an empty attribute either,
because `Number('')` is `0` and not `NaN`.

The map query now requires both coordinates, and the frontend module refuses to
draw a record whose coordinates it cannot use. A partner without coordinates
stays in the **list**, which is unchanged: it is still a perfectly good list
entry.

Absence is the criterion, not the value. `NULL` and the empty string mean "no
coordinate"; a stored `0` is a real one, and only the pair `0/0` is refused.
Longitude 0 runs through the United Kingdom, France, Spain and Ghana and
latitude 0 is the equator, so treating a single zero as missing would hide
partners that are genuinely there.

The two coordinate columns became `allowLanguageSynchronization`. A place
does not move when the page is translated, so a translation follows its default
record instead of carrying a coordinate of its own. A partner translated before
geocoding ran kept an empty coordinate and was therefore drawn at 0/0 in that
language - and, under the rule above, would have been left off that language's
map entirely.

`Domain\Repository\PartnerRepository::findGeoLocated()` gained the same
requirement, so a record that claims a `successful` or `manually` status without
ever having received coordinates is no longer reported as located.

## Impact

A partner that was previously drawn at 0/0 disappears from the map. That marker
never pointed at the partner's location, so nothing that pointed anywhere is
lost.

When no partner has coordinates at all, the plugin no longer renders an empty
map centred on Germany. It renders a message instead:

```text
No partner with a location to show on the map.
```

The label is `map.noLocatedPartnersFound` in
`Resources/Private/Language/locallang.xlf` and can be overridden like any
other label. Integrators who replaced
`Resources/Private/Templates/Partner/Map.html` keep their own copy and get
neither the condition nor the message.

A template that draws the map for **one** partner is not covered by any of this.
The typical case is a partner detail page that renders the partner's own
location: it has no query to constrain, and the list it hands to the map holds
that single partner whether it has coordinates or not. Such a template draws the
partner at 0/0, or - with the module above - an empty map centred on Germany.

`Domain\Model\Partner::isDrawable()` is the same rule for a single object.
Guard the map with it:

**EXT:my_sitepackage/Resources/Private/Templates/Pages/AcademicPartner.html**

```html
<f:if condition="{partner.drawable}">
    <f:render partial="Partner/Map" arguments="{partners: '{0: partner}'}" />
</f:if>
```

`Partner/Map` stands for the site package's own map partial: this extension
ships the map only as the plugin template, not as a partial.

It is deliberately not called "geo located":
`Domain\Repository\PartnerRepository::findGeoLocated()` also requires a
geocode *status*, and a record can claim to be located without carrying a
coordinate. Like the frontend module it also refuses a coordinate that is not a
finite number.

The model does not see exactly what the query sees, in either direction. An
absent coordinate has already become `0` by the time a template asks, so a pair
with only one coordinate missing reads as drawable at 0 on that axis while the
query excludes it; a hand-entered `0.0` is refused by the model while the query
lets it through. ACE-566 changes the column type and is where the two are
reconciled.

A custom controller that calls
`Domain\Repository\PartnerRepository::findByDemand()` itself gets the old
behaviour unless it opts in, because the demand defaults to `false`:

```php
$demand->setDrawableOnly(true);
```

The server-side rule matches the pair `0/0` as a **string**, in the spelling
`\Command\GeocodeCommand` writes. A hand-entered `0.0` therefore passes the
query and is dropped by the frontend module instead. A numeric comparison cannot
be expressed portably while the column is `VARCHAR`; ACE-566 changes the column
type and removes that asymmetry.

`\Command\GeocodeCommand` writes its result through the DataHandler now
instead of the repository. Only a DataHandler write runs
`\DataHandling\Localization\DataMapProcessor`, and geocoding is the one
path that actually writes coordinates - persisting through Extbase would reach
the default record and leave every translation behind, which is the defect one
level down.

Language synchronization takes effect when a record is saved, so it cannot
repair what is already stored. The upgrade wizard
`academicPartners_synchronizePartnerCoordinates` copies each partner's
coordinates onto its translations once. Run it after updating; a site with
translated partner pages needs it, and a site without translations does not.
Deleted translations and workspace versions are left alone, and so is a
coordinate an editor detached from its default record on purpose.

A workspace draft created *before* the update keeps its own stale coordinate:
the wizard does not touch drafts, so publishing such a draft after the update
re-introduces the empty value for that record. Re-saving it in the workspace is
enough to bring it back in line.

## Affected Installations

Every installation rendering the **Partners Map** plugin whose partner
records are not all geocoded, and every installation with translated partner
pages. Installations where every partner has coordinates see no change.

Installations whose own templates draw a map for a single partner - most often
a partner detail page - need to add the `isDrawable()` guard shown above;
this extension's own page template renders no map.
