diff --git a/Layout/default/Pop/Form.php b/Layout/default/Pop/Form.php
index b3e71457d..106fb8c87 100644
--- a/Layout/default/Pop/Form.php
+++ b/Layout/default/Pop/Form.php
@@ -117,8 +117,47 @@ if (isset($_GET['returnto']) && $_GET['returnto'] == "pop-detail") {
+
+
@@ -280,6 +294,32 @@ if (isset($_GET['returnto']) && $_GET['returnto'] == "pop-detail") {
});
+ // combined address search with select2
+ $('#address_search').select2({
+ placeholder: 'Straße Hausnummer, PLZ Ort eingeben...',
+ allowClear: true,
+ minimumInputLength: 2,
+ ajax: {
+ url: "=self::getUrl('Pop','api')?>",
+ dataType: 'json',
+ delay: 300,
+ data: function(params) { return { do: 'searchAddress', q: params.term }; },
+ processResults: function(data) { return { results: data.results || [] }; }
+ }
+ });
+
+ $('#address_search').on('select2:select', function(e) {
+ var d = e.params.data;
+ $('#street').val(d.street || '');
+ $('#number').val(d.number || '');
+ $('#zip').val(d.zip || '');
+ $('#city').val(d.city || '');
+ });
+
+ $('#address_search').on('select2:clear', function() {
+ $('#street, #number, #zip, #city').val('');
+ });
+
// network_id // owner_id
// if get parameter network_id is set, select it if found
const urlParams = new URLSearchParams(window.location.search);
diff --git a/application/Pop/PopController.php b/application/Pop/PopController.php
index 49b5f8ffc..fec304094 100644
--- a/application/Pop/PopController.php
+++ b/application/Pop/PopController.php
@@ -56,6 +56,7 @@ class PopController extends mfBaseController
"city" => $pop->city,
"street" => $pop->street,
"number" => $pop->number,
+ "address" => trim($pop->street . ' ' . $pop->number . ', ' . $pop->zip . ' ' . $pop->city, ', '),
"state" => $pop->state,
"folder_link" => $pop->folder_link,
"doku_date" => $pop->doku_date,
@@ -1411,6 +1412,8 @@ class PopController extends mfBaseController
case "getSplicePlanForElement":
return $this->getSplicePlanForElementAction();
break;
+ case "searchAddress":
+ return $this->searchAddressApi();
default:
$return = false;
}
@@ -1965,4 +1968,97 @@ class PopController extends mfBaseController
'connections' => $result
]));
}
+
+ private function searchAddressApi()
+ {
+ $q = trim($this->request->q);
+ if (strlen($q) < 2) {
+ $this->returnJson(["results" => []]);
+ }
+
+ $db = FronkDB::singleton(ADDRESSDB_DBHOST, ADDRESSDB_DBUSER, ADDRESSDB_DBPASS, ADDRESSDB_DBNAME);
+
+ // split input into parts, any order allowed: "graz alte 5" or "Alte Poststraße 5, 8010 Graz"
+ $parts = preg_split('/[\s,]+/', $q, -1, PREG_SPLIT_NO_EMPTY);
+
+ // categorize: 4-digit = PLZ, short number = hausnummer, text = street or city
+ $text_parts = [];
+ $hausnummer = null;
+ $plz = null;
+
+ foreach ($parts as $part) {
+ if (preg_match('/^\d{4}$/', $part)) {
+ $plz = $part;
+ } elseif ($hausnummer === null && preg_match('/^\d+[a-zA-Z]?$/', $part)) {
+ $hausnummer = $part;
+ } else {
+ $text_parts[] = $part;
+ }
+ }
+
+ // Pre-query Gemeinde (tiny table, instant) to resolve text→gemeinde_id
+ $gemeinde_ids_per_part = [];
+ foreach ($text_parts as $tp) {
+ $escaped = $db->escape($tp);
+ $gres = $db->query("SELECT id FROM Gemeinde WHERE name LIKE '%$escaped%'");
+ $ids = [];
+ if ($gres && $db->num_rows($gres)) {
+ while ($grow = $db->fetch_object($gres)) {
+ $ids[] = (int)$grow->id;
+ }
+ }
+ $gemeinde_ids_per_part[$tp] = $ids;
+ }
+
+ // Build conditions: text parts match Strasse.name OR pre-resolved gemeinde_id (uses index)
+ $conditions = [];
+ foreach ($text_parts as $tp) {
+ $escaped = $db->escape($tp);
+ if (!empty($gemeinde_ids_per_part[$tp])) {
+ $ids_str = implode(',', $gemeinde_ids_per_part[$tp]);
+ $conditions[] = "(Strasse.name LIKE '%$escaped%' OR Strasse.gemeinde_id IN ($ids_str))";
+ } else {
+ $conditions[] = "Strasse.name LIKE '%$escaped%'";
+ }
+ }
+ if ($hausnummer !== null) {
+ $hn = $db->escape($hausnummer);
+ $conditions[] = "Hausnummer.hausnummer LIKE '$hn%'";
+ }
+ if ($plz !== null) {
+ $pz = $db->escape($plz);
+ $conditions[] = "Plz.plzstring LIKE '$pz%'";
+ }
+
+ $where = count($conditions) ? implode(' AND ', $conditions) : '1=0';
+
+ $sql = "SELECT Strasse.name as strasse, Hausnummer.hausnummer, Plz.plz, Gemeinde.name as gemeinde
+ FROM Strasse
+ STRAIGHT_JOIN Hausnummer ON (Hausnummer.strasse_id = Strasse.id)
+ LEFT JOIN Plz ON (Plz.id = Hausnummer.plz_id)
+ LEFT JOIN Gemeinde ON (Gemeinde.id = Strasse.gemeinde_id)
+ WHERE $where
+ GROUP BY Strasse.name, Hausnummer.hausnummer, Plz.plz, Gemeinde.name
+ ORDER BY Strasse.name, Hausnummer.hausnummer + 0, Plz.plz
+ LIMIT 25";
+ $results = [];
+ $res = $db->query($sql);
+ if ($db->num_rows($res)) {
+ while ($row = $db->fetch_object($res)) {
+ $text = $row->strasse;
+ if ($row->hausnummer) $text .= ' ' . $row->hausnummer;
+ if ($row->plz || $row->gemeinde) $text .= ', ' . trim($row->plz . ' ' . $row->gemeinde);
+ $results[] = [
+ "id" => $text,
+ "text" => $text,
+ "street" => $row->strasse,
+ "number" => $row->hausnummer,
+ "zip" => $row->plz,
+ "city" => $row->gemeinde,
+ ];
+ }
+ }
+
+ $this->returnJson(["results" => $results]);
+ }
}
\ No newline at end of file