source: trunk/mapbender/http/nav/alkisnav_adr.php @ 413

Revision 413, 15.1 KB checked in by frank.jaeger, 5 years ago (diff)

Umstellung Suche (nav) auf Full-Schema, Nachkorrektur Auskunft.

Line 
1<?php
2/*      Navigation mit ALKIS-Daten im Mapbender 2 - Teil Adressen-Suche
3        Datenbank-Struktur aus dem norGIS-ALKIS-Importer.
4Version vom
5        2016-02-11 Version fÃŒr norGIS-ALKIS-Import aus Version Classic abgeleitet.
6        2016-03-02 $gemeinde auf feste LÀnge korrigieren
7        2016-11-28 Gemeinsam genutzte Datenbanken ermöglichen
8        2018-02-15 Strikte Input-Validation der Parameter
9        2018-11-12 Full-Schema
10ToDo:
11        -       Gruppierung (mit Zeile) der Straßenliste nach Gemeinde
12        -       Eingabe aus "Balken" von Buchauskunft "Lage" zulassen: Numerisch: Gem-Str-Haus-lfd
13                -- lfd (NebengebÀude) als Untergliederung der geklickten Haus-Nr anzeigen
14                Analog zur Zerlegung des FS-Kennz in _fls
15        -       Mouse-Over in Straßenliste soll Position zeigen.
16                Dazu in der DB eine Tabelle mit Koordinate zum StraßenschlÃŒssel aufbauen.
17*/
18
19$cntget = extract($_GET);
20
21// Input-Validation
22// Parameter aus Konfiguration oder Links sollten keine "Eingabefehler" enthalten.
23// Entweder falsche Konfiguration oder Hack. Programm sofort abbrechen.
24if (!isset($gkz) or !preg_match('#^[0-9]{3}$#', $gkz)) {die("Eingabefehler gkz");} // Mandant, muss!
25
26if(isset($epsg)) { // SRS, kann. Wenn als Parameter ...
27        if (preg_match('#^EPSG:[0-9]{4,5}$#', $epsg)) { // Prefix aus MB-Mapframe
28                $epsg = str_replace("EPSG:", "" , $epsg);
29        } elseif (!preg_match('#^[0-9]{4,5}$#', $epsg)) { // nur die Nummer
30                die("Eingabefehler epsg");
31        }
32} else { // Nichts ÃŒbergeben
33        $epsg=$gui_epsg; // dann default aus Conf
34}
35
36// Filter-Parameter fÃŒr Gemeindenummer in Kreis-Datenbank aus der Mapbender GUI-Konfiguration
37if (isset($gemeinde) AND trim($gemeinde, '0') != "") {
38        if (!preg_match('#^[0-9]{1,3}$#', $gemeinde)) {die("Eingabefehler Gemeinde");}
39        $gemeinde=str_pad($gemeinde, 3, "0", STR_PAD_LEFT);
40        if(strpos($gemeinde, ",") === false) {
41                $gfilter = 1; // Einzelwert
42        } else {
43                $gfilter = 2; // Liste
44        }
45} else { // Kein Filter
46        $gemeinde = "";
47        $gfilter = 0;
48}
49// // http://skrzmaptest01.asp.krzwan.de/mapbender/nav/alkisnav_adr.php?gkz=210&gemeinde=004&epsg=25832&str_schl=0575800401798
50if (isset($str_schl) ) {
51        if (!preg_match('#^[0-9]{4,13}$#', $str_schl)) {die("Eingabefehler Stra&zlig;enschl&uuml;ssel");}
52} else {
53        $str_schl="";
54}
55
56include("../../conf/alkisnav_conf.php");
57include("alkisnav_fkt.php"); // Funktionen
58$con = pg_connect ($dbconn) or die ("Fehler bei der Verbindung zur Datenbank ".$dbpre.$dbgkz);
59
60echo <<<END
61<!doctype html>
62<html lang="de">
63<head>
64        <meta http-equiv="cache-control" content="no-cache">
65        <meta http-equiv="pragma" content="no-cache">
66        <meta http-equiv="expires" content="0">
67        <meta charset="utf-8">
68        <title>ALKIS-Suche Adressen</title>
69        <link rel="stylesheet" type="text/css" href="alkisnav.css">
70        <script type='text/javascript'>
71                function transtitle (trans) { // Titel der letzten Transaktion anzeigen
72                        document.getElementById('transaktiontitle').innerHTML = trans;
73                }
74                function imFenster(dieURL) {
75                        var link = encodeURI(dieURL);
76                        window.open(link,'','left=10,top=10,width=620,height=800,resizable=yes,menubar=no,toolbar=no,location=no,status=no,scrollbars=yes');
77                }
78        </script>
79</head>
80<body>
81<a href='javascript:history.back()'>
82        <img src="ico/zurueck.png" width="16" height="16" alt="&lt;&lt;" title="zur&uuml;ck">
83</a>&nbsp;
84<span title='zuletzt ausgef&uuml;hrte Aktion'>
85        <dfn class='title' id='transaktiontitle'></dfn>
86</span>
87
88END;
89
90function suchStrName() {
91        // Strassen nach Name(-nsanfang)
92        global $street, $scalestr, $str_schl, $gkz, $gemeinde, $epsg, $gfilter, $debug, $auskpath;
93        //if ($debug > 1) {echo "<p class='dbg'>function suchStrName()<p>";} // Ablauf-Verfolgung
94
95        $linelimit=120;  // -> in Conf?
96        $str_schl=""; // Loeschen vorh. Ergebnis
97        preg_match("/^(\D+)(\d*)(\D*)/",$street,$matches); # 4 matches name/nr/zusatz
98        //echo "match: 1='".$matches[1]."', 2='".$matches[2]."', 3='".$matches[3]."'";
99        $matches[1] = preg_replace("/strasse/i","str", $matches[1]);
100        $matches[1] = preg_replace("/str\./i","str", $matches[1]);
101
102        if(preg_match("/\*/",$matches[1])){
103                $match=trim(preg_replace("/\*/i","%", strtoupper($matches[1])));
104        } else {
105                $match=trim($matches[1])."%";
106        }
107
108        $sql ="SELECT g.gemeinde, g.bezeichnung AS gemname, k.gml_id, k.bezeichnung, k.schluesselgesamt, k.lage "
109        ."FROM ax_lagebezeichnungkatalogeintrag k "
110        ."JOIN ax_gemeinde g ON k.land=g.land AND k.regierungsbezirk=g.regierungsbezirk AND k.kreis=g.kreis AND k.gemeinde=g.gemeinde "
111        ."WHERE k.bezeichnung ILIKE $1 AND k.endet IS NULL AND g.endet IS NULL ";
112
113        switch ($gfilter) {
114                case 1: // Einzelwert
115                        $sql.="AND k.gemeinde='".$gemeinde."' ";
116                        break;
117                case 2: // Liste
118                        $sql.="AND k.gemeinde in (".str_replace(",", "','", $gemeinde).") ";
119                        break;
120                default: // kein Filter
121                        break;
122        }
123        $sql.="ORDER BY g.bezeichnung, k.bezeichnung, k.lage LIMIT $2 ;";
124        $v=array($match,$linelimit);
125        $res=pg_prepare("", $sql);
126        $res=pg_execute("", $v);
127
128        if (!$res) {
129                echo "\n<p class='err'>Fehler bei Name</p>";
130                if ($debug > 2) {echo "<p class='dbg'>SQL = '".$sql."'<p>";}
131                return;
132        }
133
134        $cnt = 0;
135        $gwgem="";
136        while($row = pg_fetch_array($res)) {
137                $gemname=$row["gemname"];
138                $gemnr=$row["gemeinde"] ;
139                if ($gwgem != $gemname) {
140                        if ($gfilter != 1) {
141                                zeile_gemeinde($gemnr, $gemname, false); // ToDo: aber ohne Link oder Link verarbeiten können
142                        }
143                        $gwgem=$gemname;
144                }
145                $gkey=$row["schluesselgesamt"]; // Land-RegBez-Kreis-Gem-Strasse - fÃŒr weitere Suche
146                $skey=$row["lage"]; // Nur Str.-schl. daraus
147                $kgml=$row["gml_id"]; // ID von Katalog
148                $sname=htmlentities($row["bezeichnung"], ENT_QUOTES, "UTF-8");
149                zeile_strasse ($gkey, $skey, $sname, $kgml, $gemname);
150                $cnt++;
151        }
152
153        if($cnt == 0) {
154                echo "\n<p class='anz'>Keine Stra&szlig;e</p>";
155                //if ($debug > 2) {echo "<p class='err'>SQL = '".$sql."'<br>$1 = '".$match."'<p>";}
156        } elseif($cnt == 1) { // Eindeutig
157                $str_schl=$gkey; // dann gleich weiter
158        } elseif($cnt >= $linelimit) {
159                echo "\n<p class='anz'>".$cnt." Stra&szlig;en ... und weitere</p>";                     
160        } elseif ($cnt > 1) {
161                echo "\n<p class='anz'>".$cnt." Stra&szlig;en</p>";     
162        }
163        return;
164}
165
166function suchStrKey() { // Strassen nach num. Schluessel
167        global $street, $scalestr, $str_schl, $gkz, $gemeinde, $epsg, $gfilter, $debug, $auskpath;
168        //if ($debug > 1) {echo "<p class='dbg'>function suchStrKey()<p>";} // Ablauf-Verfolgung
169        $linelimit=60;
170        if(preg_match("/\*/",$street)) {
171                $match=trim(preg_replace("/\*/i","%",$street));
172                // fuehrende Nullen eingeben oder fuehrende Wildcard
173        } else {
174                $match=str_pad($street, 5, "0", STR_PAD_LEFT); // "Wie eine Zahl" verarbeiten
175        }
176        $sql ="SELECT g.bezeichnung AS gemname, k.gml_id, k.bezeichnung, k.schluesselgesamt, k.lage "
177        ."FROM ax_lagebezeichnungkatalogeintrag as k "
178        ."JOIN ax_gemeinde g ON k.land=g.land AND k.regierungsbezirk=g.regierungsbezirk AND k.kreis=g.kreis AND k.gemeinde=g.gemeinde "
179        ."WHERE k.lage LIKE $1 AND k.endet IS NULL AND g.endet IS NULL ";
180        switch ($gfilter) {
181                case 1: // Einzelwert
182                        $sql.="AND k.gemeinde='".$gemeinde."' ";
183                        break;
184                case 2: // Liste
185                        $sql.="AND k.gemeinde in ('".str_replace(",", "','", $gemeinde)."') ";
186                        break;
187        }
188        $sql.="ORDER BY k.lage, k.bezeichnung LIMIT $2 ;";
189
190        $v=array($match,$linelimit);
191        $res=pg_prepare("", $sql);
192        $res=pg_execute("", $v);
193        if (!$res) {
194                echo "\n<p class='err'>Fehler bei Schl&uuml;ssel</p>";
195                return;
196        }
197        $cnt = 0;
198        while($row = pg_fetch_array($res)) {
199                $sname=htmlentities($row["bezeichnung"], ENT_QUOTES, "UTF-8");         
200                $gkey=$row["schluesselgesamt"];
201                $gemname=htmlentities($row["gemname"], ENT_QUOTES, "UTF-8");
202                $skey=$row["lage"];
203                $kgml=$row["gml_id"]; // ID von Katalog
204                zeile_strasse ($gkey, $skey, $sname, $kgml, $gemname);
205                $cnt++;
206        }
207        if($cnt == 0) {
208                echo "\n<p class='anz'>Keine Stra&szlig;e mit Schl&uuml;ssel ".$match."</p>";
209        } elseif($cnt == 1) { // Eindeutig
210                $str_schl=$gkey; // dann gleich weiter
211        } elseif ($cnt >= $linelimit) {
212                echo "\n<p>".$cnt." Stra&szlig;en ... und weitere</p>";                 
213        } elseif ($cnt > 1) {
214                echo "\n<p class='anz'>".$cnt." Stra&szlig;en</p>";     
215        }       
216        return;
217}
218
219function suchHausZurStr($showParent) { // Haeuser zu einer Strasse
220        global $str_schl, $gkz, $scalestr, $scalehs, $epsg, $gemeinde, $epsg, $gfilter, $debug, $auskpath;
221        //if ($debug > 1) {echo "<p class='dbg'>function suchHausZurStr()<p>";} // Ablauf-Verfolgung
222
223        // Head
224        // Strasse zum Strassenschluessel
225        $sql ="SELECT g.bezeichnung AS gemname, k.gml_id AS kgml, k.bezeichnung, k.land, k.regierungsbezirk, k.kreis, k.gemeinde, k.lage "
226        ."FROM ax_lagebezeichnungkatalogeintrag as k "
227        ."JOIN ax_gemeinde g ON k.land=g.land AND k.regierungsbezirk=g.regierungsbezirk AND k.kreis=g.kreis AND k.gemeinde=g.gemeinde "
228        ."WHERE k.schluesselgesamt = $1 AND k.endet IS NULL AND g.endet IS NULL LIMIT 1";
229
230        $v=array($str_schl);    // Schluessel-Gesamt ..
231        $res=pg_prepare("", $sql);
232        $res=pg_execute("", $v);
233        if (!$res) {
234                echo "\n<p class='err'>Fehler bei Name zum Stra&szlig;enschl&uuml;ssel</p>";
235                if ($debug > 2) {echo "<p class='dbg'>SQL = '".$sql."'<p>";}
236                return;
237        }
238
239        if($row = pg_fetch_array($res)) { // .. gefunden
240                $kgml=$row["kgml"]; // ID aus Katalog
241                $sname=$row["bezeichnung"];
242                $land =$row["land"];    // Einzel-Felder fÃŒr JOIN _lagebezeichnung_
243                $regb =$row["regierungsbezirk"];
244                $kreis=$row["kreis"];
245                $gemnd=$row["gemeinde"];
246                $nr=$row["lage"];
247                $gemname=htmlentities($row["gemname"], ENT_QUOTES, "UTF-8");
248                if ($showParent) {
249                        // EINE Koordinate zur Strasse besorgen
250                        // ax_Flurstueck >zeigtAuf> ax_LagebezeichnungOhneHausnummer
251                        $sqlko ="SELECT ";
252                        if($epsg == "25832") { // Transform nicht notwendig
253                                $sqlko.="st_x(st_Centroid(f.wkb_geometry)) AS x, st_y(st_Centroid(f.wkb_geometry)) AS y ";
254                        } else {
255                                $sqlko.="st_x(st_transform(st_Centroid(f.wkb_geometry), ".$epsg.")) AS x, "
256                                ."st_y(st_transform(st_Centroid(f.wkb_geometry), ".$epsg.")) AS y ";
257                        }
258                        $sqlko.="FROM ax_lagebezeichnungohnehausnummer o JOIN ax_flurstueck f ON o.gml_id=ANY(f.zeigtauf) "
259                        ."WHERE o.land= $1 AND o.regierungsbezirk= $2 AND o.kreis= $3 AND o.gemeinde= $4 AND o.lage= $5 LIMIT 1;"; // die erstbeste Koordinate
260
261                        $v=array($land,$regb,$kreis,$gemnd,$nr);
262                        $resko=pg_prepare("", $sqlko);
263                        $resko=pg_execute("", $v);
264                        if ($resko) {
265                                $rowko=pg_fetch_array($resko);
266                                $x=$rowko["x"];
267                                $y=$rowko["y"];
268                        } else {               
269                                echo "\n<p class='err'>Fehler bei Koordinate zur Stra&szlig;e</p>";
270                        }
271
272                        // "function zeile_strasse()" hier nicht verwendbar. ZusÀtzlicher Map-Link mit Koordinate
273                        // Icon -> Buchnachweis
274                        echo "\n\t<br><a href='javascript:imFenster(\"".$auskpath."alkisstrasse.php?gkz=".$gkz."&amp;gmlid=".$kgml."\")'>";
275                                echo "\n\t\t<img class='nwlink' src='ico/Lage_mit_Haus.png' width='16' height='16' alt='STR' title='Buchauskunft zur Stra&szlig;e'>";
276                        echo "\n\t</a>";
277
278                        if ($x > 0) { // Koord. bekommen?
279                                echo "\n\t<a title='Positionieren 1:".$scalestr."' href='javascript:" // mit Link
280                                                ."transtitle(\"auf Stra&szlig;e positioniert\"); "
281                                                ."parent.parent.parent.mb_repaintScale(\"mapframe1\",".$x.",".$y.",".$scalestr."); "
282                                                ."parent.parent.showHighlight(".$x.",".$y."); "
283                                                ."' " // end href
284                                        ."\n\t\tonmouseover='parent.parent.showHighlight(" .$x. "," .$y. ")' "
285                                        ."\n\t\tonmouseout='parent.parent.hideHighlight()'"
286                                .">\n\t\t".$sname." (".$nr.")\n\t</a>";
287                        } else { // keine Koord. gefunden
288                                echo $sname." (".$nr.")"; // nur Anzeige, ohne Link
289                        }
290                        switch ($gfilter) {
291                                case 0: // Kein Filter
292                                        echo " in ".$gemname;
293                                        break;
294                                case 2: // Liste
295                                        echo " in ".$gemname;
296                                        break;
297                        }                       
298                }
299                echo "\n<hr>";
300
301                // Body
302                // Haeuser zum Strassenschluessel
303                $sql="SELECT min(replace(h.hausnummer,' ','')) AS hsnr, ";
304                if($epsg == "25832") { // Transform nicht notwendig
305                        $sql.="avg (st_x(p.wkb_geometry)) AS x, avg (st_y(p.wkb_geometry)) AS y ";             
306                } else { 
307                        $sql.="avg (st_x(st_transform(p.wkb_geometry,".$epsg."))) AS x, "
308                        ."avg (st_y(st_transform(p.wkb_geometry,".$epsg."))) AS y ";           
309                }
310                $sql.="FROM ap_pto p JOIN ax_lagebezeichnungmithausnummer h ON h.gml_id=ANY(p.dientzurdarstellungvon) "
311                ."WHERE p.art='HNR' AND h.land= $1 AND h.regierungsbezirk= $2 AND h.kreis= $3 AND h.gemeinde= $4 AND h.lage= $5 "
312                ."AND p.endet IS NULL AND h.endet IS NULL "
313                ."GROUP BY lpad(split_part(hausnummer,' ',1), 4, '0'), split_part(hausnummer,' ',2) "
314                ."ORDER BY lpad(split_part(hausnummer,' ',1), 4, '0'), split_part(hausnummer,' ',2);";
315                // Problem: In der Datenbank gibt es mehrere hausnummern-Koordinaten fÃŒr verschiedene
316                // MaßstÀbe der Kartendarstellung
317                // Diese sollten nicht mehrfach gelistet werden. FÃŒr die Positionierung "irgendeine" nehmen.
318                // Lösung: ÃŒber GROUP BY in SQL. Alternative Lösungen wÀren:
319                //  1. Gruppenwechsel bei Abarbeitung des Result
320                //  2. Subquery mit LIMIT 1 statt JOIN
321                //  3. Koordinate aus dem Mittelpunkt der GebÀude-Geometrie verwenden statt aus dem PrÀsentationsobjekt der Hausnummer
322
323                $v=array($land,$regb,$kreis,$gemnd,$nr);
324                $resh=pg_prepare("", $sql);
325                $resh=pg_execute("", $v);
326                if (!$resh) {
327                        echo "\n<p class='err'>Fehler bei H&auml;user zum Stra&szlig;enschl&uuml;ssel</p>";
328                        if ($debug > 2) {echo "<p class='dbg'>SQL='".$sql."'<br>Array=".$v."</p>";}
329                        return;
330                }
331
332                $cnt=0;
333                $count=0;
334                echo "\n<table>";
335                while($rowh = pg_fetch_array($resh)) { // mehrere HsNr je Zeile
336                        if($count == 0) {echo "\n<tr>";}       
337                        $hsnr=$rowh["hsnr"];
338                        $x=$rowh["x"];
339                        $y=$rowh["y"];
340                        echo "\n\t<td class='hsnr'>"
341                                ."<a href='javascript:transtitle(\"auf Haus ".$hsnr." positioniert\"); "
342                                        ."parent.parent.parent.mb_repaintScale(\"mapframe1\",".$x.",".$y.",".$scalehs."); "
343                                        ."parent.parent.showHighlight(".$x.",".$y.");' "
344                                        ."onmouseover='parent.parent.showHighlight(".$x.",".$y.")' "
345                                        ."onmouseout='parent.parent.hideHighlight()"
346                                ."'>".$hsnr."</a>"
347                        ."</td>";
348                        $cnt++;
349                        $count++;
350                        if($count == 7) { // Max. Hausnummern je Zeile (Test: 3stellige HsNr mit Zusatz)
351                                echo "\n</tr>";
352                                $count = 0;
353                        }
354                }
355                if($count > 0) {echo "\n</tr>";}
356                echo "\n</table>";
357                if ($cnt > 1) {
358                        echo "\n<p class='anz'>".$cnt." Hausnummern</p>";
359                }
360        } else {
361                echo "\n<p class='anz'>Keine Stra&szlig;e</p>";
362        }
363        return;
364}
365// ===========
366// Start hier!
367// ===========
368
369// Validation: Eingabefeld aus Formular.
370// Suchbegriff (Straßenname) oder StraßenschlÃŒssel.
371// Hier formatierte Meldung und html-Foot.
372if (isset($street) and $street != "" ) {
373        if (!preg_match('#^[0-9a-zA-ZÀöÌÄÖÜß* -.]{1,25}$#', $street)) {
374                echo "<p class='err'>Eingabe unzul&auml;ssig!</p>";
375                $street="";
376        }
377} else {
378        $street="";
379}
380
381if ($str_schl != "") { // aus Link
382        $trans="Hausnummern zur Stra&szlig;e";
383        suchHausZurStr(true);
384} elseif($street != "") { // Eingabe in Formular
385        if (trim($street, "*,0..9, ") == "") { // Zahl, ggf. mit Wildcard
386                $trans="Suche Stra&szlig;enschl&uuml;ssel \"".$street."\"";
387                suchStrKey();
388        } else { // Name suchen
389                $trans="Suche Stra&szlig;enname \"".$street."*\"";
390                suchStrName();
391        }
392        if($str_schl != "") { // EINdeutiges Ergebnis
393                $trans="1 Stra&szlig;e gefunden, Hausnummern";
394                suchHausZurStr(false);
395        }
396} else {
397        $trans="keine Eingabe";
398}
399
400// Nach Durchlaufen des PHP-Scriptes die zuletzt ausgefÃŒhrte Transaktion
401//  im Kopf des Ergebnisrahmens anzeigen.
402// Dazu die im HTML-Header definierte Javascript-Function benutzen.
403// Alternativ wird auch aus dem Javascript "positionieren Karte" dieser Titel gesetzt.
404echo "
405<script type='text/javascript'>
406        transtitle ('".$trans."') ;
407</script>";
408
409?>
410
411</body>
412</html>
Note: See TracBrowser for help on using the repository browser.