Admin-Dokumentation: Unterschied zwischen den Versionen

Aus kvwmap
Wechseln zu: Navigation, Suche
(Kapitel für Sicherung und Administration DB zusammengefasst/erweitert)
(Der Generische Layereditor GLE)
 
(190 dazwischenliegende Versionen von 7 Benutzern werden nicht angezeigt)
Zeile 5: Zeile 5:
 
kvwmap setzt unter anderem auf Apache, UMN-MapServer, php-Mapscript, MySQL, Postgres mit PostGIS und OGR auf. <br />
 
kvwmap setzt unter anderem auf Apache, UMN-MapServer, php-Mapscript, MySQL, Postgres mit PostGIS und OGR auf. <br />
 
Dank an dieser Stelle für die Entwicklung und Bereitstellung der genannten Software.
 
Dank an dieser Stelle für die Entwicklung und Bereitstellung der genannten Software.
 +
 +
[[Bild:Uebersicht Architektur.jpg|1100px]]
  
 
Dieses Manual wurde erstellt unter Mitwirkung von
 
Dieses Manual wurde erstellt unter Mitwirkung von
Zeile 25: Zeile 27:
 
Die Dokumentation wird in der jeweils aktuellen Version jedem neuen Versionspaket von kvwmap im Unterordner help hinzugefügt.
 
Die Dokumentation wird in der jeweils aktuellen Version jedem neuen Versionspaket von kvwmap im Unterordner help hinzugefügt.
 
Für die Richtigkeit und Vollständigkeit der folgenden Angaben wird keine Garantie übernommen.
 
Für die Richtigkeit und Vollständigkeit der folgenden Angaben wird keine Garantie übernommen.
 
== Hintergründe für die Entwicklung ==
 
 
Kvwmap ist eine auf den UMN-MapServer aufsetzende Entwicklung zur Erfassung, Verarbeitung, Analyse und Präsentation von raumbezogenen Information. Die Entwicklung besteht aus einer Reihe von PHP-Skripten, einem Schema für eine MySQL-Datenbank zur Speicherung von Benutzerdaten und einem Schema für eine PostgreSQL-Datenbank mit PostGIS Aufsatz zur Speicherung von raumbezogenen Daten. Die Anwendung nutzt PHP-MapScript für den Zugriff auf die Funktionen des UMN-MapServers und die pdf class von R&OS zur Erzeugung von PDF-Dokumenten.
 
  
 
== Funktionalität im Client ==
 
== Funktionalität im Client ==
Zeile 114: Zeile 112:
 
: Mit der Layersuche lassen sich sowohl PostGIS-Layer als auch WFS-Layer durchsuchen. Die Suchfunktion ist generisch. Das heißt, das Suchfenster wird für die jeweiligen zu durchsuchenden Layer automatisch an Hand der vordefinierten Attribute bereitgestellt. Bei WFS-Layern stehen alle Sachattribute, die der WFS anbietet für die Suche zur Verfügung. Bei PostGIS-Layern können die Attribute durchsucht werden, für die der Nutzer mindestens Leserecht hat.
 
: Mit der Layersuche lassen sich sowohl PostGIS-Layer als auch WFS-Layer durchsuchen. Die Suchfunktion ist generisch. Das heißt, das Suchfenster wird für die jeweiligen zu durchsuchenden Layer automatisch an Hand der vordefinierten Attribute bereitgestellt. Bei WFS-Layern stehen alle Sachattribute, die der WFS anbietet für die Suche zur Verfügung. Bei PostGIS-Layern können die Attribute durchsucht werden, für die der Nutzer mindestens Leserecht hat.
 
:[[bild:Layersuche.png]]
 
:[[bild:Layersuche.png]]
 +
 +
=== Merkliste ===
 +
Es gibt die Möglichkeit gefundene Datensätze auf eine Merkliste zu setzen. Für einen einzelnen Datensatz geschieht das in der Sachdatenanzeige über den Button "Datensatz merken" [[Datei:MerklisteEinenDatensatzHinzufuegen.png]]. Mehrere ausgewählte oder alle Datensätze können mit dem Button "merken" [[Datei:MerklisteAlleDatensaetzeHinzufuegen.png]] am Ende der Sachdatenanzeige eines Layers auf die Merkliste gesetzt werden.
 +
 +
Die Anzeige der Merkliste erfolgt über den Anwendungfall "go=Zwischenablage" für den ein Menüpunkt angelegt werden sollte.
 +
 +
Die Merkliste selbst zeigt die Layer und die Anzahl der Objekte pro Layer an.
 +
 +
[[Datei:Merkliste.png]]
 +
 +
Man kann alle Objekte eines Layers von der Liste entfernen oder die gesamte Merkliste leeren. Klickt man auf einen Layernamen oder die Anzahl der Objekte werden die gemerkten Objekte angezeigt. Die gemerkten Objekte haben statt des Button "merken" jetzt den Button "" [[Datei:MerkenEinesDatensatzesLoeschen.png]] . Am Ende der Sachdatenanzeige des Layers erscheint ein Button "" [[Datei:MerkenAllerDatensaetzeLoeschen.png]].
  
 
=== Geo-Namen-Suche ===
 
=== Geo-Namen-Suche ===
Zeile 189: Zeile 198:
 
* In der sog. "'''Query'''" der Layerdefinition muss eine SQL-Abfrage formuliert werden, die die Attribute des Layers sammelt, die in der Fachdatenanzeige eine Rolle spielen sollen.
 
* In der sog. "'''Query'''" der Layerdefinition muss eine SQL-Abfrage formuliert werden, die die Attribute des Layers sammelt, die in der Fachdatenanzeige eine Rolle spielen sollen.
 
* Die sog. "'''Haupttabelle'''" muss oids besitzen (Das Feld wird beim Anlegen oder Speichern eines Layers automatisch gefüllt, wenn es leer ist. Sollte bei einer Layerdefinition über mehrere Tabellen hinweg dort jedoch die falsche Tabelle stehen, kann man den Namen der Haupttabelle von Hand korrigieren.)
 
* Die sog. "'''Haupttabelle'''" muss oids besitzen (Das Feld wird beim Anlegen oder Speichern eines Layers automatisch gefüllt, wenn es leer ist. Sollte bei einer Layerdefinition über mehrere Tabellen hinweg dort jedoch die falsche Tabelle stehen, kann man den Namen der Haupttabelle von Hand korrigieren.)
* Dem Layer darf in der jeweiligen Stelle kein Template zugeordnet sein (mit Ausnahme des Raster-Templates "generic_layer_editor_doc_raster.php", siehe oben)
+
* Dem Layer darf in der jeweiligen Stelle kein [[Admin-Dokumentation#Templates_.28eigene_Snippets.29|Template]] zugeordnet sein (mit Ausnahme des Raster-Templates "generic_layer_editor_doc_raster.php", siehe oben)
  
 
Über den Template-Eintrag lässt sich also steuern, ob für einen Layer der generische Layereditor oder ein Snippet zur Sachdatenanzeige verwendet werden soll.
 
Über den Template-Eintrag lässt sich also steuern, ob für einen Layer der generische Layereditor oder ein Snippet zur Sachdatenanzeige verwendet werden soll.
Zeile 196: Zeile 205:
  
 
Bei der Speicherung der Layerdefinition holt der GLE eine Reihe von Datenbankmerkmalen der jeweiligen Attribute aus der Postgis-DB und verwendet diese in den verschiedenen GLE-Oberflächen (z.B. Constraints, NOT NULL, Defaults etc.).
 
Bei der Speicherung der Layerdefinition holt der GLE eine Reihe von Datenbankmerkmalen der jeweiligen Attribute aus der Postgis-DB und verwendet diese in den verschiedenen GLE-Oberflächen (z.B. Constraints, NOT NULL, Defaults etc.).
 +
 +
Die Einstellungen der Layer für den GLE erfolgen über den Layereditor. Der Layereditor unterteilt sich in die Allgemeinden Einstellungen, Klasseneditor, Style- und Labeleditor, Attributeditor, Stellenzuweisung und Rechteeditor. Man gelangt über die Reiter zu den jeweiligen Einstellungen bzw. Editoren. Je nach Layertyp sind nicht alle Einstellungen / Reiter vorhanden.
 +
 +
[[Bild:Layereditor.png|rand|Layereditor|1200px]]
  
 
====Die Layerattribut-Rechteverwaltung des generischen Layereditors====
 
====Die Layerattribut-Rechteverwaltung des generischen Layereditors====
Zeile 219: Zeile 232:
 
Folgende Formularelementtypen stehen zur Auswahl:
 
Folgende Formularelementtypen stehen zur Auswahl:
  
=====Text=====
+
=====Eingabefeld=====
 
Im generischen Layereditor erscheint ein einzeiliges Eingabefeld.
 
Im generischen Layereditor erscheint ein einzeiliges Eingabefeld.
  
Zeile 255: Zeile 268:
 
:Der String 'neuer Wert' ist in der Funktion natürlich durch eine Variable zu ersetzen, welche den generierten Text enthält.
 
:Der String 'neuer Wert' ist in der Funktion natürlich durch eine Variable zu ersetzen, welche den generierten Text enthält.
  
=====Zahl=====
+
=====Zahl mit Tausendertrennzeichen=====
 
:Dieser Typ kann für numerische Werte verwendet werden. Die Zahlen werden mit einem Punkt als Tausendertrenner und einem Komma als Dezimaltrenner angezeigt (1.234.567,89).
 
:Dieser Typ kann für numerische Werte verwendet werden. Die Zahlen werden mit einem Punkt als Tausendertrenner und einem Komma als Dezimaltrenner angezeigt (1.234.567,89).
  
Zeile 364: Zeile 377:
  
 
:Es besteht auch die Möglichkeit, die Auswahlmöglichkeiten abhängig von der aktuellen Stelle oder dem aktuellen Nutzer zu machen. Dafür kann man im SQL die Schlüsselwörter '''$stelleid''' und '''$userid''' verwenden, welche dann durch die aktuelle Stellen-ID bzw. User-ID ersetzt werden. Dies macht insbesondere dann Sinn, wenn die Auswahlmöglichkeiten auch einem Layer entsprechen und verschiedene Stellen bzw. Nutzer in diesem Layer neue Auswahlmöglichkeiten erfassen können aber jede Stelle bzw. jeder Nutzer nur die eigenen Auswahlmöglichkeiten sehen soll. Wenn in diesem Layer ein Attribut vom Typ [[Admin-Dokumentation#StelleID|StelleID]] oder [[Admin-Dokumentation#NutzerID|NutzerID]] existiert, wodurch jedesmal automatisch die Stellen-ID bzw. Nutzer-ID gespeichert wird, kann diese Spalte dann im Auswahlfeld-SQL zusammen mit dem Schlüsselwort $stelleid oder $userid verwendet werden, um die Auswahlmöglichkeiten auf die Stelle bzw. den Nutzer einzuschränken.
 
:Es besteht auch die Möglichkeit, die Auswahlmöglichkeiten abhängig von der aktuellen Stelle oder dem aktuellen Nutzer zu machen. Dafür kann man im SQL die Schlüsselwörter '''$stelleid''' und '''$userid''' verwenden, welche dann durch die aktuelle Stellen-ID bzw. User-ID ersetzt werden. Dies macht insbesondere dann Sinn, wenn die Auswahlmöglichkeiten auch einem Layer entsprechen und verschiedene Stellen bzw. Nutzer in diesem Layer neue Auswahlmöglichkeiten erfassen können aber jede Stelle bzw. jeder Nutzer nur die eigenen Auswahlmöglichkeiten sehen soll. Wenn in diesem Layer ein Attribut vom Typ [[Admin-Dokumentation#StelleID|StelleID]] oder [[Admin-Dokumentation#NutzerID|NutzerID]] existiert, wodurch jedesmal automatisch die Stellen-ID bzw. Nutzer-ID gespeichert wird, kann diese Spalte dann im Auswahlfeld-SQL zusammen mit dem Schlüsselwort $stelleid oder $userid verwendet werden, um die Auswahlmöglichkeiten auf die Stelle bzw. den Nutzer einzuschränken.
 +
 +
=====Auswahlfeld mit Bild=====
 +
 +
Mit diesem Formularelementtyp wird ein Auswahlfeld erzeugt, welches in jeder Auswahlmöglichkeit ein Bild und einen Ausgabetext anzeigt. Die Definition der Auswahlmöglichkeiten sieht so aus:
 +
select <Ausgabespalte> as output, <Schlüsselspalte> as value, <Bildpfadspalte> as image from <Tabellenname>
 +
Die <Bildpfadspalte> muss den Pfad zu einem Browser-kompatiblen Bildtyp (z.B. jpg, png, gif) enthalten.
  
 
=====Autovervollständigungsfeld=====
 
=====Autovervollständigungsfeld=====
Zeile 395: Zeile 414:
  
 
Gibt man bespielsweise folgende Zeichenfolge ein: "raco a", so würde "racomitrium aquaticum" gefunden werden.
 
Gibt man bespielsweise folgende Zeichenfolge ein: "raco a", so würde "racomitrium aquaticum" gefunden werden.
 +
 +
=====Farbauswahl=====
 +
Hier wird ein Auswahlfeld mit den Farben aus der Tabelle colors angezeigt. Gespeichert werden die RGB-Werte in der Form 123 231 123.
  
 
=====Radiobutton=====
 
=====Radiobutton=====
Zeile 413: Zeile 435:
 
Mit diesem Formularelementtyp lassen sich 2 Layer miteinander verknüpfen. Der Benutzer kann in kvwmap über einen Link, der in einem Layer erscheint, direkt in einen zweiten Layer "springen", der Daten enthält, die in Abhängigkeit zum ersten Layer stehen. Das "PK" steht für '''Primärschlüssel''' und damit für die Art der Verknüpfung.  
 
Mit diesem Formularelementtyp lassen sich 2 Layer miteinander verknüpfen. Der Benutzer kann in kvwmap über einen Link, der in einem Layer erscheint, direkt in einen zweiten Layer "springen", der Daten enthält, die in Abhängigkeit zum ersten Layer stehen. Das "PK" steht für '''Primärschlüssel''' und damit für die Art der Verknüpfung.  
  
:''Beispiel'': Man hat einen ersten Layer 'Verpachtungen' und einen zweiten Layer 'verpachtete Flurstücke'. Beide Layer bilden eine '''1:n Beziehung''', d.h. eine Verpachtung kann mehrere Flurstücke haben, ein verpachtetes Flurstück ist aber immer genau einer Verpachtung zugeordnet.
+
:''Beispiel'': Man hat einen ERSTEN Layer 'Verpachtungen' und einen ZWEITEN Layer 'verpachtete Flurstücke'. Beide Layer bilden eine '''1:n Beziehung''', d.h. eine Verpachtung kann mehrere Flurstücke haben, ein verpachtetes Flurstück ist aber immer genau einer Verpachtung zugeordnet. Der zweite Layer wird auch "Subform-Layer" genannt.
 
   
 
   
  
Zeile 422: Zeile 444:
  
 
Um 2 Layer über SubformPK auf diese Weise zu verknüpfen, müssen folgende Voraussetzungen erfüllt sein:
 
Um 2 Layer über SubformPK auf diese Weise zu verknüpfen, müssen folgende Voraussetzungen erfüllt sein:
:* Der erste Layer muss einen eindeutigen Identifikator besitzen),
+
:* Der ERSTE Layer muss einen eindeutigen Identifikator besitzen,
:* Der zweite Layer muss ein Attribut besitzen, welches genau so heißt wie der eindeutige Identifikator des ersten Layers,
+
:* Der ZWEITE Layer muss ein Attribut besitzen, welches genau so heißt wie der eindeutige Identifikator des ersten Layers,
:* Außerdem muss in der Query des ersten Layers ein Attribut definiert werden, welches die Verlinkung zum zweiten Layer herstellt. Der Wert dieses Attributs erscheint als Link und dient als "Vorschau" auf die entsprechenden Datensätze des zweiten Layers.  
+
:* Außerdem muss in der Query des ERSTEN Layers ein Attribut definiert werden, welches die Verlinkung zum ZWEITEN Layer herstellt. Der Wert dieses Attributs erscheint als Link und dient als "Vorschau" auf die entsprechenden Datensätze des ZWEITEN Layers.  
  
 
:''Beispiel'': Der zweiten Layer 'verpachtete Flurstücke' enthält ein Attribut "flurstueckskennzeichen", das als Vorschau herangezogen werden kann.
 
:''Beispiel'': Der zweiten Layer 'verpachtete Flurstücke' enthält ein Attribut "flurstueckskennzeichen", das als Vorschau herangezogen werden kann.
  
:* Für den ersten Layer muss im Attributeditor beim Vorschau-Attribut als Typ 'SubformPK' ausgewählt werden. Im Feld Optionen wird die Layer-ID des zweiten Layers eingetragen und, durch Komma getrennt, der eindeutige Identifikator. (Primärschlüsselattribut) des ersten Layers.
+
:* Für den ERSTEN Layer muss im Attributeditor beim Vorschau-Attribut als Typ 'SubformPK' ausgewählt werden. Im Feld Optionen wird die Layer-ID des ZWEITEN Layers eingetragen und, durch Komma getrennt, der eindeutige Identifikator (das Primärschlüsselattribut) des ERSTEN Layers.
  
 
:''Beispiel'': "152,lfdnr"
 
:''Beispiel'': "152,lfdnr"
Zeile 435: Zeile 457:
  
 
:''Beispiel'': "152,lfdnr,gemkgschl,flur,flurstkennz"
 
:''Beispiel'': "152,lfdnr,gemkgschl,flur,flurstkennz"
 +
 +
Auch wenn die Verknüpfung nur über ein Attribut erfolgt, können trotzdem noch mehr Attribute des ersten Layers hinter das Primärschlüsselattribut geschrieben werden. Das macht dann Sinn, wenn im Subform-Layer (dem ZWEITEN Layer) ein neuer Datensatz angelegt werden soll. Dann stehen die Werte der übergebenen Attribute bereits zur Verfügung und können beim Anlegen des Datensatzes verwendet werden (z.B. bei der Definition von Dateinamen, siehe Abschnitt "dynamische Dateipfade" in [[Admin-Dokumentation#Dokument|Dokument]]). Natürlich müssen die entsprechenden Attribute auch in der Query des zweiten Layers enthalten sein.
  
 
'''Weitere Optionen''' (werden mit einem ";" abgetrennt):
 
'''Weitere Optionen''' (werden mit einem ";" abgetrennt):
Zeile 440: Zeile 464:
  
  
Im Query-Statement des ersten Layers kann für das Vorschau-Attribut eine Aggregationsfunktion verwendet werden, um die verknüpften Datensätze zusammenzufassen. Also beispielsweise die Ausgabe der Anzahl der Flurstücke oder die Hintereinanderreihung der Flurstückskennzeichen. Das ist deswegen sinnvoll, damit der Nutzer in der Suche in diesem Verknüpfungsattribut auch suchen kann. Solange im abhängigen zweiten Layer noch kein Datensatz angelegt wurde, der mit einem Datensatz im übergeordneten ersten Layer verknüpft ist, ergibt sich eine Anzahl von 0 Treffern. Damit der "anzeigen"-Button in diesem Fall nicht erscheint, kann die Aggregationsfunktion mit einem CASE ergänzt werden, der für den Fall 0 Treffer einfach einen Leertext ausgibt (In SQL: 2 Hochkomma).
+
Im Query-Statement des ersten Layers kann für das Vorschau-Attribut eine Aggregationsfunktion verwendet werden, um die verknüpften Datensätze zusammenzufassen. Also beispielsweise die Ausgabe der Anzahl der Flurstücke oder die Hintereinanderreihung der Flurstückskennzeichen. Das ist deswegen sinnvoll, damit der Nutzer in der Suche in diesem Verknüpfungsattribut auch suchen kann. Solange im abhängigen zweiten Layer noch kein Datensatz angelegt wurde, der mit einem Datensatz im übergeordneten ersten Layer verknüpft ist, ergibt sich eine Anzahl von 0 Treffern. Damit der "anzeigen"-Button in diesem Fall nicht erscheint, kann die Aggregationsfunktion mit einem CASE ergänzt werden, der für den Fall 0 Treffer einfach einen Leertext ausgibt (In SQL: 2 Hochkomma). Beispiel:
 +
 
 +
select array2string(array(
 +
  select case when gml_id is not null then buchungsart else <nowiki>''</nowiki> end from alkis.ax_buchungsstelle where ...
 +
))
 +
 
  
  
Zeile 487: Zeile 516:
  
 
:''Beispiel'': "481,bezirk,blatt,bvnr"
 
:''Beispiel'': "481,bezirk,blatt,bvnr"
 +
 +
Außerdem ist es hier nicht notwendig, dass die Verknüpfungsattribute in beiden Layern gleich heißen müssen. Man kann hier auch erst den Namen des Attributs im untergeordneten Layer, dann einen Doppelpunkt und dann den Namen des Attributs im übergeordneten Layer angeben.
 +
 +
:''Beispiel'': "481,bezirk:bezirk_id,blatt:blatt_id,bvnr"
  
  
Zeile 514: Zeile 547:
  
 
:''Beispiel'': "152,vorhaben_id,Vorgangsart: vorgangsart vorgangs_id"
 
:''Beispiel'': "152,vorhaben_id,Vorgangsart: vorgangsart vorgangs_id"
 +
 +
Außerdem ist es hier nicht notwendig, dass die Verknüpfungsattribute in beiden Layern gleich heißen müssen. Man kann hier auch erst den Namen des Attributs im übergeordneten Layer, dann einen Doppelpunkt und dann den Namen des Attributs im untergeordneten Layer angeben.
 +
 +
:''Beispiel'': "152,id:vorhaben_id,Vorgangsart: vorgangsart vorgangs_id"
  
  
Zeile 521: Zeile 558:
 
:* list_edit  -  bewirkt, dass alle Datensätze des untergeordneten Layers nur im Listen-Editier-Modus angezeigt werden
 
:* list_edit  -  bewirkt, dass alle Datensätze des untergeordneten Layers nur im Listen-Editier-Modus angezeigt werden
 
:* reload  -  bewirkt, dass beim Ändern oder Neuanlegen im verknüpften Layer die gesamte Sachdatenanzeige neu geladen wird
 
:* reload  -  bewirkt, dass beim Ändern oder Neuanlegen im verknüpften Layer die gesamte Sachdatenanzeige neu geladen wird
 +
:* show_count  -  bewirkt, dass die Anzahl der Datensätze des untergeordneten Layers angezeigt wird
  
 
:''Beispiel'': "152,vorhaben_id,vorgangsart;embedded"
 
:''Beispiel'': "152,vorhaben_id,vorgangsart;embedded"
Zeile 580: Zeile 618:
  
 
;dynamische Dateipfade
 
;dynamische Dateipfade
:Neben dieser standardmäßigen Variante der Dateiablage auf dem Server lassen sich die Dateinamen und auch die Verzeichnisstruktur unterhalb des Dokumentenordners bzw. der Dokumenten-URL für jedes Attribut vom Typ "Dokument" frei definieren. Dazu besteht die Möglichkeit im Attributeditor im Optionenfeld des Dokumenten-Attributs eine beliebige SQL-Abfrage zu definieren. Die Abfrage muss als Ergebnis die Ordnerstruktur unterhalb des Dokumentenordners inklusive des Dateinamens - aber ohne Dateiendung - liefern.
+
:Neben dieser standardmäßigen Variante der Dateiablage auf dem Server lassen sich die Dateinamen und auch die Verzeichnisstruktur unterhalb des Dokumentenordners bzw. der Dokumenten-URL für jedes Attribut vom Typ "Dokument" frei definieren. Dazu besteht die Möglichkeit im Attributeditor im Optionenfeld des Dokumenten-Attributs eine beliebige SQL-Abfrage zu definieren, die mit SELECT beginnt. Die Abfrage kann eine Ordnerstruktur und Variablen mit $ beinhalten sowie mit einem Dateinamen ohne Dateierweiterung oder mit '/' enden.
 +
:Beispiele für eine hochgeladene Datei mit dem Namen Draft.pdf bei gesetztem Dokument-Pfad /var/www/data/upload/, User-ID: 54, Stelle-ID: 2, Datensatz-ID: 123 und Dokumenttyp: 'Entwurf':
 +
* SELECT 'antragsdokumente/' => /var/www/data/upload/antragsdokumente/Draft.pdf
 +
* SELECT 'antragsdokumente/$USER_ID/' => /var/www/data/upload/antragsdokumente/54/Draft.pdf
 +
* SELECT 'antragsdokumente/$STELLE_ID/$datensatz_id' => /var/www/data/upload/antragsdokumente/2/123.pdf
 +
* SELECT 'antragsdokumente/$dokumententyp/' || now() => /var/www/data/upload/antragsdokumente/Entwurf/2024-09-03 14:23:15.pdf
 +
 
 +
Wenn der Pfad mit einem / endet, wird also der Name der Hochgeladenen Datei verwendet, ansonsten wird nur die Dateiendung angehängt.
 +
 
 +
:Beispiel:
 +
<nowiki>select 'container-' || '$container_id'</nowiki>
 +
Feststehende Texte werden in Hochkommata notiert, Attribute des Layers mit $-Zeichen in Hochkommata: '$<attributname>'. Vorsicht bei Verwendung von Serial-Attributen: Das Select muss berücksichtigen, dass es den Datensatz bei einem INSERT noch gar nicht gibt und dass das Serial-Attribut in diesem Fall keinen Wert liefert. Abhilfe schafft die Eintragung des nextval-Strings aus der Layerdefinition (nextval('xyz_seq'::regclass)). Diese wird von kvwmap bei Attributen vom serial Typ mittlerweile automatisch in die Attribut-Definition eingetragen. Verwendet werden können nur die Realname der Attribute, nicht die Aliasnamen. Ist ein Attribut z.B. mit id AS konvertierung_id definiert setzt man in der Option für das document $id statt $konvertierung_id.
 +
 
 +
Handelt es sich um einen Subform-Layer, können [[Admin-Dokumentation#SubformPK|aus dem übergeordneten Layer Attribute übergeben]] werden, die dann bei der Erzeugung des Dateinamens verwendet werden können:
 +
 
 +
<nowiki>select 'befliegung-' || '$befliegungsnummer' || '$dokumente_id'</nowiki>
  
 
:Wenn man die Dateien in einem Unterordner "kvwmap-like" ablegen will, d.h. mit einem Zufallsnamen bestehend aus timestamp und sechstelliger Zufallszahl, dann kann die Option beispielsweise so formuliert sein:
 
:Wenn man die Dateien in einem Unterordner "kvwmap-like" ablegen will, d.h. mit einem Zufallsnamen bestehend aus timestamp und sechstelliger Zufallszahl, dann kann die Option beispielsweise so formuliert sein:
  
 
  <nowiki>select 'unterordner/' || to_char(current_timestamp, 'YYYY-MM-DD_HH_MM_SS') || '-' || ceil(random() * 1000000)</nowiki>
 
  <nowiki>select 'unterordner/' || to_char(current_timestamp, 'YYYY-MM-DD_HH_MM_SS') || '-' || ceil(random() * 1000000)</nowiki>
 
:Werte der Attribute dieses Layers können über "$<attributname>" in die Abfrage einbezogen werden, so dass der Dateiname aus den Attributen des zugehörigen Datensatzes erzeugt wird. Vorsicht bei Verwendung von Serial-Attributen: Das Select muss dann berücksichtigen, dass es den Datensatz bei einem INSERT noch gar nicht gibt und das Serial-Attribut keinen Wert liefert.
 
  
 
:Es lassen sich sogar variabel weitere Unterordner in diesem Unterordner anlegen.
 
:Es lassen sich sogar variabel weitere Unterordner in diesem Unterordner anlegen.
Zeile 745: Zeile 796:
  
 
Damit die Attribute in der Sachdatenanzeige gruppiert angezeigt werden, kann man ihnen im Attributeditor Gruppennamen zuordnen. Alle Attribute mit dem selben Gruppennamen werden zu einer Gruppe zusammengefasst, wobei die Attribute schon in der richtigen Reihenfolge sein müssen.
 
Damit die Attribute in der Sachdatenanzeige gruppiert angezeigt werden, kann man ihnen im Attributeditor Gruppennamen zuordnen. Alle Attribute mit dem selben Gruppennamen werden zu einer Gruppe zusammengefasst, wobei die Attribute schon in der richtigen Reihenfolge sein müssen.
 +
 
Die Gruppen lassen sich im GLE auf- und zuklappen. Hängt man an den Gruppennamen noch ";collapsed" an, ist diese Gruppe schon zu Beginn zugeklappt.
 
Die Gruppen lassen sich im GLE auf- und zuklappen. Hängt man an den Gruppennamen noch ";collapsed" an, ist diese Gruppe schon zu Beginn zugeklappt.
Wichtig bei der Verwendung von Attributgruppen ist, dass jedes Attribut einer Gruppe zugeordnet ist. Beim Speichern füllt der Attributeditor daher leere Gruppenfelder automatisch mit der letzten Gruppe auf.
+
 
 +
Wenn Gruppen verwendet werden, '''muss''' jedes Attribut einer Gruppe zugeordnet ist. Beim Speichern füllt der Attributeditor daher leere Gruppenfelder automatisch mit der letzten Gruppe auf.
 +
 
 +
Die Gruppen können wiederum in mehrere Tabs aufgeteilt werden. Im Attributordner ordnet man den Attributen entsprechende Tab-Namen zu. Auch hier gilt: Wenn Tabs verwendet werden, '''muss''' jedes Attribut einer Gruppe und jede Gruppe einem Tab zugeordnet sein. Wenn der Gruppenname identisch ist mit dem Tabnamen, wird der Gruppenname nicht angezeigt. Wenn die Sachdaten eines Layers mit Tabs über eine URL aufgerufen werden, kann mit opentab=<Tabnummer> der geöffnete Tab angegeben werden. <Tabnummer> beginnt bei 0.
  
 
====Attributeditor - Anordnung von Attributen====
 
====Attributeditor - Anordnung von Attributen====
Zeile 779: Zeile 834:
 
: ja, wenn: das Attribut wird unter einer bestimmten Bedingung angezeigt (abhängig vom Wert eines anderen Attributs)
 
: ja, wenn: das Attribut wird unter einer bestimmten Bedingung angezeigt (abhängig vom Wert eines anderen Attributs)
  
Wenn die letzte Variante ausgewählt ist, erscheinen 3 extra Felder um die Sichtbarkeitsbedingung zu definieren. Hier kann das Attribut, ein Operator und ein Wert definiert werden. Folgende Operatoren werden unterstützt: "=", "!=", ">", "<" und "IN". Der Wert muss ohne Hochkomma oder ähnliches angegeben werden. Beim Operator "IN" können mehrere Werte angegeben werden, die mit "|" voneinander getrennt sind.
+
Wenn die letzte Variante ausgewählt ist, erscheinen 3 extra Felder um die Sichtbarkeitsbedingung zu definieren. Hier kann das Attribut, ein Operator und ein Wert definiert werden. Folgende Operatoren werden unterstützt: "=", "!=", ">", "<" und "IN". Der Wert muss ohne Hochkomma oder ähnliches angegeben werden. Beim Operator "IN" können mehrere Werte angegeben werden, die mit "|" voneinander getrennt sind. Wenn das Attribut, welches für den Vergleich verwendet werden soll vom Typ Boolean ist, trägt man t oder f ein ohne Hochkommas.  
  
 
Die Einstellung der Sichtbarkeit betrifft jedoch nur die Darstellung in der Sachdatenanzeige. Das ist nützlich, wenn das Attribut nicht angezeigt werden soll, aber dennoch im Formular, z.B. für die Bildung eines anderen Attributes, den Export, dynamische URL's oder andere Abhängigkeiten benötigt wird.
 
Die Einstellung der Sichtbarkeit betrifft jedoch nur die Darstellung in der Sachdatenanzeige. Das ist nützlich, wenn das Attribut nicht angezeigt werden soll, aber dennoch im Formular, z.B. für die Bildung eines anderen Attributes, den Export, dynamische URL's oder andere Abhängigkeiten benötigt wird.
Zeile 786: Zeile 841:
 
Wird diese Option für ein Attribut gesetzt, wird es im Rastertemplate auch im zugeklappten Zustand angezeigt. Die Auswahl erfolgt in der Checkbox in der Spalte mit dem Raster bzw. Fenster-Symbol.
 
Wird diese Option für ein Attribut gesetzt, wird es im Rastertemplate auch im zugeklappten Zustand angezeigt. Die Auswahl erfolgt in der Checkbox in der Spalte mit dem Raster bzw. Fenster-Symbol.
  
====Validierung von Nutzereingaben====
+
====Templates (eigene Snippets)====
  
Der GLE unterstützt verschiedene Varianten die Gültigkeit von Nutzereingaben zu überprüfen. Alle diese Varianten haben ihre Grundlage in der [[Admin-Dokumentation#PostGIS-Tabelle_anlegen_und_f.C3.BCllen|PostGIS-Datenbank]], d.h. die Einschränkungen, die in der Datenbank für eine Tabelle gemacht werden, werden von kvwmap erkannt und in die Oberfläche des GLEs in Form von Validierungstests übertragen. Einige dieser Tests finden statt während der Nutzer eine Eingabe macht (z.B. Test auf Zahl) und einige werden erst durchgeführt, wenn der Nutzer versucht zu speichern (z.B. Test auf NOT NULL).
+
In den stellenbezogenen Eigenschaften des Layers (bzw. in den Defaults der Stellenzuweisung) kann ein PHP-Template angegeben werden, welches von kvwmap für die Sachdatenazeige eines Datensatzes verwendet werden soll. Das Template wird standardmäßig im Ordner custom/snippets/ gespeichert.
 +
 
 +
Im Template wird kein eigenes <form> Objekt angelegt. kvwmap setzt seine eigene <form> um alles. Die Speicherung funktioniert über den normalen Speichern-Button. Allerdings kann der Speichern-Button auch mit in das Template gezogen werden. Dafür muss der eigentliche Speichern-Button im CSS aus dem HTML-genommen werden:
 +
#nds_submit {
 +
  display: none;
 +
}
 +
Anschließend wird das <nowiki><div></nowiki> mit dem Speichern-Button im Template an geigneter Stelle eingebaut:
 +
<nowiki><div id="ticket-send">
 +
  <input type="button" name="go_plus" id="sachdatenanzeige_save_button" value="Speichern" onclick="save_new_dataset();">
 +
</div></nowiki>
 +
 
 +
Jedes Attribut im Template muss einen <name> Tag aufweisen. Der Name besteht aus 8 Elementen, die mit Semikolon getrennt werden:
 +
*(1) Die LayerID des zugehörigen Layers (das Attribut muss in der Query des Layers genannt sein)
 +
*(2) Der Spaltenname in der Datenbanktabelle
 +
*(3) Der Name der Datenbanktabelle
 +
*(4) Der Wert der ID-Spalte zum Datensatz
 +
*(5) Der Formularelementtyp des Attributs aus dem Attributeditor
 +
*(6) 0 oder 1. Wenn 0, dann ist es ein NOT NULL Attribut
 +
*(7) Der Datentyp des Feldes auf Datenbankebene
 +
*(8) 0 oder 1. Wenn 0, dann entspricht das Attribut im Template einem Feld in der Datenbanktabelle, ist also speicherbar
 +
 
 +
Beispiel:
 +
<input id="vorname" name="50304601;vname;ansprechpartner;;Text;0;varchar;1" aria-required="true" maxlength="30"></input>
 +
 
 +
Die Formularelementtypen werden nicht nach ihrem "lesbaren" Namen angegeben, sondern nach dem Value aus den Optionen der Auswahlliste:
 +
Text
 +
Zahl
 +
Textfeld
 +
Auswahlfeld
 +
Auswahlfeld_Bild
 +
Autovervollständigungsfeld
 +
Autovervollständigungsfeld_zweispaltig
 +
Farbauswahl
 +
Radiobutton
 +
Checkbox
 +
Time
 +
User
 +
UserID
 +
StelleID
 +
Link
 +
mailto
 +
Länge
 +
Style
 +
ExifRichtung
 +
ExifErstellungszeit
 +
 
 +
Am Ende des Templates müssen alle "name" Tags noch einmal gemeinsam in eine Variable geschrieben werden, die beim Speichern des Datensatzes an kvwmap übergeben wird. Die Variable lautet ''$this->form_field_names'' und die einzelnen "Namen" werden mit Pipe getrennt.
 +
 
 +
Beispiel:
 +
<?php
 +
  $this->form_field_names = '50304601;anrede;ticket;;Auswahlfeld;0;varchar;1|50304601;vname;ticket;;Text;0;varchar;1|50304601;nname;ticket;;Textfeld;0;text;1|50304601;email;ticket;;mailto;0;varchar;1|50304601;erstellt_von;ticket;;UserID;0;int4;1';
 +
?>
 +
 
 +
Wenn ein neuer Datensatz über das Template gespeichert wird, sollen der gespeicherte Datensatz anschließend im Template angezeigt werden. Dafür wird der qlayerset von kvwmap verwendet, wobei ''$this->qlayerset'' den ersten (und hier einzigen, deswegen "0") Layer bezeichnet und ''['shape']'' der Array für die Datensätze ist (hier auch "0", weil nur ein Datensatz zurück kommt):
 +
 
 +
Beispiel:
 +
<?php
 +
  $vorname = $this->qlayerset[0]['shape'][0]['vorname'];
 +
  ...
 +
?>
 +
 
 +
Beispiel für ein Attribut:
 +
<input id="vorname" name="50304601;v_name;ansprechpartner;;Text;0;varchar;1" aria-required="true" maxlength="30" value="<?php echo $vorname; ?>"></input>
 +
 
 +
==== Validierung von Nutzereingaben ====
 +
 
 +
===== Attributbezogene Validierung =====
 +
 
 +
Der GLE unterstützt verschiedene Varianten, die Gültigkeit von Nutzereingaben zu überprüfen. Alle diese Varianten haben ihre Grundlage in der [[Admin-Dokumentation#PostGIS-Tabelle_anlegen_und_f.C3.BCllen|PostGIS-Datenbank]], d.h. die Einschränkungen, die in der Datenbank für eine Tabelle gemacht werden, werden von kvwmap erkannt und in die Oberfläche des GLEs in Form von Validierungstests übertragen. Einige dieser Tests finden statt während der Nutzer eine Eingabe macht (z.B. Test auf Zahl) und einige werden erst durchgeführt, wenn der Nutzer versucht zu speichern (z.B. Test auf NOT NULL).
  
 
Folgende Attribut-Informationen werden beim Speichern der Layerdefinition erkannt:
 
Folgende Attribut-Informationen werden beim Speichern der Layerdefinition erkannt:
Zeile 801: Zeile 924:
  
  
'''Auswertung von Regeln'''
+
===== Validierung über Triggerfunktionen =====
  
Manchmal gibt es spezielle Anforderungen an die Einträge in einer Tabelle und dann reichen diese Möglichkeiten an Einschränkungen nicht aus. Z.B. kann es die Forderung geben, dass in einer Tabelle entweder Spalte A oder Spalte B mit einem Wert versehen sein muss (die "NOT NULL"-Einschränkung ist hier also nicht ausreichend). Eine andere Forderung könnte sein, dass neue Objekte sich geometrisch nicht mit vorhandenen Objekten überlappen dürfen.
+
''Nicht mehr empfohlen: Validierung über Regeln (Rules). Insbesondere, wenn mehrere Regeln bei einer Tabelle ausgeführt werden sollen, sind die Limitierungen von Regeln klar erkennbar. Triggerfunktionen bieten die gleichen Möglichkeiten der Validierung bei deutlich mehr Übersichtlichkeit. Darüber hinaus bieten Triggerfunktionen die Möglichkeit, beliebigen SQL-Code auszuführen. Die nicht mehr empfohlene Methode der Validierung über Regeln wird hier anhand der [[Validierung_von_Nutzereingaben_über_mehrere_Rules|Validierung von Nutzereingaben über mehrere Rules]] beschrieben.''
Um diese Fälle in der PostGIS-DB abzubilden, ist es möglich, INSERT- und UPDATE-Regeln für die entsprechenden Tabellen zu erstellen. Diese Regeln überprüfen die einzutragenden Werte und führen das INSERT bzw. UPDATE nur aus, wenn die gewünschte Forderung erfüllt ist ("Do INSTEAD", d.h. führe den Befehl nicht aus, sondern mache etwas anderes). Alternativ kann die Regel das INSERT bzw. UPDATE prüfen und beim Vorliegen bestimmter Bedingungen einen zusätzlichen Befehl ausführen ("DO ALSO", d.h. führe den Befehl aus und mache noch etwas anderes).
+
<br><br>
 +
Die [[Admin-Dokumentation#Attributbezogene_Validierung|attributbezogene Validierung]] bietet einen Set an Einschränkungen. Speziellere Anforderungen an die Validierung von Nutzereingaben können damit nicht abgedeckt werden. Triggerfunktionen erlauben es, jede beliebige Eingabe zu prüfen und mit einem Hinweis, einer Warnung oder einer Fehlermeldung zu beantworten. Z.B. kann es die Forderung geben, dass in einer Tabelle entweder Spalte A oder Spalte B mit einem Wert versehen sein muss (die "NOT NULL"-Einschränkung ist hier also nicht ausreichend). Oder eine bestimmte Eingabe (auch eine leere) soll mit einem ganz bestimmten Hinweis beantwortet werden. Oder neue bzw. geänderte flächenhafte Objekte dürfen sich geometrisch nicht mit vorhandenen Objekten aus derselben Tabelle überlappen.
  
Wenn die Regeln so erstellt werden, dass beim Vorliegen bestimmter Bedingungen ein entsprechender Fehler- oder Hinweistext ausgegeben wird, kann kvwmap diesen anzeigen und so den Nutzer auf die Bedingungen aufmerksam machen.
+
Validierungen wie diese werden in der PostGIS-DB über die Definition einer Triggerfunktion im Schema und eines Triggers bei der entsprechenden Tabelle realisiert. Triggerfunktionen haben folgenden Aufbau:
  
Beispiele:
+
CREATE OR REPLACE FUNCTION <schema>.<name der funktion>()
 +
  RETURNS trigger
 +
  LANGUAGE plpgsql
 +
  AS $function$
 +
  DECLARE
 +
 +
  BEGIN
 +
 +
    // Definition der Prüfung
 +
 +
    RETURN NEW;
 +
  END;
 +
  $function$
 +
;
  
*In einer Tabelle "denkmale" gibt es u.a. die Spalten "fundgruppe" und "fundart". Mindestens eine der beiden Spalten soll bei einer Neuerfassung ausgefüllt sein:
+
In der Triggerfunktion kann die Anwendungsoperation unterschieden werden, also INSERT oder UPDATE oder DELETE. Dafür wird je ein IF notiert in der Form
  
  CREATE OR REPLACE RULE denkmale_insert AS
+
  IF (TG_OP = 'INSERT') THEN
ON INSERT TO denkmale
+
  ...
WHERE new.fundart IS NULL AND new.fundgruppe IS NULL DO INSTEAD SELECT 'Die Fundart oder die Fundgruppe muss ausgefüllt sein.';
+
  END IF;
  
 +
IF (TG_OP = 'UPDATE') THEN
 +
  ...
 +
END IF;
  
*In einer Tabelle "dokumente" wird ein Attribut "datei" gespeichert. Der Nutzer soll einen Hinweis bekommen, wenn Dateien mit gleichem Namen gespeichert werden:
+
IF (TG_OP = 'DELETE') THEN
 +
  ...
 +
END IF;
  
CREATE OR REPLACE RULE insert_pdf_name AS
+
Wenn diese IFs weggelassen werden, wird die Prüfung bei allen im Trigger definierten Anwendungsoperationen ausgeführt. Diese IFs können auch schon weitere Bedingungen enthalten, es ist aber übersichtlicher, die Prüfung in ein eigenes IF zu schreiben. Das macht außerdem vor allem dann Sinn, wenn zu einem Anwendungsfall mehrere Prüfungen stattfinden sollen:
ON INSERT TO denkmale.dokumente
+
WHERE (substring(new.datei, position(new.datei, 'original_name=') + 14) IN ( SELECT substring(dokumente.datei, position(dokumente.datei, 'original_name=') + 14) FROM denkmale.dokumente))
+
DO ALSO SELECT 'Hinweis: Eine Datei mit diesem Namen existiert bereits!';
+
  
 +
IF (TG_OP = 'INSERT') THEN
 +
  IF <prüfung1> THEN
 +
    ...
 +
  END IF;
 +
  IF <prüfung2> THEN
 +
    ...
 +
  END IF;
 +
END IF;
  
*In einer Tabelle mit Flächengeometrien "polygons" soll verhindern werden, dass dort Datensätze angelegt werden, deren Geometrie sich mit anderen Datensätzen überlappt.
+
Das Ergebnis der Prüfung mündet immer in einen Text, den der Nutzer zurückbekommt. Dieser Text muss ihm alle notwendigen Informationen an die Hand geben, damit er weiß, was passiert ist. Drei mögliche Zustände (am Beispiel des INSERTs):
:Die INSERT-Regel hat folgende Form:
+
  
CREATE OR REPLACE RULE avoid_overlap_insert AS
+
* Die Prüfung mündet in einen '''Hinweis''' (INSERT bzw. UPDATE bzw. DELETE soll trotzdem durchgeführt werden)
ON INSERT TO polygons
+
IF (TG_OP = 'INSERT') THEN
WHERE ( SELECT true AS bool
+
  IF <prüfung> THEN
        FROM polygons
+
    RAISE INFO 'Hier kommt der Hinweistext für den Nutzer';
        WHERE st_overlaps(new.the_geom, polygons.the_geom)
+
  END IF;
        LIMIT 1)
+
END IF;
DO INSTEAD  SELECT 'Polygonüberlappung ist nicht erlaubt.';
+
  
:Soll dieser Test auch bei Änderung eines Datensatz erfolgen, muss auch eine entsprechende Regel für ON UPDATE erstellt werden. Diese hat fast die gleiche Form, außer dass die Bedingung für den Überlappungstest etwas anders ist, denn die neue Geometrie darf sich natürlich mit der alten Geometrie schneiden:
+
* Die Prüfung mündet in eine '''Warnung''' (INSERT bzw. UPDATE bzw. DELETE soll trotzdem durchgeführt werden)
 +
IF (TG_OP = 'INSERT') THEN
 +
  IF <prüfung> THEN
 +
    RAISE WARNING 'Hier kommt die Warnung für den Nutzer';
 +
  END IF;
 +
END IF;
  
CREATE OR REPLACE RULE avoid_overlap_update AS
+
* Die Prüfung ergibt einen '''Fehler''' (INSERT bzw. UPDATE bzw. DELETE soll '''NICHT''' durchgeführt werden)
ON UPDATE TO polygons
+
IF (TG_OP = 'INSERT') THEN
WHERE ( SELECT true AS bool
+
  IF <prüfung> THEN
        FROM polygons
+
    RAISE EXCEPTION 'Hier kommt die Fehlermeldung für den Nutzer';
        WHERE st_overlaps(new.the_geom, polygons.the_geom) AND NOT polygons.the_geom = old.the_geom
+
  END IF;
        LIMIT 1)
+
END IF;
DO INSTEAD  SELECT 'Polygonüberlappung ist nicht erlaubt.';
+
  
'''Erfolg, Fehler oder Warnung'''<br>
+
<br><br>
Die Rückmeldung, die in einem Do oder DO INSTEAD Statement erzeugt wird, kann eine zusätzliche Spalte ''msg_type'' mit dem Wert 'notice', 'warning' oder 'error' enthalten. Je nachdem was angegeben ist, wird die Message-Box zur Anzeige der Meldung mit einem gelblichen Hintergrund für einen Hinweis oder mit einem rötlichem Hintergrund für einen Fehler ausgegeben. Wird diese Spalte nicht angegeben oder sie enthält einen anderen Wert bleibt der Hintergrund in dem hellblauen Standardton.
+
Der zugehörige Trigger wird bei der Tabelle notiert und feuert vor oder nach einem Event (INSERT, UPDATE oder DELETE). Trigger können auch bei Views eingesetzt werden und feuern dort INSTEAD OF. Im Trigger wird außerdem angegeben, welche Triggerfunktion ausgeführt werden soll. Beispiel:
  
Beispiel für Warnung:
+
CREATE TRIGGER check_entries
 +
BEFORE INSERT or UPDATE
 +
ON <schema>.<tabelle> for each row execute procedure <schema>.<triggerfunktion>
  
CREATE OR REPLACE RULE r1_auftragsdatei_pruefen AS
+
<br><br>
ON UPDATE TO fortfuehrungslisten.ff_auftraege
+
WHERE ( SELECT new.auftragsdatei::text <> ''::text AND new.antragsnr::text <> "substring"(split_part(new.auftragsdatei::text, 'original_name='::text, 2), 1, 10) )
+
DO SELECT 'Die Antragsnummer im Dateinamen entspricht nicht der Antragsnummer im Formular oben.', 'warning' AS msg_type;
+
  
Beispiel für Fehler:
+
Beispiele für Triggerfunktionen:  
  
CREATE OR REPLACE RULE r2_auftrag_sperren AS
+
* In einer Tabelle "denkmale" gibt es u.a. die Spalten "fundgruppe" und "fundart". Mindestens eine der beiden Spalten soll bei einer Neuerfassung ausgefüllt sein:
ON UPDATE TO fortfuehrungslisten.ff_auftraege
+
WHERE ( SELECT old.gesperrt)
+
DO INSTEAD  SELECT 'Die Bearbeitung des Fortführungsnachweises ist gesperrt.', 'error' AS msg_type;
+
  
 +
CREATE OR REPLACE FUNCTION denkmale_check_entries()
 +
  RETURNS trigger
 +
  LANGUAGE plpgsql
 +
  AS $function$
 +
  DECLARE
 +
 +
  BEGIN
 +
  IF (TG_OP = 'INSERT') THEN
 +
    IF (new.fundart IS NULL AND new.fundgruppe IS NULL) THEN
 +
    RAISE EXCEPTION 'Die Fundart oder die Fundgruppe muss ausgefüllt sein!';
 +
    END IF;
 +
  END IF;
 +
  RETURN NEW;
 +
  END;
 +
  $function$
 +
;
  
'''Validierung mehrerer Attribute gleichzeitig'''<br>
+
* In einer Tabelle "dokumente" wird ein Attribut "datei" gespeichert. Der Nutzer soll einen Hinweis bekommen, wenn Dateien mit gleichem Namen gespeichert werden:
Wenn mehrere Attribute geprüft werden sollen, müssen mehrere Regeln geschrieben werden. Dann jedoch funktioniert das obige Verfahren nicht mehr reibungslos. In den HowTos ist eine Möglichkeit beschrieben, wie die [[Validierung_von_Nutzereingaben_über_mehrere_Rules|Validierung von Nutzereingaben über mehrere Rules]] erfolgen kann.
+
  
 +
CREATE OR REPLACE FUNCTION dokumente_check_entries()
 +
  RETURNS trigger
 +
  LANGUAGE plpgsql
 +
  AS $function$
 +
  DECLARE
 +
 +
  BEGIN
 +
  IF (TG_OP = 'INSERT') THEN
 +
    IF (substring(new.datei, position(new.datei, 'original_name=') + 14) IN ( SELECT substring(datei, position(datei, 'original_name=') + 14) FROM dokumente)) THEN
 +
    RAISE INFO 'Eine weitere Datei mit diesem Namen existiert bereits!';
 +
    END IF;
 +
  END IF;
 +
  RETURN NEW;
 +
  END;
 +
  $function$
 +
;
  
'''Triggerfunktionen / Auswertung von RAISE NOTICE'''
+
* In einer Tabelle mit Flächengeometrien "polygons" soll verhindern werden, dass dort Datensätze angelegt oder vorhandene Datensätze geändert werden, deren Geometrie sich mit der Geometrie bereits vorhandener Datensätze überlappt:
  
Alternativ zu Regeln kann man auch mit Triggerfunktionen auf Datenbankeinträge Einfluss nehmen. Triggerfunktionen bieten hier sogar mehr Möglichkeiten, da nicht nur einzelne SQL-Befehle, sondern beliebiger Code ausgeführt werden kann.
+
CREATE OR REPLACE FUNCTION geom_topo()
 +
  RETURNS trigger
 +
  LANGUAGE plpgsql
 +
  AS $function$
 +
  DECLARE
 +
  b varchar;
 +
 +
  BEGIN
 +
 +
  IF (TG_OP = 'INSERT') then
 +
    EXECUTE format(
 +
    'SELECT true AS bool
 +
    FROM %I.%I as z
 +
    WHERE st_overlaps(st_buffer(%L, -0.0001), z.the_geom)
 +
    LIMIT 1'
 +
    , TG_TABLE_SCHEMA, TG_TABLE_NAME, new.the_geom) INTO b;
 +
    IF (b = 't') THEN
 +
    RAISE EXCEPTION 'Die Geometrie darf sich nicht mit einer bereits vorhandenen überlappen!';
 +
    END IF;
 +
  END IF;
 +
 +
  IF (TG_OP = 'UPDATE') THEN
 +
    EXECUTE format( 
 +
    'SELECT true AS bool
 +
    FROM %I.%I as z
 +
    WHERE st_overlaps(st_buffer(%L, -0.0001), z.the_geom) AND NOT z.the_geom = %L
 +
    LIMIT 1'
 +
    , TG_TABLE_SCHEMA, TG_TABLE_NAME, new.the_geom, old.the_geom) INTO b;
 +
    IF (b = 't') THEN
 +
    RAISE EXCEPTION 'Die Geometrie darf sich nicht mit einer bereits vorhandenen überlappen!';
 +
    END IF;
 +
  END IF;
 +
 +
  RETURN NEW;
 +
  END;
 +
$function$
 +
;
  
In einer Triggerfunktion lassen sich über RAISE NOTICE ebenfalls Ausgaben erzeugen, die von kvwmap angezeigt werden. Wenn die Notice einen einfachen Text enthält, wird dieser nach dem Update bzw. Insert als Messagebox in kvwmap angezeigt. Meist steht hier der Text "HINWEIS:" davor. Die Notice kann aber auch ein JSON-String sein, welcher das Attribut "msg" mit dem auszugebenden Text enthält. Dann wird nur dieser Text angezeigt.
+
Hinweise:
 +
* st_buffer erzeugt eine winzige Lücke, die es ermöglicht, dass direkt aneinander grenzende Flächen, die aus kvwmap kommen, von st_overlaps nicht als überlappend angesehen werden.
 +
* Schema- und Tabellenname werden über TG_TABLE_SCHEMA und TG_TABLE_NAME in die Funktion gegeben. Diese Funktion kann also von allen Tabellen eines Schemas benutzt werden und muss nicht für jede Tabelle neu geschrieben werden.
 +
<br><br>
  
   RAISE NOTICE '{"success:" : false, "msg_type": "warning", "msg" : "Meldung der Validierung"}';
+
RAISE kann auch einen JSON-String enthalten, welcher das Attribut "msg" mit dem auszugebenden Text enthält. Dann wird nur dieser Text angezeigt.
 +
 
 +
   RAISE INFO '{"success" : true, "msg_type" : "notice", "msg" : "Meldung der Validierung"}'; 
 +
 
 +
''"success":true'' produziert den Text "Änderung erfolgreich" - unabhängig davon, ob der Datensatz gespeichert wird oder nicht!
 +
 
 +
''"success":false'' produziert den Text "Kann Datensatz nicht speichern" - unabhängig davon, ob der Datensatz gespeichert wird oder nicht!
 +
 
 +
Achtung: Nur RAISE EXCEPTION bewirkt, dass die Verarbeitung des Datensatzes '''abgebrochen''' wird. Bei der Verwendung des JSON-Strings kann man also auch fehlerhafte Ausgaben produzieren.
 +
 
 +
RAISE gibt es auch noch als RAISE NOTICE.
 +
 
 +
  RAISE NOTICE '{"success" : false, "msg_type" : "warning", "msg" : "Meldung der Validierung"}';
 +
 
 +
Achtung: RAISE NOTICE sendet keine Mitteilung an den Client, solange ''client_min_messages'' nicht auf 'NOTICE' gesetzt wurde. Das passiert entweder durch ein vorangestelltes
 +
  SET client_min_messages TO 'NOTICE';
 +
oder durch dauerhafte Änderung in der postgresql.conf.
 +
 
 +
Achtung: RAISE NOTICE an sich verhindert das Verarbeiten des Datensatzes nicht. Dass Verarbeiten wird hier nur durch ein zusätzlich notiertes
 +
  RETURN NULL;
 +
unterbunden.
  
 
====Bearbeitung von Geometrien - Geometrie-Editor====
 
====Bearbeitung von Geometrien - Geometrie-Editor====
Zeile 926: Zeile 1.161:
  
 
[[Bild:Punktfang.png|800px]]
 
[[Bild:Punktfang.png|800px]]
 +
 +
Zur Unterstützung bei der Digitalisierung besteht die Möglichkeit zu zoomen ohne dass der Kartenausschnitt neu geladen wird. Dazu muss man die Strg-Taste gedrückt halten und kann über das Mausrad reinzoomen. Dadurch lassen sich z.B. nahe beieinander liegende Punkte leichter fangen. Lässt man die Strg-Taste los, wird der Zoom zurück gesetzt und die Darstellung springt auf die Ausgangslage zurück.
  
  
Zeile 968: Zeile 1.205:
 
|}
 
|}
  
Das Ergebnis der Suche erscheint dann im generischen Layer-Editor bzw., falls dem Layer ein Template zugeordnet ist, das entsprechende Template.
+
Das Ergebnis der Suche erscheint dann im generischen Layer-Editor bzw., falls dem Layer ein [[Admin-Dokumentation#Templates_.28eigene_Snippets.29|Template]] zugeordnet ist, das entsprechende Template.
  
 
===== Zurück zur vorherigen Seite =====
 
===== Zurück zur vorherigen Seite =====
Zeile 986: Zeile 1.223:
 
[[Bild:Datendrucklayouteditor.png]]
 
[[Bild:Datendrucklayouteditor.png]]
  
Links wird ein Vorschaubild des Drucklayouts angezeigt und rechts das Formular mit den Daten des Drucklayouts. Oben rechts befinden sich 3 Buttons zur schnellen Navigation im Formular (nach oben, zu den Freitexten, zu den Linien).  
+
Links wird ein Vorschaubild des Drucklayouts angezeigt und rechts das Formular mit den Daten des Drucklayouts. Oben rechts befinden sich 3 Buttons zur schnellen Navigation im Formular (nach oben, zu den Freitexten, zu den Linien).
 +
 
 +
Das Layout wird über seinen Namen eindeutig definiert und gehört immer nur zu einem Layer. Die Druckdatei erhält beim Drucken den Namen der unter Dateiname angegeben ist. Die Ränder definieren den Bereich der für Fließtext genutzt wird. Man kann z.B. Kopf und Fußzeilen, die absolut positioniert sind auch in die Randbereiche schreiben.
 +
 
 +
Ist die Option "Leere Attributwerte nicht drucken" ausgewählt werden diese Attribute und ggf. für die Attribute angegebene Label nicht gedruckt. Nachfolgende Attribute mit relativer Positionierung dazu werden jedoch gezeichnet.
 +
 
 +
Ist die Option "Vorschaubilder verwenden statt Originale" ausgewählt werden für den Druck statt der originalen Bilder die Preview-Bilder verwendet falls sie vorhanden sind. Die Option wirkt sich auf alle Attribute mit Formularelementtype "Dokument" aus. Durch den Druck der Vorschaubilder kann die Größe der PDF-Dokumente erheblich reduziert werden. Die Option ist besonders zu empfehlen wenn der Druck von vielen Objekten gleichzeitig möglich ist oder viele Bilder zu einzelnen Features gehören und gedruckt werden können. Prüfen Sie auch ob die Größe der Vorschaubilder ausreichend ist für die Auflösung im PDF. Diese kann mit der Konstante Layout > PREVIEW_IMAGE_WIDTH auf der Admin-Seite eingestellt werden.
  
 
Das Prinzip der Layoutdefinition ist ähnlich dem der Druckrahmen für den PDF-Kartendruck. Jedes Attribut kann über einen x- und y-Wert auf der PDF-Seite positioniert und mit einer bestimmten Schriftgröße und -Art ausgegeben werden. In der Vorschau des Layouts im Layouteditor werden die Attributnamen verwendet, beim späteren Druck eines Datensatzes die Attributwerte. Auch hier können analog zum Kartendruck beliebig viele Freitexte und ein Hintergrundbild im Layout angeordnet werden. Zusätzlich ist es möglich, Linien zu "zeichnen".
 
Das Prinzip der Layoutdefinition ist ähnlich dem der Druckrahmen für den PDF-Kartendruck. Jedes Attribut kann über einen x- und y-Wert auf der PDF-Seite positioniert und mit einer bestimmten Schriftgröße und -Art ausgegeben werden. In der Vorschau des Layouts im Layouteditor werden die Attributnamen verwendet, beim späteren Druck eines Datensatzes die Attributwerte. Auch hier können analog zum Kartendruck beliebig viele Freitexte und ein Hintergrundbild im Layout angeordnet werden. Zusätzlich ist es möglich, Linien zu "zeichnen".
Zeile 995: Zeile 1.238:
  
 
Wenn man in einem Drucklayout Attribute ausgeben möchte, die Text über mehrere Zeilen enthalten und dieser Text unterschiedlich lang sein kann, ist die Positionierung der nachfolgenden Attribute und Freitexte schwierig. In diesem Fall kann man die y-Position der nachfolgenden Elemente relativ zu den vorhergehen Attributen angeben. Dazu wählt man für alle nachfolgenden Elemente im Auswahlfeld "unterhalb von" das Attribut aus, auf das sich die relative Position beziehen soll und gibt als y-Wert den Abstand zu diesem Attribut an.
 
Wenn man in einem Drucklayout Attribute ausgeben möchte, die Text über mehrere Zeilen enthalten und dieser Text unterschiedlich lang sein kann, ist die Positionierung der nachfolgenden Attribute und Freitexte schwierig. In diesem Fall kann man die y-Position der nachfolgenden Elemente relativ zu den vorhergehen Attributen angeben. Dazu wählt man für alle nachfolgenden Elemente im Auswahlfeld "unterhalb von" das Attribut aus, auf das sich die relative Position beziehen soll und gibt als y-Wert den Abstand zu diesem Attribut an.
 +
 +
Wenn ein Label angegeben ist, wird dieses vor den Wert des Attributes geschrieben. Der Wert beginnt dann vom Anfang des Labels aus gesehen im Abstand des Wertes der bei Abstand angegeben wurde. Wird '$alias' angegeben wird der Aliasname des Attributes als Label verwendet. Werden ein oder mehrere Leerzeichen eingegeben, wird kein Label ausgegeben aber trotzdem der Abstand zum Attributwert verwendet. Die Leerzeichen werden als nicht sichtbare Label gewertet. Ein Label kann fett ausgeben werden wenn es mit den Tags <nowiki><b></nowiki>eingeschlossen<nowiki></b></nowiki> ist.
  
 
Es gibt 3 verschiedene Layouttypen:
 
Es gibt 3 verschiedene Layouttypen:
Zeile 1.057: Zeile 1.302:
 
  kvwmap/index.php?go=generischer_sachdaten_druck_Drucken&aktivesLayout=31&chosen_layer_id=743&oid=$oid&archivieren=1;archivieren;no_new_window
 
  kvwmap/index.php?go=generischer_sachdaten_druck_Drucken&aktivesLayout=31&chosen_layer_id=743&oid=$oid&archivieren=1;archivieren;no_new_window
  
Für die Funktion
+
Wenn das Attribut vom Typ Dokument ein Array ist, wird das erzeugte PDF als neues Array-Element angehängt ohne die bisherigen PDFs zu überschreiben. Dadurch entsteht eine Liste mit den historischen Ständen des Datensatzes.
 
+
Am Ende der Funktion wird über den Anwendungsfall GenerischeSuche_Suchen der Datenstatz des gewählten Layers aufgerufen der im ersten Dokument-Attribut den Namen des gerade generierten PDF-Dokumentes stehen hat.
+
  
 
====dynamische Layerdefinitionen====
 
====dynamische Layerdefinitionen====
Zeile 1.073: Zeile 1.316:
  
 
;Definition der Parameter
 
;Definition der Parameter
Die Layer-Parameter können über '''go=Layer_Parameter''' definiert werden. Es muss ein Name, ein Aliasname, ein Standardwert und eine SQL-Abfrage für die Auswahlmöglichkeiten eingegeben werden. Die SQL-Abfrage für die Auswahlmöglichkeiten kann genauso aufgebaut sein, wie bei der Definition eines Auswahlfeldes im Attributeditor. Sie muss eine Spalte "value" für den Wert und eine Spalte "output" für den angezeigten Text liefern. Für das obige Beispiel könnte die SQL-Abfrage z.B. so aussehen:
+
Die Layer-Parameter können definiert werden, indem man einen Menüpunkt mit dem Link "index.php?go=Layer_Parameter" erstellt und aufruft.
 +
 
 +
[[Datei:Layer_Parameter.png]]
 +
 
 +
Es muss ein Name, ein Aliasname, ein Standardwert und eine SQL-Abfrage für die Auswahlmöglichkeiten eingegeben werden. Die SQL-Abfrage für die Auswahlmöglichkeiten kann genauso aufgebaut sein, wie bei der Definition eines Auswahlfeldes im Attributeditor. Sie muss eine Spalte "value" für den Wert und eine Spalte "output" für den angezeigten Text liefern. Für das obige Beispiel könnte die SQL-Abfrage z.B. so aussehen:
  
 
  SELECT jahr AS value, jahr AS output FROM generate_series(2016,2036) AS jahr
 
  SELECT jahr AS value, jahr AS output FROM generate_series(2016,2036) AS jahr
  
 
;Verwendung der Parameter in der Layer-Definition
 
;Verwendung der Parameter in der Layer-Definition
Die Parameter können bei der Layer-Definition in der Form "$<name>" im Layernamen, im Aliasnamen, im Query-SQL, im Data-SQL, im Feld Classitem und im Feld Klassifizierung verwendet werden. Wenn man im Feld Klassifizierung einen dynamischen Layer-Parameter verwendet, kann innerhalb des Layers zwischen verschiedenen Klassifizierungen gewählt werden.
+
Die Parameter können bei der Layer-Definition in der Form "$<name>" in folgenden Feldern verwendet werden:
 +
 
 +
* Layername
 +
* Aliasname
 +
* Connection
 +
* Schema
 +
* Query
 +
* Data
 +
* Haupttabelle
 +
* Classitem
 +
* Tileindex
 +
* Klassifizierung
 +
* Processing
 +
* Attributeditor->Optionen
 +
 
 +
Wenn man im Feld Klassifizierung einen dynamischen Layer-Parameter verwendet, kann innerhalb des Layers zwischen verschiedenen Klassifizierungen gewählt werden.
  
 
;Auswahl der Parameter-Werte
 
;Auswahl der Parameter-Werte
Zeile 1.088: Zeile 1.350:
  
 
Eine andere Variante, die Parameter zu setzen, besteht beim Aufruf der Optionen ("go=Stelle_waehlen"). Wenn man hier den zusätzlichen URL-Parameter "&show_layer_parameter=1" angibt, wird ein Formular zum Setzen der Layer-Parameter angezeigt.  
 
Eine andere Variante, die Parameter zu setzen, besteht beim Aufruf der Optionen ("go=Stelle_waehlen"). Wenn man hier den zusätzlichen URL-Parameter "&show_layer_parameter=1" angibt, wird ein Formular zum Setzen der Layer-Parameter angezeigt.  
 +
 +
Wenn ein Parameter nur in einem Layer verwendet wird, erscheint beim Öffnen der Layer-Optionen in der Legende ein entsprechendes Auswahlfeld um den Parameterwert zu setzen. Wenn sich der Parameterwert auf die Kartendarstellung des Layers auswirkt, kann man mit der Maus oder den Pfeiltasten der Tastatur durch die Auswahlmöglichkeiten gehen und das Kartenbild ändert sich sofort für diesen Layer entsprechend des Parameterwertes.
  
 
;vordefinierte Parameter
 
;vordefinierte Parameter
Neben den o.g. selbst definierten Parametern, gibt es in kvwmap auch 5 vordefinierte Parameter, die in den Layer-Definitionen verwendet werden können.
+
Neben den o.g. selbst definierten Parametern, gibt es in kvwmap auch vordefinierte Parameter, die in den Layer-Definitionen verwendet werden können.
* $language: Dieser Parameter enthält die aktuell ausgewählte Sprache (german, english, ...)
+
* $LANGUAGE: Dieser Parameter enthält die aktuell ausgewählte Sprache (german, english, ...)
* $hist_timestamp: Dieser Parameter enthält den in den Optionen auswählbaren Zeitpunkt für historische Daten. Dieser Zeitpunkt kann für für eine zeitliche Navigation in Daten mit Vollhistorie verwendet werden (wie z.B. bei den ALKIS-Daten).
+
* $HIST_TIMESTAMP: Dieser Parameter enthält den in den Optionen auswählbaren Zeitpunkt für historische Daten. Dieser Zeitpunkt kann für für eine zeitliche Navigation in Daten mit Vollhistorie verwendet werden (wie z.B. bei den ALKIS-Daten).
* $current_date: Das aktuelle Datum.
+
* $CURRENT_DATE: Das aktuelle Datum.
* $current_timestamp: Der aktuelle Zeitpunkt.
+
* $CURRENT_TIMESTAMP: Der aktuelle Zeitpunkt.
* $user_id: Die ID des aktuell angemeldeten Nutzers
+
* $USER_ID: Die ID des aktuell angemeldeten Nutzers
* $stelle_id: Die ID der Stelle in der der Nutzer aktuell angemeldet ist.
+
* $STELLE_ID: Die ID der Stelle in der der Nutzer aktuell angemeldet ist.
* $scale: Der aktuelle Maßstab (bzw. der Nenner des Maßstabbruchs) Dieser Parameter kann im Feld "Data" verwendet werden um z.B. eine maßstabsabhängige Größenangabe für Styles zu realisieren.
+
* $SCALE: Der aktuelle Maßstab (bzw. der Nenner des Maßstabbruchs) Dieser Parameter kann im Feld "Data" verwendet werden um z.B. eine maßstabsabhängige Größenangabe für Styles zu realisieren.
 +
 
 +
Will man einen Datenbestand mit Historie führen, wird man ein Lebenszeitintervall in das Datenschema einbauen, beispielsweise ''lebenszeit_beginnt'' und ''lebenszeit_ende''t (beides date-Typ). Im Attribut-Editor müssen die beiden Attribute entsprechend gefüttert werden. Dann kann die Query des Layers so aussehen:
 +
 
 +
  SELECT id, ... , lebenszeit_beginnt, lebenszeit_ende
 +
  FROM <tabelle>
 +
  WHERE tsrange(lebenszeit_beginnt, lebenszeit_ende) @> COALESCE(NULLIF('$hist_timestamp', <nowiki>''</nowiki>)::timestamp, localtimestamp)
  
 
====Layerduplikate====
 
====Layerduplikate====
Zeile 1.195: Zeile 1.465:
 
Mit dem Style- und Labeleditor lassen sich die Styles der Geometrie und der Beschriftung der Klassen von Layern editieren, siehe auch [[Admin-Dokumentation#Style_und_Labeleditor|API]].
 
Mit dem Style- und Labeleditor lassen sich die Styles der Geometrie und der Beschriftung der Klassen von Layern editieren, siehe auch [[Admin-Dokumentation#Style_und_Labeleditor|API]].
  
Der Editor (go=Style_Label_Editor) wird entweder aus dem Menü Layerverwaltung oder dem Formular zum Ändern von Layereigenschaften aufgerufen. Im Editor wählt man zunächst links oben den Layer aus. Nach Aufruf aus dem Layereditor ist der Layer schon voreingestellt. Anschließend wählt man die Klasse aus, für die man den Style anpassen will. Daraufhin erscheinen ein Feld mit den zugeordneten Styles und Labels. Ein Klick auf den Style oder das Label öffnet das dazugehörige Formular mit den entsprechenden Parametern des Mapserver-STYLE- bzw. LABEL-Objekts.
+
Der Editor (go=Style_Label_Editor) wird entweder aus dem Menü Layerverwaltung oder dem Formular zum Ändern von Layereigenschaften aufgerufen. Im Editor wählt man zunächst links oben den Layer aus. Nach Aufruf aus dem Layereditor ist der Layer schon voreingestellt. Anschließend wählt man die Klasse aus, für die man den Style anpassen will. Daraufhin erscheinen ein Feld mit den zugeordneten Styles und Labels. Ein Klick auf den Style oder das Label öffnet das dazugehörige Formular mit den entsprechenden Parametern des Mapserver-[https://mapserver.org/mapfile/style.html STYLE]- bzw. [https://mapserver.org/mapfile/label.html LABEL]-Objekts.
  
 
Im rechten Bereich befinden sich oben Hilfsmittel zur Auswahl von Farben und Fonts und unten eine Vorschau der Layer. Wenn der Style eines Layers geändert wird, sollte dieser auch eingeschaltet sein. Änderungen von Styles werder erst sichtbar, wenn man unter dem Formular auf Speichern geklickt hat und danach die Karte aktualisiert. Es können mehr als ein Style pro Klasse erzeugt werden oder wieder gelöscht werden. Style- und Labeleinstellungen gelten derzeit stellenübergreifend. Das heißt ein Layer sieht in allen Stellen gleich aus. Sollen Layer in verschiedenen Stellen unterschiedlich aussehen, kann man die Layer einfach kopieren und anpassen.
 
Im rechten Bereich befinden sich oben Hilfsmittel zur Auswahl von Farben und Fonts und unten eine Vorschau der Layer. Wenn der Style eines Layers geändert wird, sollte dieser auch eingeschaltet sein. Änderungen von Styles werder erst sichtbar, wenn man unter dem Formular auf Speichern geklickt hat und danach die Karte aktualisiert. Es können mehr als ein Style pro Klasse erzeugt werden oder wieder gelöscht werden. Style- und Labeleinstellungen gelten derzeit stellenübergreifend. Das heißt ein Layer sieht in allen Stellen gleich aus. Sollen Layer in verschiedenen Stellen unterschiedlich aussehen, kann man die Layer einfach kopieren und anpassen.
  
Es ist möglich, einen Style zu kopieren (bei den Labels geht das nicht). Man trägt in einem neuen oder vorhandenen Style einfach die Nummer eines bereits existierenden Sytels ein und speichert.
+
Es ist möglich, einen Style zu kopieren. Man trägt in einem neuen oder vorhandenen Style einfach die ID eines bereits existierenden Styles ein und speichert. Dabei ist zu beachten, dass nach jedem Tastendruck versucht wird, die Styleinformationen zu laden. Am besten kopiert man die gewünschte Style-ID deshalb aus der Zwischenablage in das Feld rein.
  
[[Bild:Style_und_Labeleditor.jpg|rand|800px|Style- und Labeleditor]]
+
[[Datei:styleundlabeleditor.png]]
 
<br><br>
 
<br><br>
 +
* Die Felder size, minsize, maxsize, gap, initialgap und linejoinmaxsize haben einen Eingabebereich von 0 bis 200.
 +
* Die Felder width, minwidth und maxwidth haben einen Eingabebereich von 0 bis 100.
  
 
===Import/Export-Funktionen===
 
===Import/Export-Funktionen===
Zeile 1.249: Zeile 1.521:
  
 
Über go=Punktliste_Anzeigen können Textdateien importiert werden, die zeilenbasierte Koordinaten-Listen enthalten. Jede Zeile muss mindestens 2 Spalten für den Hoch- und den Rechts-Wert enthalten. Zusätzlich können weitere Spalten vorhanden sein. Als Trennzeichen der Spalten sind Komma, Semikolon, Tab und Leerzeichen erlaubt. Das Koordinatenreferenzsystem muss bekannt sein und es dürfen keine Leerzeilen in der Datei vorkommen. Nach dem Klick auf "Datei laden" muss noch festgelegt werden, welche Spalten als Hoch- und Rechts-Wert verwendet werden sollen. Die Auswahl einer Beschriftungsspalte ist optional.
 
Über go=Punktliste_Anzeigen können Textdateien importiert werden, die zeilenbasierte Koordinaten-Listen enthalten. Jede Zeile muss mindestens 2 Spalten für den Hoch- und den Rechts-Wert enthalten. Zusätzlich können weitere Spalten vorhanden sein. Als Trennzeichen der Spalten sind Komma, Semikolon, Tab und Leerzeichen erlaubt. Das Koordinatenreferenzsystem muss bekannt sein und es dürfen keine Leerzeilen in der Datei vorkommen. Nach dem Klick auf "Datei laden" muss noch festgelegt werden, welche Spalten als Hoch- und Rechts-Wert verwendet werden sollen. Die Auswahl einer Beschriftungsspalte ist optional.
 +
 +
 +
=====importierte Daten mit Anderen teilen=====
 +
Es gibt die Möglichkeit, den durch den Daten-Import entstandenen Rollenlayer zu einem "normalen" Layer zu machen, so dass er auch von anderen Nutzern gesehen werden kann. Dies kann der Nutzer, dem der Rollenlayer gehört über die Layeroptionen machen. Dort gibt es eine Option "Layer freigeben". Der Nutzer kann bei Bedarf noch den Namen des Layers anpassen und muss dann die Layergruppe auswählen, in der der Layer erstellt werden soll. Außerdem kann noch festgelegt werden, ob der Layer überall nur lesbar, in der gerade aktuellen Stelle editierbar oder in allen Stellen editierbar sein soll.
 +
 +
[[Datei:Share Layers.png]]
 +
 +
Damit diese Option in den Layeroptionen zur Verfügung steht, muss der Administrator vorher mehrere Sachen einstellen. Zunächst muss festgelegt werden, welche Layergruppen zur Verfügung stehen, um dort geteilte Layer zu erstellen. Diese Einstellung wird in der jeweiligen Layergruppe im Feld "Selectable_for_shared_layers" gemacht. Außerdem muss vom Administrator festgelegt werden, welchen Stellen geteilte Layer zugeordnet werden sollen. Dies wird im Stellenformular im Feld "Freigegebene Layer in dieser Stelle anzeigen" gemacht. Wenn ein Nutzer einen Rollenlayer freigibt, wird der Layer aber nicht allen Stellen zugeordnet, für das eben genannte Feld gesetzt ist, sondern nur den Stellen, denen der Nutzer auch zugeordnet ist. Dass ein bestimmter Nutzer Layer teilen darf, muss auch festgelegt werden. Dies erfolgt im Nutzerformular im Feld "Layer Teilen".
 +
 +
Durch die Freigabe des Rollenlayer entsteht ein neuer Layer, bei dem im Feld "Geteilt von Nutzer" die Nutzer-ID des Nutzers gespeichert ist, der den Layer freigegeben hat. Ansonsten ist es ein "normaler" Layer. Der Nutzer, der den Layer freigegeben hat, kann den Layer in den Layeroptionen auch wieder löschen.
 +
 +
Der geteilte Layer hat auch eine eigene Datenbank-Tabelle im Schema "shared", die von der Originaltabelle im Schema "custom_shapes" kopiert worden ist.
 +
 +
In einer Admin-Stelle hat man auch die Möglichkeit den Schemanamen und den Tabellennamen anzugeben, mit dem die Tabelle angelegt wird.
  
 
===Kartenausschnitt speichern/laden===
 
===Kartenausschnitt speichern/laden===
Zeile 1.270: Zeile 1.556:
 
Drucken eines frei wählbaren Kartenausschnittes unter Angabe des Maßstabes und der Drehung des Druckbereiches, siehe [[Dokumentation#Drucken_in_PDF|Drucken in PDF]].
 
Drucken eines frei wählbaren Kartenausschnittes unter Angabe des Maßstabes und der Drehung des Druckbereiches, siehe [[Dokumentation#Drucken_in_PDF|Drucken in PDF]].
  
===Weitere Funktionalitäten===
+
===Benachrichtigungen===
 +
 
 +
Der Administrator kann über den Menüpunkt mit dem Link index.php?go=notifications_anzeigen eine oder mehrere Benachrichtigungen für Anwender verwalten.
 +
 
 +
[[Datei:notifications_anzeigen_menue.png]]
 +
 
 +
Wenn der Menüpunkt angelegt ist, muss er nur der Stelle zugeordnet werden in dem die Benachrichtigungen verwaltet werden können sollen.
 +
 
 +
[[Datei:notifications_anzeigen.png]]
 +
 
 +
Über den Plus-Button kann man eine neue Benachrichtigung anlegen und über den Stift gelangt man in die Editiermaske einer vorhandenen.
 +
 
 +
[[Datei:Notification_Hint.png]]
 +
 
 +
In den Info-Feldern sind Hinweise zur Eingabe hinterlegt. Werden falsche Eingaben getätigt, erscheinen beim Speichern Fehlermeldungen.
 +
 
 +
[[Datei:notification_validation_result.png]]
 +
 
 +
Der Benachrichtigungstext und das Ablaufdatum müssen angegeben werden. Das Veröffentlichungsdatum muss vor dem Ablaufdatum liegen.
 +
 
 +
Im Feld Stellenfilter kann die Anzeige der Benachrichtigung auf bestimmte Stellen begrenzt werden.
 +
 
 +
Im Feld Nutzerfilter kann die Anzeige der Benachrichtigung auf bestimmte Nutzer begrenzt werden. Sind in beiden Feldern Filter angegeben wir beides gefiltert. Wird nichts angegeben, wird die Benachrichtigung bei allen angezeigt.
 +
 
 +
Die Benachrichtigungen werden in der MariaDB-Datenbank in der Tabelle [[Admin-Dokumentation#Tabelle_.22notifications.22|notifications]] gespeichert und die Information welcher Nutzer seine Benachrichtigungen noch nicht gelöscht hat in der Tabelle [[Admin-Dokumentation#Tabelle_.22user2notifications.22|user2notifications]].
 +
 
 +
Wird eine neue Benachrichtigung vom Admin eingetragen, erhalten zunächst alle Nutzer eine Eintragung in der Tabelle user2notifications. Wählt ein Nutzer beim Ausblenden einer Benachrichtigung 'nicht mehr anzeigen', wird diese Zuordnung in der Tabelle user2notification gelöscht und für diesen Nutzer in keiner Stelle mehr angezeigt.
 +
 
 +
Wird eine Benachrichtigung geändert, werden die Zuordnungen für alle Nutzer noch mal neu eingetragen. So sehen die Nutzer auch geänderte Benachrichtigungen obwohl sie diese vielleicht schon mal mit 'nicht mehr anzeigen' abgewählt hatten.
 +
 
 +
Löscht der Admin eine Benachrichtigung wird vorher eine Warnung angezeigt.
 +
 
 +
[[Datei:notification_delete_warning.png]]
 +
 
 +
Beim Löschen einer Benachrichtigung werden auch alle Zuordnungen zu Nutzern gelöscht. Zwischen notifications und user2notifications besteht ein Fremdschlüssel mit ON DELETE CASCADE und ON UPDATE CASCADE. Wenn also in der Datenbank die ID einer Notification geändert wird, wird auch die notification_id in der Tabelle user2notifications geändert.
 +
 
 +
 
 +
Die Anzahl der verfügbaren neuen Benachrichtigungen werden über das Glockensymbol im Kopf der Oberfläche angezeigt.
 +
 
 +
[[Datei:glocke.png]]
 +
 
 +
Wer eine eigene Header-Datei verwendet kann die Funktion zur Anzeige der Benachrichtiungen in seinen Kopf übernehmen in dem er das Div mit dem title="Benachrichtigungen" aus der Datei layouts/snippets/header.html übernimmt. Der Style der Benachtichtigungsfenster kann über den Klassennamen notification-box in der eigenen Style-Datei überschrieben werden.
 +
 
 +
[[Datei:notification_box.png]]
 +
 
 +
Wie der Nutzer die Benachrichtigungen ausblenden und für sich löschen kann ist in der Nutzer-Dokumentation beschrieben. [[Nutzer-Dokumentation#Benachrichtigungen]]
  
* Kartengröße wahlweise einstellbar
+
Die Anzahl der Benachrichtigungen und die Benachrichtigungen selber, werden beim Laden der Seite neu aus der Datenbank abgefragt. Dabei wird der Nutzer- und Stellenfilter angewendet.u2m.user_id = " . $gui->user->id . " AND
* Kartenausschnitt als Rasterbild abspeicherbar
+
  u2m.user_id = " . $gui->user->id . " AND
* Bildschirm-Ansichten drucken (Browserfunktionalität)
+
  CURRENT_DATE BETWEEN COALESCE(veroeffentlichungsdatum, CURRENT_DATE) AND COALESCE(ablaufdatum, CURRENT_DATE) AND
* Druck-Voransicht (Browserfunktionalität)
+
  (
* Layer wahlweise ein-/ausschaltbar
+
    m.stellen_filter IS NULL OR
* Hilfe-Funktion
+
    m.stellen_filter = '' OR
 +
    concat(',', m.stellen_filter, ',') LIKE '%," . $gui->Stelle->id . ",%'
 +
  )
  
 
== Funktionen auf dem Server ==
 
== Funktionen auf dem Server ==
Zeile 1.391: Zeile 1.724:
  
 
  <nowiki>SET @group_id = 1;
 
  <nowiki>SET @group_id = 1;
 +
SET @connection_id = 1;
 
SET @connection = 'host=pgsql dbname=kvwmapsp user=kvwmap password=*****';
 
SET @connection = 'host=pgsql dbname=kvwmapsp user=kvwmap password=*****';
  
INSERT INTO layer (`Name`, `alias`, `Datentyp`, `Gruppe`, `pfad`, `maintable`, `Data`, `schema`, `document_path`, `tileindex`, `tileitem`, `labelangleitem`, `labelitem`, `labelmaxscale`, `labelminscale`, `labelrequires`, `connection`, `printconnection`, `connectiontype`, `classitem`, `filteritem`, `tolerance`, `toleranceunits`, `epsg_code`, `template`, `queryable`, `transparency`, `drawingorder`, `minscale`, `maxscale`, `offsite`, `ows_srs`, `wms_name`, `wms_server_version`, `wms_format`, `wms_connectiontimeout`, `wms_auth_username`, `wms_auth_password`, `wfs_geom`, `selectiontype`, `querymap`, `logconsume`, `processing`, `kurzbeschreibung`, `datenherr`, `metalink`, `privileg`, `trigger_function`, `sync`) VALUES ('Notizen', '', '0', @group_id, 'SELECT q_notiz_kategorien.id,notiz,q_notiz_kategorien.kategorie,person,datum, the_geom FROM q_notizen, q_notiz_kategorien WHERE q_notiz_kategorien.id = q_notizen.kategorie_id::integer', 'q_notizen', 'the_geom from (select GeometryType(the_geom) as geomtype,oid,notiz AS label,person,kategorie_id,datum,st_Pointonsurface(the_geom) AS the_geom from q_notizen) as foo using unique oid using srid=2398', '', '', '', '', '', 'label', '50000', '0', '', @connection, '', '6', 'geomtype', 'kategorie_id', '3', 'pixels', '2398', '', '0', NULL, '10000', NULL, NULL, '', 'EPSG:2398', '', '1.1.0', 'image/png', '60', '', '', '', '', '0', '0', '', '', '', '', '0', '', '');
+
INSERT INTO layer (`Name`, `alias`, `Datentyp`, `Gruppe`, `pfad`, `maintable`, `Data`, `schema`, `document_path`, `tileindex`, `tileitem`, `labelangleitem`, `labelitem`, `labelmaxscale`, `labelminscale`, `labelrequires`, `connection_id`, `connection`, `printconnection`, `connectiontype`, `classitem`, `tolerance`, `toleranceunits`, `epsg_code`, `template`, `queryable`, `transparency`, `drawingorder`, `minscale`, `maxscale`, `offsite`, `ows_srs`, `wms_name`, `wms_server_version`, `wms_format`, `wms_connectiontimeout`, `wms_auth_username`, `wms_auth_password`, `wfs_geom`, `selectiontype`, `querymap`, `logconsume`, `processing`, `kurzbeschreibung`, `metalink`, `privileg`, `trigger_function`, `sync`) VALUES ('Notizen', '', '0', @group_id, 'SELECT q_notiz_kategorien.id,notiz,q_notiz_kategorien.kategorie,person,datum, the_geom FROM q_notizen, q_notiz_kategorien WHERE q_notiz_kategorien.id = q_notizen.kategorie_id::integer', 'q_notizen', 'the_geom from (select GeometryType(the_geom) as geomtype,oid,notiz AS label,person,kategorie_id,datum,st_Pointonsurface(the_geom) AS the_geom from q_notizen) as foo using unique oid using srid=2398', '', '', '', '', '', 'label', '50000', '0', '', @connection_id, @connection, '', '6', 'geomtype', '3', 'pixels', '2398', '', '0', NULL, '10000', NULL, NULL, '', 'EPSG:2398', '', '1.1.0', 'image/png', '60', '', '', '', '', '0', '0', '', '', '', '0', '', '0');
 
SET @last_layer_id53=LAST_INSERT_ID();
 
SET @last_layer_id53=LAST_INSERT_ID();
 
INSERT INTO layer_attributes (`layer_id`, `name`, `real_name`, `tablename`, `table_alias_name`, `type`, `geometrytype`, `constraints`, `nullable`, `length`, `decimal_length`, `default`, `form_element_type`, `options`, `alias`, `alias_low-german`, `alias_english`, `alias_polish`, `alias_vietnamese`, `tooltip`, `group`, `raster_visibility`, `mandatory`, `order`, `privileg`, `query_tooltip`) VALUES (@last_layer_id53, 'datum', 'datum', 'q_notizen', 'q_notizen', 'date', '', '', '1', NULL, NULL, '', 'Text', '', '', '', '', '', '', '', '', NULL, NULL, '4', '0', '0');
 
INSERT INTO layer_attributes (`layer_id`, `name`, `real_name`, `tablename`, `table_alias_name`, `type`, `geometrytype`, `constraints`, `nullable`, `length`, `decimal_length`, `default`, `form_element_type`, `options`, `alias`, `alias_low-german`, `alias_english`, `alias_polish`, `alias_vietnamese`, `tooltip`, `group`, `raster_visibility`, `mandatory`, `order`, `privileg`, `query_tooltip`) VALUES (@last_layer_id53, 'datum', 'datum', 'q_notizen', 'q_notizen', 'date', '', '', '1', NULL, NULL, '', 'Text', '', '', '', '', '', '', '', '', NULL, NULL, '4', '0', '0');
Zeile 1.403: Zeile 1.737:
 
INSERT INTO classes (`Name`, `Layer_ID`, `Expression`, `drawingorder`, `text`) VALUES ('Punktnotizen', @last_layer_id53, '(\'[geomtype]\' eq \'POINT\')', '0', '');
 
INSERT INTO classes (`Name`, `Layer_ID`, `Expression`, `drawingorder`, `text`) VALUES ('Punktnotizen', @last_layer_id53, '(\'[geomtype]\' eq \'POINT\')', '0', '');
 
SET @last_class_id=LAST_INSERT_ID();
 
SET @last_class_id=LAST_INSERT_ID();
INSERT INTO styles (`symbol`, `symbolname`, `size`, `color`, `backgroundcolor`, `outlinecolor`, `minsize`, `maxsize`, `angle`, `angleitem`, `antialias`, `width`, `minwidth`, `maxwidth`, `sizeitem`) VALUES (NULL, 'zugehoerigkeitspfeil', '30', '255 255 150', '', '100 100 100', '20', '40', '0', '', NULL, NULL, NULL, NULL, '');
+
INSERT INTO styles (`symbol`, `symbolname`, `size`, `color`, `backgroundcolor`, `outlinecolor`, `minsize`, `maxsize`, `angle`, `angleitem`, `width`, `minwidth`, `maxwidth`) VALUES (NULL, 'zugehoerigkeitspfeil', '30', '255 255 150', '', '100 100 100', '20', '40', '0', '', NULL, NULL, NULL);
 
SET @last_style_id=LAST_INSERT_ID();
 
SET @last_style_id=LAST_INSERT_ID();
 
INSERT INTO u_styles2classes (style_id, class_id, drawingorder) VALUES (@last_style_id, @last_class_id, 0);
 
INSERT INTO u_styles2classes (style_id, class_id, drawingorder) VALUES (@last_style_id, @last_class_id, 0);
Zeile 1.482: Zeile 1.816:
 
In der Klasse GUI sollten alle Funktionen enthalten sein, die die Interaktion des Benutzers mit dem Programm betreffen. Einige allgemeine Funktionen, wie das Lesen der Karteninformationen aus der Datenbank übernimmt die Klasse GUI, andere fachspezifische Aufgaben werden durch separate Objekte übernommen. Das gilt vor allem für die Funktionen der Fachschalen.
 
In der Klasse GUI sollten alle Funktionen enthalten sein, die die Interaktion des Benutzers mit dem Programm betreffen. Einige allgemeine Funktionen, wie das Lesen der Karteninformationen aus der Datenbank übernimmt die Klasse GUI, andere fachspezifische Aufgaben werden durch separate Objekte übernommen. Das gilt vor allem für die Funktionen der Fachschalen.
  
= kvwmap mobil =
+
= kvmobile =
Derzeit ist die Entwicklung einer [[Plugins#Mobile|App]] für die Erfassung von Geodaten im Offline-Modus mit Synchronisierungsfunktion in Arbeit. Damit wird es möglich sein Daten von Layern, die in kvwmap definiert wurden auf mobilen Endgeräten wie Handys oder Tablets zu erfassen oder zu bearbeiten. Details bitte bei den Entwicklern nachfragen.
+
Zur Erfassung, Verarbeitung und Präsentation von Geodaten aus kvwmap auf mobilen Endgeräten gibt es zwei Möglichkeiten.
 +
 
 +
Wenn auf dem mobilen Endgerät eine ständige mobile Internet-Verbindung oder WLAN-Verbindung verfügbar ist, kann kvwmap ganz normal im Browser verwendet werden. Das Layout ist jedoch nicht für kleinere Bildschirme optimiert. Gut Nutzbar wäre kvwmap im Browser nur auf Tabletts oder Laptops.
 +
 
 +
Um auch auf kleineren Endgeräten wie Handy's und auch ohne ständige Internet-Verbindung die Daten von kvwmap nutzen zu können bietet sich die APP kvmobile an.
 +
 
 +
Die APP wird als HTML-CSS-JavaScript Anwendung entwickelt. Der Source Code ist auf [https://github.com/pkorduan/kvmobile github] verfügbar. Die APP und wird über Cordova für das Android Betriebssystem gebaut und als [https://gdi-service.de/public/kvmobile/ APK-Datei zum Download] angeboten.
 +
 
 +
Serverseitig ist das [[Plugins#Mobile|kvwmap Plugin mobile]] erforderlich. Das Plugin ermöglicht das Arbeiten im Offline-Modus in kvmobile sowie die Synchronisierung von Geodaten und Fotos zwischen dem Server und dem mobilen Endgerät. An die Layer, die in kvmobile bearbeitet werden sollen, werden besondere Anforderungen gestellt, die in der Dokumentation zum Plugin beschrieben sind.
 +
 
 +
Die APP kvmobile verbindet sich über Benutzername und Passwort mit einer Stelle in einem kvwmap und stellt dem Nutzer die in der Stelle verfügbaren Layer mobile zur Verfügung. Ohne kvwmap funktioniert die APP also derzeit nicht. kvmobile muss sich erst mindestens ein mal mit dem Server verbunden haben um die dortigen Layer auf das Endgerät zu holen. Anschließend kann der Nutzer offline arbeiten. Erst wenn wieder Internet vorhanden ist können die Daten mit dem Server synchronisiert werden.
 +
 
 +
Für die Synchronisierung wird ein Versionierungskonzept mit uuid's und Deltas verwendet. Alle Daten haben eine eindeutige uuid und eine Versionsnummer pro Layer. Wenn kvmobile sich die Daten erstmalig holt, werden diese so wie sie sind in der sqlite Datenbank in kvmobile gespeichert. Werden Änderungen durchgeführt, egal ob auf Server oder Client werden die dazugehörigen SQL-Requests als sogenannte Deltas mit hochgezählter Versionsnummer gespeichert. Bei der Synchronisierung schickt kvmobile seine Deltas zum Server, die dort ausgeführt werden, und holt sich die Deltas vom Server die vom Zeitpunkt der letzten Synchronisierung bis jetzt angelegt wurden und führt diese auf dem Client aus. In der APP kvmobile wird die neue Version gesetzt, damit sie weiß bis zu welcher Änderungen die Deltas schon ausgeführt wurden.
 +
 
 +
Werden die selben Objekte von verschiedenen kvmobil APP's gleichzeitig bearbeitet, überschreibt immer die letzte Synchronisierung vorherige. Wenn die Abstände zwischen den Synchronisierungen größer sind, z.B. weil schlechtes Internet verfügbar ist, ist es also ratsam die Daten die bearbeitet werden sollen vorher in Bereiche für verschiedene Mitarbeiter aufzuteilen.
  
 
=Installation=
 
=Installation=
 +
Es gibt verschiedene Wege für die Installation von kvwmap. Das hängt von der zur Verfügung stehenden Umgebung ab.
 +
Der Standardweg auf einem Root-Server ist die Installation von [https://registry.hub.docker.com/r/pkorduan/kvwmap-server Docker Containern] in denen die zugehörigen Komponenten voreingerichtet sind.
 +
 +
Die Installation der Container läuft über eine Script in wenigen Arbeitsschritten ab.
 +
 +
wget -O inithost.sh https://gdi-service.de/public/kvwmap_resources/inithost && \
 +
chmod a+x inithost.sh && \
 +
./inithost.sh
 +
 +
Die Voraussetzung ist ein Server mit Zugang zum Internet, Debian Betriebssystem und ein Root-Zugang. Die Hardwareausstattung richtet sich nach der Menge der Daten die verarbeitet werden sollen und den erforderlichen Datenverarbeitungsprozessen.
 +
Für ein normales Portal z.B. Schutzgebietskataster, Liegenschaftsauskunftssystem oder Flächenmanagementkataster reicht ein Server mit folgender Ausstattung:
 +
* AMD Ryzen 8700 oder Intel® Core i5-13500
 +
* Okta-Core CPU
 +
* 64 GB RAM
 +
* 2 x 512 GB Festplatte im RAID 1
 +
 +
Weitere teils aber schon veraltete Informationen zu Möglichkeiten die Umgebung zu installieren:
  
* im [https://registry.hub.docker.com/u/pkorduan/kvwmap-server/ Docker Container]
 
 
* unter Debian mit [https://wiki.debian.org/DebianGis GIS-Paketen]
 
* unter Debian mit [https://wiki.debian.org/DebianGis GIS-Paketen]
 
* unter Windows mit [[Dokumentation#Installation_mit_ms4w|ms4w-Paket]]
 
* unter Windows mit [[Dokumentation#Installation_mit_ms4w|ms4w-Paket]]
Zeile 1.504: Zeile 1.868:
  
 
===Serverseite===
 
===Serverseite===
* Apache - Es ist eine Version >= 2.0.48 eingesetzt werden, damit die Umgebungsvariable REDIRECT_REMOTE_USER genutzt werden kann. Diese wird zur Identifizierung des Nutzers verwendet. (siehe auch Apache bug-report)
+
* Apache - Es ist eine Version >= 2.0.48 eingesetzt worden, damit die Umgebungsvariable REDIRECT_REMOTE_USER genutzt werden kann. Diese wird zur Identifizierung des Nutzers verwendet. (siehe auch Apache bug-report)
*:Session sollte z.Z. noch aktiv geschaltet werden, aber die Anwendung wird umgestellt, so dass sie ohne Session läuft und alle relevanten Parameter der Benutzer in der Datenbank zwischengespeichert werden.
+
* Folgende Apache-Module werden von kvwmap verwendet und müssen daher vorhanden sein
* PHP - Die Entwicklung von kvwmap läuft derzeit auf der Version 4.3.7
+
** authz_groupfile
*:Zur Konfiguration von php wurden in unserem Beispiel folgende Parameter gesetzt.
+
** cgi
*:./configure --enable-force-cgi-redirect --with-config-file-path=/opt/lampp/etc --with-regex=system *:--with-gd=/usr/local/gd --with-freetype-dir=/usr/local/freetype --enable-gd-native-ttf *:--with-png-dir=/usr/local/libpng --with-jpeg-dir=/usr/local/libjpeg --with-zlib --with-zlib-dir=/usr/local/zlib *:--enable-dbase –with-pgsql=/usr/local/pgsql
+
** headers
*:      Diese Parameter müssen Sie an Ihr System anpassen oder ggf. ergänzen.
+
** rewrite
*:      Ob PHP richtig kompiliert wurde erkennen Sie durch die Ausgabe eines phpinfo() Befehls. Erzeugen Sie dazu eine Datei mit folgendem Inhalt in einem Verzeichnis unterhalb von wwwroot.
+
** ssl
 +
** proxy
 +
** proxy_http
 +
** proxy_html
 +
** xml2enc
 +
 
 +
* PHP - Die Entwicklung von kvwmap läuft derzeit auf der Version 7
 +
* Folgende Module werden für kvwmap installiert und müssen daher vorhanden sein
 +
** php-cli
 +
** php-curl
 +
** php-dev
 +
** php-gd
 +
** php-mbstring
 +
** php-mysql
 +
** php-pgsql
 +
** php-soap
 +
** php-sqlite3
 +
** php-xsl
 +
** php-zip 
 +
* Ob PHP richtig kompiliert wurde erkennen Sie durch die Ausgabe eines phpinfo() Befehls. Erzeugen Sie dazu eine Datei mit folgendem Inhalt in einem Verzeichnis unterhalb von wwwroot. oder fügen Sie dieses Programmschnipselchen in eine andere php Datei ein.
 
       <?php
 
       <?php
 
         phpinfo();
 
         phpinfo();
 
       ?>
 
       ?>
*:      oder fügen Sie dieses Programmschnipselchen in eine andere php Datei ein.
+
Die Funktion phpinfo zeigt dann an welche Module geladen sind.
*:      Das sollte dann eine Ausschrift erzeugen, die folgendes beinhaltet:
+
 
+
 
<div align="center">
 
<div align="center">
  
Zeile 1.911: Zeile 2.292:
 
Darin erkennt man ob MySQL, GD und PostgreSQL wirklich unterstützt werden und z.B. welche PostgresSQL-Version unterstützt wird.
 
Darin erkennt man ob MySQL, GD und PostgreSQL wirklich unterstützt werden und z.B. welche PostgresSQL-Version unterstützt wird.
  
Wenn die Angaben z.B. zu pgsql nicht zu finden sind, sollte man php mit --with-pgsql=/pgsql-install-pfad neu kompilieren und wieder die entstandene PHP aus /usr/local/php/sapi/cgi ins cgi-bin Verzeichnis vom Webserver kopieren und neu testen.
+
Informationen zu Einstellungen von php findet man sonst auch in der php.ini Datei. Nach dem Kompilieren von PHP gegebenenfalls php.ini anpassen:
 
+
Wenn das auch nichts bringt, greift das Lampp vielleicht auf eine ganz andere php zu, z.B. auf eine dynamisch geladene Bibliothek (libphp4.so). Testen durch das umbenennen von php in cgi-bin in php-bla. Danach sollte die Fehlermeldung vom Apache kommen, dass er die php-Datei nicht ausführen kann, oder der Quellcode gesendet werden, was dem gleich kommt. Dann suchen nach dem wahren Ort wo lampp php ausführt.
+
 
+
Informationen darüber findet man in den Anleitungen zum Ausführen von php in
+
 
+
Apache. In der httpd.conf steht zum Beispiel:   
+
 
+
LoadModule php4_module modules/libphp4.so
+
Um pgsql in libphp4.so nutzen zu können müsste man die pgsql Unterstützung eben da hinein kompilieren.
+
Alternativ dazu steht die Variante php als cgi-Version einzurichten mit den entsprechenden Optionen in der httpd.conf:
+
 
+
+
 
+
Action php-script /cgi-bin/php
+
 
+
+
 
+
#AddHandler cgi-script .cgi
+
 
+
AddHandler php-script .php .php3
+
 
+
+
 
+
Dann könnte man also php als CGI-Version kompilieren mit:
+
 
+
--with-regex=system
+
 
+
Dazu zur Sicherheit gibt man an:
+
 
+
--enable-force-cgi-redirect
+
 
+
Um anzugeben, wo die Konfigurationsdateien zu finden sind:
+
--with-config-file-path=/opt/lampp/etc
+
 
+
 
+
Nach dem Kompilieren von PHP gegebenenfalls php.ini anpassen:
+
  
 
  short_open_tag = On            - erlaubt den verk&uuml;rzten Tag f&uuml;r php  
 
  short_open_tag = On            - erlaubt den verk&uuml;rzten Tag f&uuml;r php  
session.auto_start = 1          - f&uuml;r Authentifizierung &uuml;ber PHP notwendig
 
 
  session.gc_maxlifetime = xxxx  - L&auml;nge der php-Session in Sekunden
 
  session.gc_maxlifetime = xxxx  - L&auml;nge der php-Session in Sekunden
  
 
* gd - wenn die Druckrotation funktionieren soll, gd nicht selbst kompilieren, sondern PHP kompilieren mit --with-gd
 
* gd - wenn die Druckrotation funktionieren soll, gd nicht selbst kompilieren, sondern PHP kompilieren mit --with-gd
* MapServer - Version ab 5.x wird empfohlen
+
* MapServer - Version ab 7.x wird empfohlen
*:  Zur Konfiguration von MapServer und damit auch phpMapScript wurden folgende Parameter gesetzt:
+
* Folgende Einstellungen werden für die Kompilierung von MapServer verwendet:
*: OUTPUT=PNG OUTPUT=JPEG OUTPUT=WBMP SUPPORTS=PROJ SUPPORTS=FREETYPE SUPPORTS=WMS_SERVER SUPPORTS=WMS_CLIENT INPUT=EPPL7 INPUT=POSTGIS INPUT=GDAL INPUT=SHAPEFILE
+
** -DWITH_PROTOBUFC=0
*:  Welche Optionen für configure wirklich notwendig sind, hängt davon ab welche Datenarten und welche Services der MapServer unterstützten soll.
+
** -DWITH_RSVG=1
* phpMapScript - ist in der Version: 1.194.2.3
+
** -DWITH_CAIRO=1
*:  phpMapScript wird mit installiert, wenn die Option –with-php angegeben wird.
+
** -DWITH_SVGCAIRO=0
* PDFClass – installieren in www-root Verzeichnis
+
** -DWITH_PHP=1
 +
** -DWITH_CLIENT_WMS=1
 +
** -DWITH_CLIENT_WFS=1
 +
* Folgende Funktionen muss MapServer dann erfüllen:
 +
** OUTPUT=PNG OUTPUT=JPEG SUPPORTS=PROJ SUPPORTS=AGG SUPPORTS=FREETYPE SUPPORTS=CAIRO SUPPORTS=SVG_SYMBOLS SUPPORTS=RSVG SUPPORTS=ICONV SUPPORTS=FRIBIDI SUPPORTS=WMS_SERVER SUPPORTS=WMS_CLIENT SUPPORTS=WFS_SERVER SUPPORTS=WFS_CLIENT SUPPORTS=WCS_SERVER SUPPORTS=FASTCGI SUPPORTS=GEOS SUPPORTS=POINT_Z_M INPUT=JPEG INPUT=POSTGIS INPUT=OGR INPUT=GDAL INPUT=SHAPEFILE
 +
* phpMapScript wird durch -DWITH_PHP mit MapServer installiert.
 +
* PDFClass ist Bestandteil von kvwmap
 
*: Quelle: http://www.ros.co.nz/pdf/
 
*: Quelle: http://www.ros.co.nz/pdf/
* Imagemagick und Ghostscript - zur Druckvorschau und Bildkonvertierung, siehe [[Installation_von_Imagemagick_mit_TIF-Support|Installation von ImageMagick mit JPEG-, PNG- und TIF-Unterstützung]]
+
* Imagemagick und Ghostscript - zur Druckvorschau und Bildkonvertierung, siehe [[Installation_von_Imagemagick_mit_TIF-Support|Installation von ImageMagick mit JPEG-, PNG- und TIF-Unterstützung]] ist im WebContainer enthalten und mit --with-rsvg=yes kompiliert.
* MySQL – irgendeine aktuelle Version, verwende noch Tabellentyp MyISAM, wer Transaktionen machen will braucht eine Version die InnoDB unterstützt.
+
* MySQL – Unterstützung von InnoDB erforderlich.
 
* phpMyAdmin
 
* phpMyAdmin
 
*:  Zur Administration der MySQL Datenbank kann phpMyAdmin installiert werden. Jedes andere DB-Frontend mit ODBC-Treiber für MySQL ist natürlich auch möglich. Ich benutze z.B. auch MS-Access mit MySQL-ODBC.
 
*:  Zur Administration der MySQL Datenbank kann phpMyAdmin installiert werden. Jedes andere DB-Frontend mit ODBC-Treiber für MySQL ist natürlich auch möglich. Ich benutze z.B. auch MS-Access mit MySQL-ODBC.
 
* PostgreSQL - Version ab 9.0
 
* PostgreSQL - Version ab 9.0
*: Zur Verwaltung von PostgreSQL setzten wir bei GDI-Service pgAdmin III ein. Es ginge aber auch phpPgAdmin wobei pgAdmin III schon etwas mächtiger ist. Voraussetzung hierfür ist eine Verbindung über TCP/IP über Port 5432 und die Freischaltung von Postgres für externe Zugriffe in postgres.conf und eventuell das Eintragen der eigenen IP in pg_hba.conf.
+
*: Zur Verwaltung von PostgreSQL setzten wir bei GDI-Service pgAdmin 4 ein. Es ginge aber auch phpPgAdmin wobei pgAdmin 4 schon etwas mächtiger ist. Voraussetzung hierfür ist eine Verbindung über TCP/IP über Port 5432 und die Freischaltung von Postgres für externe Zugriffe in postgres.conf und eventuell das Eintragen der eigenen IP in pg_hba.conf.
 
* PostGIS - Version ab 1.5
 
* PostGIS - Version ab 1.5
 
*: Die Verwaltung von Geometrie geht recht gut mit dem Desktop GIS QuantumGIS. Darin kann man direkt Tabellen mit PostGIS Geometrie als Layer einbinden um schnell mal was anzeigen zu lassen oder räumlich zu bearbeiten.
 
*: Die Verwaltung von Geometrie geht recht gut mit dem Desktop GIS QuantumGIS. Darin kann man direkt Tabellen mit PostGIS Geometrie als Layer einbinden um schnell mal was anzeigen zu lassen oder räumlich zu bearbeiten.
Zeile 1.996: Zeile 2.346:
 
Siehe auch: http://wiki.osgeo.org/index.php/Installation_von_MapServer%2C_Apache_und_PostgreSQL/PostGIS_auf_Debian_4.0
 
Siehe auch: http://wiki.osgeo.org/index.php/Installation_von_MapServer%2C_Apache_und_PostgreSQL/PostGIS_auf_Debian_4.0
 
http://en.giswiki.org/wiki/UMN_MapServer_Installationsanleitung_von_Kai_Behncke
 
http://en.giswiki.org/wiki/UMN_MapServer_Installationsanleitung_von_Kai_Behncke
http://freegis.org/pipermail/mapserver-de/2005-July/001408.html
 
  
 
UMN MapServer für Linux ist im Packet FGS und für Windows im Packet ms4w enthalten. Siehe dazu unter: http://www.maptools.org/fgs bzw. http://www.maptools.org/ms4w/
 
UMN MapServer für Linux ist im Packet FGS und für Windows im Packet ms4w enthalten. Siehe dazu unter: http://www.maptools.org/fgs bzw. http://www.maptools.org/ms4w/
Zeile 2.198: Zeile 2.547:
 
[[Datei:Konstanten.png]]
 
[[Datei:Konstanten.png]]
  
Die Konstanten sind in Gruppen aufgeteilt und für ausgewählte Plugins getrennt aufgeführt. Die Bedeutung der Konstanten ist in den meisten Fällen hinter der "i"-Schaltfläche hinterlegt.
+
Die Konstanten sind in Gruppen aufgeteilt und für ausgewählte [[Plugins]] getrennt aufgeführt. Die Bedeutung der Konstanten ist in den meisten Fällen hinter der "i"-Schaltfläche hinterlegt.
  
 
===Datenbankeinträge für die Anzeige im Client===
 
===Datenbankeinträge für die Anzeige im Client===
Zeile 2.369: Zeile 2.718:
  
 
*'''[[PostGIS in der fgs-dev Umgebung kompilieren]]'''
 
*'''[[PostGIS in der fgs-dev Umgebung kompilieren]]'''
 +
 +
=Docker Network=
 +
In diesem Abschnitt wird beschrieben wie das Netzwerk der von kvwmap genutzten Docker-Containern aufgebaut ist, wie man die darin befindlichen Container verwalten kann und wo die zugehörigen Daten zur Verwendung im GIS und für die Administration der Anwendung liegen. siehe Präsentation [[Medium:docker-network.pdf|docker-network.pdf]]
 +
== Netzwerkarchitektur ==
 +
[[Datei:netzwerk-architektur.png|800px|Netzwerk-Architektur]]
  
 
=Administration=
 
=Administration=
Zeile 2.451: Zeile 2.805:
 
Zum Anlegen einer neuen Stelle kann der Menüpunkt „Stelle Anlegen“ aus der Menügruppe „Stellenverwaltung“ verwendet werden.
 
Zum Anlegen einer neuen Stelle kann der Menüpunkt „Stelle Anlegen“ aus der Menügruppe „Stellenverwaltung“ verwendet werden.
  
Im Stelleneditor können folgende Einstellungen für die Stelle vorgenommen werden:
+
Das Formular ist in folgende Gruppen unterteilt:
Bezeichnung,  Referenzkarten ID, maximale Ausdehnung, EPSG-Code (der zur maximalen Ausdehnung passt), eine Datenbankverbindung, OWS-Parameter, das Wappen und ein Wappen-Link
+
* Stammdaten
 +
* Zuordnungen
 +
* Metadaten
 +
* Sonstiges
 +
Die Gruppe Metadaten ist defaultmäßig zugeklappt.
  
[[Datei:Stelleneditor1.png|600px|Stelleneditor Teil 1]]
+
[[Datei:Stelle-neu-anlegen.png|600px|Gruppen im Stelleneditor]]
  
Des Weiteren welche Menüpunkte in der Stellen zu sehen sein sollen, welche Funktionen erlaubt sind (muss nur angegeben werden, wenn die Funktion nicht in zugeordneten Menüpunkten aufgerufen wird), welche Karten und Sachdatendrucklayouts dazugehören, welche Layer in der Stelle genutzt werden können und welche Benutzer zu der Stelle gehören.
+
In der Gruppe Stammdaten können folgende Einstellungen für die Stelle vorgenommen werden:
 +
Bezeichnung, Referenzkarte, maximale Ausdehnung, EPSG-Code (der zur maximalen Ausdehnung passt), eine Datenbankverbindung, eine Wappendatei und ein Wappen-Link
 +
Für Referenzkarten wird eine Auswahlliste angeboten. Soll eine Referenzkarte für die Stelle verwendet werden, die noch nicht in der Auswahl erscheint, ist zuvor eine neue Referenzkarte in der MariaDB-Tabelle referenzkarten zu registrieren. Die Datei mit der Referenzkarte ist in dem Verzeichis zu hinterlegen, welches in der Konstante '''REFERENCEMAPPATH''' angegeben ist.
  
[[Datei:Stelleneditor2.png|600px|Stelleneditor Teil 2]]
+
Die maximale Ausdehnung ist in dem EPSG-Code anzugeben, der bei EPSG-Code eingetragen ist.
 +
x ist der Rechtswert und y der Hochwert. Damit werden die Koordinaten in der Reihenfolge West, Süd, Ost, Nord angegeben.
  
Des Weiteren können die in der folgenden Abbildung aufgeführten Parameter eingestellt werden:
+
[[Datei:Stelleformular-Stammdaten.png|600px|Stelleneditor Stammdaten]]
* IP-Adresse des Nutzers überprüfen. Wenn das eingestellt ist, kann der Nutzer nur auf die Stelle zugreifen, wenn die IP-Adresse von der der Nutzer zugreift beim Nutzer eingetragen ist. Siehe Nutzerverwaltung
+
 
 +
In der Gruppe Zuordnungen können der Stelle folgende Dinge zugeordnet werden:
 +
* Menüpunkte
 +
* Funktionen
 +
* Kartendruck-Layouts
 +
* Datendruck-Layouts
 +
* Layer
 +
* Benutzer
 +
* Übergeordnete Stellen
 +
* Untergeordnete Stellen
 +
 
 +
Die Zuordnung erfolgt jeweils durch Selektion ein oder mehrerer Werte in der rechten Box (verfügbare) und klicken auf den Doppelpfeil der nach links zeigt. Die Boxen für verfügbare Menüpunkte und Layer sind zweigeteilt. Im obigen Teil kann eine ganze Gruppe ausgewählt werden. Sind in der Gruppe einzelne Menüpunkte bzw. Layer enthalten, können im unteren Teil der Box einzelne für die Übernahme ausgewählt werden.
 +
 
 +
Eine Zuordnung kann aufgehoben werden durch Selektion ein oder mehrerer Werte in der linken Box (zugeordnete) und klicken auf den Doppelpfeil der nach rechts zeigt.
 +
 
 +
Die Zuordnungen sowie auch alle anderen Änderungen im Formular werden erst wirksam wenn das Formular gespeichert wird.
 +
 
 +
Eine Funktion muss nur zugeordnet werden, wenn die Funktion nicht schon in zugeordneten Menüpunkten aufgerufen wird.
 +
 
 +
Die Zuordnung von über- zu untergeordneten Stellen muss zueinander passen.
 +
 
 +
[[Datei:Stelleformular-Zuordnung1.png|600px|Zuordnungen Teil 1]]
 +
 
 +
[[Datei:Stelleformular-Zuordnung2.png|600px|Zuordnungen Teil 2]]
 +
 
 +
[[Datei:Stelleformular-Zuordnung3.png|600px|Zuordnungen Teil 3]]
 +
 
 +
In der Gruppe Metadaten können Beschreibungen angeben werden, die für die Veröffentlichung von Diensten (Capabilities) und in Datensatz-Metadaten Verwendung finden. Die Daten können auch für die interne Beschreibung von Stellen in kvwmap verwendet werden.
 +
 
 +
Die zur Stelle gehörenden Metadaten lassen sich in jeder Stelle gesondert bearbeiten, wenn es in der Stelle einen Menüpunkt mit dem Anwendungsfall '''Dienstmetadaten''' (index.php?go=Dienstmetadaten) gibt. Damit können Nutzer einer Stelle die Metadaten der Stelle selber pflegen.
 +
Das Formular ist aufgeteilt in allgemeine Metadaten wie Titel, Kurzbeschreibung, Zugangsbeschränkung, Kosten und Referenzsystem den Angaben über die Stelle, die für die Metadaten verantwortlich sowie die Stellen, die verantwortlich sind für die Inhalte und die Veröffentlichung. Die Metadatenelemente, die in INSPIRE- und ISO-konformen Metadatendokumenten Pflicht sind, sind mit '''*''' gekennzeichnet.
 +
 
 +
[[Datei:Stellenformular-Metadaten1.png|600px|Allgemeine Metadaten und Verantwortlicher für die Metadaten]]
 +
 
 +
[[Datei:Stelleformular-Metadaten2.png|600px|Kontakt zum Verantwortlichen über den Inhalt der Geodaten]]
 +
 
 +
[[Datei:Stelleformular-Metadaten3.png|600px|Kontakt zum Verantwortlichen für den Vertrieb der Daten]]
 +
 
 +
In der Gruppe Sonstiges können die folgenden Parameter eingestellt werden:
 +
* Wird ein Standardnutzer für die Stelle ausgewählt, werden dessen Rolleneinstellungen für alle Nutzer initial übernommen, wenn die Nutzer dieser Stelle neu zugewiesen werden, es sei den es handelt sich bei der Zuweisung um den Standardnutzer selbst, denn sonst könnte man dem Standardnutzer niemals andere Einstellungen zuordnen als die, die er schon hat.
 +
* ob durch andere freigegebene Layer in dieser Stelle angezeigt werden können sollen.
 +
* IP-Adresse des Nutzers überprüfen. Wenn das eingestellt ist, können Nutzer nur auf die Stelle zugreifen, wenn die IP-Adresse von der der Nutzer aus zugreift beim Nutzer eingetragen ist. Siehe [[Admin-Dokumentation#Nutzerverwaltung|Nutzerverwaltung]]
 
* Alter von Passwörtern in dieser Stelle prüfen.
 
* Alter von Passwörtern in dieser Stelle prüfen.
 
* Erlaubtes Alter von Passwörtern, wenn es geprüft wird (in Monaten)
 
* Erlaubtes Alter von Passwörtern, wenn es geprüft wird (in Monaten)
 
* Layer-Aliasnamen verwenden
 
* Layer-Aliasnamen verwenden
 
* historische Zeitstempel zulassen
 
* historische Zeitstempel zulassen
* Standardnutzer, Wird ein Standardnutzer für die Stelle ausgewählt, werden dessen Rolleneinstellungen für alle Nutzer initial übernommen, wenn die Nutzer dieser Stelle neu zugewiesen werden, es sei den es handelt sich bei der Zuweisung um den Standardnutzer selbst, denn sonst könnte man dem Standardnutzer niemals andere Einstellungen zuordnen als die, die er schon hat.
+
* Kommentar welcher für Hinweise gedacht ist, die ein oder mehrere Administratoren verwalten.
  
[[Datei:Stelleneditor3.png|400px|Stelleneditor Teil 3]]
+
[[Datei:Stelleformular-Sonstiges.png|600px|Stelleneditor, sonstige Angaben]]
  
 
===Stellen anzeigen===
 
===Stellen anzeigen===
  
Über den Menüpunkt „Stellen anzeigen“ der Menügruppe Stellenverwaltung können Stellen angezeigt werden, gelöscht und geändert werden.
+
Über den Menüpunkt '''Stellen anzeigen''' der Menügruppe '''Stellenverwaltung''' können Stellen gelistet und sortiert werden. Zu jeder Stelle gibt es Links zum Stelleneditor (siehe [[Admin-Dokumentation#Stelle_anlegen|Stelle anlegen]]), den zur Stelle zugeordneten Layern (siehe [[Admin-Dokumentation#Stellenbezogene_Layereigenschaften|stellenbezogene Layereigenschaften]] und zum Löschen der Stelle.
 +
 
 +
[[Datei:Edit-Layer-Loeschenbutton.png|100px|Button in der Stellenanzeige.]]
  
 
===Stellen ändern===
 
===Stellen ändern===
  
Zur Änderung von Stellen siehe „Stelle anlegen“.
+
Zur Änderung von Stellen siehe [[Admin-Dokumentation#Stelle_anlegen|Stelle anlegen]].
  
 
===Maximale Ausdehnung des Kartenfensters für eine Stelle ändern===
 
===Maximale Ausdehnung des Kartenfensters für eine Stelle ändern===
Zeile 2.548: Zeile 2.952:
  
 
==Nutzerverwaltung==
 
==Nutzerverwaltung==
 +
Die Nutzerverwaltung erreicht man über den Menüpunkt Nutzerverwaltung.
 +
In der Nutzerverwaltung kann man die existierenden Nutzer anzeigen, Neu anlegen oder in einer Übersicht zugeordnet zu Stellen auflisten lassen.
 +
 +
[[Datei:Nutzerverwaltung.png]]
 +
 
===Authentifizierung über PHP===
 
===Authentifizierung über PHP===
 
Seit der Version 1.6.5 erfolgt die Authentifizierung über PHP und die für die Nutzereinstellungen verwendete MySQL Datenbank. Das PHP Skript prüft ob ein Benutzer sich bereits authentifiziert hat, wenn nicht, erscheint ein Dialog zur Eingabe von Benutzername und Passwort. Nach absenden diese Formulares wird in der MySQL Datenbank von kvwmap nachgesehen ob der Benutzername zum Passwort passt.
 
Seit der Version 1.6.5 erfolgt die Authentifizierung über PHP und die für die Nutzereinstellungen verwendete MySQL Datenbank. Das PHP Skript prüft ob ein Benutzer sich bereits authentifiziert hat, wenn nicht, erscheint ein Dialog zur Eingabe von Benutzername und Passwort. Nach absenden diese Formulares wird in der MySQL Datenbank von kvwmap nachgesehen ob der Benutzername zum Passwort passt.
Zeile 2.631: Zeile 3.040:
 
===Nutzer ändern===
 
===Nutzer ändern===
  
Um Nutzerdaten zu ändern wählen Sie erst „Nuter anzeigen“ und dann „ändern“ oder „löschen“.
+
Um Nutzerdaten zu ändern wählen Sie erst Nutzerverwaltung > Nuter anzeigen. Damit werden alle Nutzer, die nicht archiviert sind angezeigt.
 +
 
 +
[[Bild:Nutzer anzeigen.png|1000px|Nutzer Anzeigen]]
 +
 
 +
Durch anklicken des Nutzernamen gelangt man in das Formular zur Bearbeitung der Nutzerdaten.
 +
 
 +
[[Bild:Nutzerdaten_aendern.jpg|Nutzerdatenformular]]
 +
 
 +
Die Zustimmung zu den Nutzungsbedingungen kann durch den Administrator zurückgenommen werden. Dadurch wird der Nutzer gezwungen den Nutzungsbedingungen erneut zuzustimmen, z.b. wenn diese geändert wurden.
 +
[[Bild:agreement_accepted.png]]
 +
 
 +
 
 +
Soll das Passwort geändert werden auf den Link "Passwort ändern" klicken.
 +
 
 +
[[Bild:Passwort_aendern.png]]
 +
 
 +
===Nutzerübersicht===
 +
Die Nutzerübersicht zeigt die aktiven Nutzer gruppiert nach den Stellen in denen sie zugeordnet sind.
 +
 
 +
[[Bild:Nuteruebersicht.png|Nutzerübersicht]]
 +
 
 +
Über die Nutzerübersicht gelangt man auch zu den Nutzerdatenformularen und kann Nutzer löschen bzw. archivieren.
 +
===Nutzer archivieren===
 +
 
 +
Wenn die Konstante Administration > NUTZER_ARCHIVIEREN auf true gesetzt ist, werden Nutzer beim Löschen in der Tabelle user nicht gelöscht, sondern der Flag archived auf das aktuelle Datum gesetzt.
 +
 
 +
Archivierte Nutzer erscheinen nicht mehr in der Liste der Nutzer in der Nutzerverwaltung und können sich auch nicht mehr am System anmelden. Um archivierte Nutzer wieder zu aktivieren ist der Flag archived in der Tabelle user auf NULL zu setzen.
  
 
==Layer-Definition==
 
==Layer-Definition==
Zeile 2.675: Zeile 3.110:
 
===Neuen Layer anlegen===
 
===Neuen Layer anlegen===
  
kvwmap bietet eine Admin-Oberfläche zum Erstellen und Bearbeiten von Layern: Den Layereditor (go=Layereditor). Layer sollten immer über den Layereditor angelegt werden, da kvwmap aus den Eintragungen der Layerdefintion (insbesondere dem Query-Feld) etliche Ableitungen erstellt, z.B. zur Definition der Attribute des Layers. Ein händisches Eintragen eines Layers in der MySQL-Datenbank ist möglich, ist aber sehr aufwändig und fehleranfällig, da in diversen Tabellen zwingend Eintragungen gemacht werden müssen, damit der Layer funktioniert.
+
kvwmap bietet eine Admin-Oberfläche zum Erstellen und Bearbeiten von Layern: Den Layereditor (go=Layereditor). Layer sollten immer über den Layereditor angelegt werden, da kvwmap aus den Eintragungen der Layerdefintion (insbesondere dem Query-Feld) etliche Ableitungen erstellt, z.B. zur Definition der Attribute des Layers. Ein händisches Eintragen eines Layers in der MySQL-Datenbank ist auch möglich, aber sehr aufwändig und fehleranfällig, da in diversen Tabellen zwingend Eintragungen gemacht werden müssen, damit der Layer funktioniert.
 +
Wenn ein neuer Layer angelegt wird (ohne Layer-ID) ist das Formular leer, enthält aber ein Auswahlfeld für die Connection.
  
[[Datei:LayerEditor1.png]]
+
[[Datei:Bildschirmfoto 2024-02-05 um 14.40.28.png]]
 +
 
 +
Wird hier eine Connection ausgewählt werden alle Tabellen in eine weitere Auswahlliste geladen. Wenn hier eine Tabelle ausgewählt wird, befüllt sich das Formular mit den Angaben zur Tabelle. Wird dieses Formular so gespeichert entsteht ein Layer, der den Inhalt dieser Tabelle darstellt. Hat die Geometrie eine Tabelle wird auch der Geometrietyp eingetragen sonst ist es ein einfacher Abfragelayer.
 +
 
 +
[[Datei:Bildschirmfoto 2024-02-05 um 14.47.20.png]]
 +
 
 +
Die folgenden Felder werden automatisch ausgefüllt: Name, Alias, Datentyp, Connection-Typ, Connection, EPSG-Code, Query, Data, Haupttabelle, ID-Spalte, Schema, Tolleranzunits=pixels. Vor dem Speichern können natürlich auch noch Änderungen vorgenommen werden. Die Gruppe muss immer manuell ausgewählt werden, weil sie eine Pflichtangabe ist und nicht automatisch ausgewählt werden kann.
 +
 
 +
Wird ein Layer ausgewählt oder das Formular mit einer Layer-ID im Parameter selected_layer_id aufgerufen erscheint das Formular mit allen bisherigen Einträgen zum Layer und kann bearbeitet werden.
 +
 
 +
[[Datei:LayerEditor2.png|950px]]
 +
 
 +
[[Datei:LayerEditor_Sachdaten.png|950px]]
 +
 
 +
[[Datei:Layereditor3.png|950px]]
 +
 
 +
[[Datei:plugin layer attributes.png|950px]]
 +
 
 +
[[Datei:Layereditor4.png|950px]]
  
 
Die wichtigsten Einstellungen zum Layer sind die '''Basisparameter'''. Hier wird u.a. der Name, die Connection, das Query- und Data-SQL sowie das Koordinatensystem des Layers definiert. Bis auf den Aliasnamen müssen alle diese Felder befüllt sein, damit der Layer funktioniert.  
 
Die wichtigsten Einstellungen zum Layer sind die '''Basisparameter'''. Hier wird u.a. der Name, die Connection, das Query- und Data-SQL sowie das Koordinatensystem des Layers definiert. Bis auf den Aliasnamen müssen alle diese Felder befüllt sein, damit der Layer funktioniert.  
  
Darüberhinaus gibt es weitere Felder, die für die '''Kartendarstellung''' des Layers verwendet werden. Die meisten dieser Felder sind Mapserver-Einstellungen. Eine ausführliche Beschreibung dieser Mapserver-Layer-Parameter findet sich auf der Seite [https://mapserver.org/mapfile/layer.html].  
+
Darüberhinaus gibt es weitere Felder, die für die '''Kartendarstellung''' des Layers verwendet werden. Die meisten dieser Felder sind Mapserver-Einstellungen. Eine ausführliche Beschreibung dieser Mapserver-Layer-Parameter findet sich in der [https://mapserver.org/mapfile/layer.html MapServer Doku].
 +
 
 +
Über die Stift-Icons neben der Gruppe gelangt man in den Gruppeneditor und neben der Connection zum Editor der Connections.  
  
 
Im Abschnitt '''Sachdaten''' können Einstellungen vorgenommen werden, die die Sachdatenausgabe des Layers betreffen. Hier kann z.B. eingestellt werden, wieviele Datensätze auf einmal bei einer Sachdatenabfrage angezeigt werden sollen, wie die Dateien für diesen Layer abgelegt werden sollen oder welche Toleranz bei der Kartenabfrage berücksichtigt werden soll. Über das Feld "DDL Default Attribut" kann festgelegt werden, welches Sachdatendrucklayout standardmäßig vorausgewählt sein soll.
 
Im Abschnitt '''Sachdaten''' können Einstellungen vorgenommen werden, die die Sachdatenausgabe des Layers betreffen. Hier kann z.B. eingestellt werden, wieviele Datensätze auf einmal bei einer Sachdatenabfrage angezeigt werden sollen, wie die Dateien für diesen Layer abgelegt werden sollen oder welche Toleranz bei der Kartenabfrage berücksichtigt werden soll. Über das Feld "DDL Default Attribut" kann festgelegt werden, welches Sachdatendrucklayout standardmäßig vorausgewählt sein soll.
Zeile 2.687: Zeile 3.143:
 
Unter '''OWS-Parameter''' befinden sich Felder, die für die Verwendung von WMS- und WFS-Diensten verwendet werden.
 
Unter '''OWS-Parameter''' befinden sich Felder, die für die Verwendung von WMS- und WFS-Diensten verwendet werden.
  
Unter '''Metadaten''' kann eine Kurzbeschreibung, der Datenherr und ein Metadatenlink mit ausführlichen Informationen zum Layer definiert werden.
+
Wenn die Option "Schreibe Mapserver Templates" gesetzt ist, wird für den Layer jeweils beim Speichern eine zum Data-Statement oder der Haupttabelle passende MapServer Header und Template Datei in das Verzeichnis " . WMS_MAPFILE_PATH . "templates/ geschreiben. Der generische Ansatz der auf der Haupttabelle basiert, erzeugt zu Codelisten und Enumerations, wie sie für XPlanung und im AAA-Modell verwendet werden, jeweils Attribute mit Textausgabe in der auch die Beschreibungen und ggf. der Codespace enthalten sind. Der Pfad zum templates Ordner kann in der Konstante WMS_MAPFILE_PATH angepasst werden. Ist das Verzeichnis noch nicht vorhanden wird es angelegt. Der Dateiname setzt sich zusammen aus dem Layernamen sowie dem Zusatz _head.html bzw. _body.html. Ist die Datei schon vorhanden, wird sie überschrieben. Als Layername wird der Name der beim Speichern eingestellten Sprache genommen.
 +
 +
 
 +
Unter '''Metadaten''' kann eine Kurzbeschreibung, Quellenangabe, der Ansprechpartner (Datenherr), dessen Telefonnummer und E-Mail-Adresse sowie Angaben zur Aktualität, Aktualisierungsrate und ein Metadatenlink für ausführlichere Informationen zum Layer hinterlegt werden.
 +
 
 +
Wenn [[Plugins]] geladen sind, kann es sein dass zusätzliche Layerparameter angezeigt werden. Im Beispiel sind die Attribute cluster_option aus dem [[Plugins#Portal_.28f.C3.BCr_kvportal.29|Plugin portal]] sowie die Attribute sync und vector_tile_url aus dem [[Plugins#Mobile_.28f.C3.BCr_kvmobile.29|Plugin mobile]] dargestellt.  
  
 
Eine umfassende Erläuterung aller Layer-Einstellungen findet sich in der [[Admin-Dokumentation#Tabelle_.22layer.22|Referenz zur MySQL-Datenbank von kvwmap]].
 
Eine umfassende Erläuterung aller Layer-Einstellungen findet sich in der [[Admin-Dokumentation#Tabelle_.22layer.22|Referenz zur MySQL-Datenbank von kvwmap]].
Zeile 2.831: Zeile 3.292:
 
Die Verwendung von Umlauten, Leerzeichen, Schrägstrichen oder sonstigen Sonderzeichen in Verzeichnissen und Dateinamen sollte vermieden werden.
 
Die Verwendung von Umlauten, Leerzeichen, Schrägstrichen oder sonstigen Sonderzeichen in Verzeichnissen und Dateinamen sollte vermieden werden.
 
<br><br>
 
<br><br>
 +
 +
===Layer-Metadaten===
 +
Die Metadaten zum Layer dienen der Beschreibung des Layers. Sie werden an folgenden Stellen zur Dokumentation der Layer verwendet.
 +
* Die Kurzbeschreibung wird als Abstract für die Veröffentlichungen des Layers im Dienst (go=OWS) oder für den Export von Map-Dateien, z.B. beim WMS-Export und beim Erzeugen von Dienstdateien (go=create_geoweb_service) im Plugin [https://kvwmap.de/wiki/index.php/Plugins#xplankonverter xplankonverter] verwendet.
 +
* Die Kurzbeschreibung und der Metadatenlink werden in der Themenübersicht (go=Layer_Uebersicht) verwendet.
 +
* Alle Metadaten außer Metadatenlink, Version und Kommentar werden beim Layerdef-Export zur Darstellung der Layer-Info in [https://kvwmap.de/wiki/index.php/Plugins#Portal_.28f.C3.BCr_kvportal.29 kvmportal] verwendet.
 +
* Die Quellenangaben werden beim Klick auf den © Button links unter der Karte in kvmwap und auch in kvportal als Urheberrechte angezeigt.
 +
 +
====Quellenangaben====
 +
Es können eine oder mehrere Quellenangaben pro Layer aus einer definierten Liste ausgewählt werden.
 +
 +
[[Datei:Urheberrechte.png]]
 +
 +
Zum Hinzufügen einer Quelle wird der [[Datei:Plus-Button.png]] Button verwendet. Daraufhin erscheint eine Auswahlliste.
 +
 +
[[Datei:Datasource-Auswahlliste.png]]
 +
 +
Wird eine Datasource angeklickt, erscheint diese als ausgewählte Datasource des Layers. Es können mehrere ausgewählt werden.
 +
 +
[[Datei:2Datasources.png]]
 +
 +
Über den [[Datei:Stift-Button.png]] Button gelangt man in die Liste der eingetragenen Datenquellen. Dort können neuer hinzugefügt und vorhandene geändert und gelöscht werden.
 +
 +
[[Datei:Quellenangaben Formular.png]]
 +
 +
Der Name wird als Copy-Right-Info in kvportal verwendet.
 +
 +
Der Text der Beschreibung wird für den Layer angezeigt wenn man unter der Karte auf den Copy-Right-Button klickt. Wenn am Ende des Textes getrennt durch ein ; ein Link beginnend mit http steht, wird der Text davor als Link dargestellt der auf die angegebene URL zeigt.
  
 
===Layer-Klassifizierung===
 
===Layer-Klassifizierung===
Zeile 2.854: Zeile 3.343:
 
  ('[textattribut]' = 'text')
 
  ('[textattribut]' = 'text')
 
  ('[textattribut]' eq 'text')
 
  ('[textattribut]' eq 'text')
  ('[textattribut]' != 'text')  
+
  ('[textattribut]' != 'text')
 +
('[textattribut]' != <nowiki>''</nowiki>)  
 
* Beispiele Schreibweise für numerische Vergleiche:
 
* Beispiele Schreibweise für numerische Vergleiche:
 
  ([numerisches attribut] = 1234)
 
  ([numerisches attribut] = 1234)
 +
([numerisches attribut] eq 1234)
 
  ([numerisches attribut] > 1234)
 
  ([numerisches attribut] > 1234)
 +
([numerisches attribut] gt 1234)
 +
([numerisches attribut] >= 1234)
 +
([numerisches attribut] ge 1234)
 
  ([numerisches attribut] > 1234 and [numerisches attribut] < 2345)  
 
  ([numerisches attribut] > 1234 and [numerisches attribut] < 2345)  
 
* Schreibweise für boolsche Vergleiche:
 
* Schreibweise für boolsche Vergleiche:
  ('[boolean attribut]' eq 't')
+
  <s>('[boolean attribut]' eq 't')
  ('[boolean attribut]' eq 'f')
+
  ('[boolean attribut]' eq 'f')</s>
: Mehr Informationen zu den Möglichkeiten der EXPRESSION siehe [http://mapserver.org/de/mapfile/class.html mapserver.org].
+
Für boolsche Attribute am besten im Data-Statement das Attribut in ein numerisches umwandeln und dieses dann zur Klassifizierung nutzen:
 +
CASE WHEN bool_att THEN 1 ELSE 0 END AS class_att
 +
Im Klasseneditor kann dann anhand class_att nach 1 und 0 klassifiziert werden.<br><br>
 +
Mehr Informationen zu den Möglichkeiten der EXPRESSION siehe [http://mapserver.org/de/mapfile/class.html mapserver.org].
 
<br><br>
 
<br><br>
  
Zeile 2.875: Zeile 3.372:
 
* Style und gegebenfalls Label der neuen Klasse müssen definiert werden.
 
* Style und gegebenfalls Label der neuen Klasse müssen definiert werden.
 
<br><br>
 
<br><br>
 +
 +
===Diagramme in der Sachdatenanzeige===
 +
Zu Vektorlayern aus der PostGIS-Datenbank können ein oder mehrere Diagramme definiert werden. Die definierten Diagramme des Layers werden im Layereditor am Ende vom Abschnitt Sachdaten angezeigt.
 +
 +
[[Datei:Liste-in-Layerformular.png]]
 +
 +
Mit Betätigung des Stift-Button können die vorhandenen Diagramme gelistet, geändert, gelöscht und neue hinzugefügt werden. Es gibt keine gesonderten Menüpunkte zum Editieren von Diagrammen. Man kann nur über den Layereditor oder über die Sachdatenanzeige zu den Diagrammenlisten und -formularen gelangen.
 +
 +
Ein Menü-Link zur Diagrammliste eines Layers mit der ID 9 benötigt die Parameter go=layer_charts_Anzeigen und layer_id=9.
 +
 +
[[Datei:Liste Diagramme.png]]
 +
 +
Das Anlegen und Ändern von Diagrammen erfolgt im Formular layout/snippets/layer_chart_formular.php.
 +
 +
[[Datei:Formular Diagramm.png]]
 +
 +
Die Diagramme werden in der Tabelle layer_charts gespeichert welche folgende Attribute enthält:
 +
* layer_id integer not null: Id des Layers zu dem das Diagramm gehört. Wird im Editor nicht angezeigt. Der Titel des Layers ist aber im Formular zu sehen.
 +
* Diagramm ID, id integer not null autoincrement: Fortlaufende id zur identifizierung des Diagramms.
 +
* Diagrammtitel, title varchar(255): Bezeichnung des und Überschrift über dem Diagramms.
 +
* Diagrammtyp, type enum('bar','pie','doughnut') not null default 'bar': Diagrammtyp.der Berechnung des Hochwertes im Diagramm.
 +
* Beschriftung Balken, value_attribute_label varchar(100):
 +
* Aggregationsfunktion, aggregate_function enum('sum', 'average', 'min', 'max'): Art
 +
* Werteattribut (Hochwert), value_attribute_name varchar(65): Name des Attributes dessen Werte für die Berechnung des Hochwertes verwendet werden.
 +
* Beschriftungsattribut (Rechtswert):, label_attribute_name varchar(65): Name des Attributes nach dem klassifiziert wird und dessen Werte als Beschriftung an der Rechtsachse verwendet werden.
 +
* Beschreibung, beschreibung: Ein Freitextfeld zur Beschreibung des Inhaltes des Diagramms
 +
* Breite, breite: Die Breite in der das Diagram maximal angezeigt werden soll. In Pixel (px) oder Prozent (%). Die Angabe ist Pflicht.
 +
 +
Die Diagramme werden am Ende einer Sachdatenanzeige in einer separaten Gruppe, die aufgeklappt werden muss angezeigt.
 +
 +
[[Datei:Diagramme Gruppe Sachdatenanzeige.png]]
 +
 +
Als Diagrammtyp können über die Auswahlliste die Typen Balken, Torten und Doughnut gewählt werden. Das Diagramm passt sich jeweils automatisch an.
 +
 +
[[Datei:Flächenanteile Säulendiagram.png]] [[Datei:Flächenanteile donat.png]]
 +
 +
Fährt man mit der Maus über ein Segment des Diagramms wird der konkrete Wert, z.B. die Flächensumme für die Kategorie angezeigt.
 +
 +
[[Datei:Flächenanteile Bebauung.png]]
 +
 +
Interessiert man sich nur für das Verhältnis von innerhalb und außerhalb, kann man Sonstiges durch anklicken ausblenden, die Beschriftung wird durchgestrichen und das Diagramm zeigt nur noch innerhalb und außerhalb an.
 +
 +
[[Datei:Verhältnis-innerhalb-außerhalb.png]]
 +
 +
Mit dem '''Bearbeiten'''-Button kommt man zum Änderungsformular. Der Button wird nur angezeigt wenn in der Stelle der Menüpunkt mit dem Anwendungsfall "Layereditor" zur Verfügung steht oder die Funktion "Layereditor" zugeordnet ist die Funktion user->is_case_allowed für den angemeldeten Nutzer true liefert. Also wenn der Nutzer den Layer auch bearbeiten darf. (In der Regel nur Administratoren)
 +
 +
'''Voraussetzung für die Funktion:''' Für die Erzeugung der Diagramme wird die Bibliothek [https://www.chartjs.org Chart.js] eingesetzt. Die Datei chart.js muss im THIRDPARTY_PATH unter dem Verzeichnis Chart abgelegt sein. Der View für die Darstellung der Diagramme befindet sich in kvwmap unter layouts/snippets/layer_charts.php, die Funktionen im gleichen Verzeichnis in layer_chart_functions.php.
  
 
===Chart Layer===
 
===Chart Layer===
Zeile 2.919: Zeile 3.463:
 
Der Layer kann direkt im Layereditor einer oder mehreren Stellen zugeordnet werden. Über den Stelleneditor (go=Stellen_Anzeigen) kann die Zuordnung von Layern zu einer Stelle ebenfalls erfolgen. Die Defaults aus der Layerdefinition (zur Zeichenreihenfolge, zum Maßstabsbereich usw.) werden in der Zuordnung verwendet und müssen gegebenenfalls stellenabhängig im Nachgang angepasst werden. Sind in der Layer-Rechteverwaltung (go=Layerattribut-Rechteverwaltung) bereits Default-Rechte für den Layer vergeben, so werden diese bei der Zuordnung eines Layers zu einer Stelle gesetzt.
 
Der Layer kann direkt im Layereditor einer oder mehreren Stellen zugeordnet werden. Über den Stelleneditor (go=Stellen_Anzeigen) kann die Zuordnung von Layern zu einer Stelle ebenfalls erfolgen. Die Defaults aus der Layerdefinition (zur Zeichenreihenfolge, zum Maßstabsbereich usw.) werden in der Zuordnung verwendet und müssen gegebenenfalls stellenabhängig im Nachgang angepasst werden. Sind in der Layer-Rechteverwaltung (go=Layerattribut-Rechteverwaltung) bereits Default-Rechte für den Layer vergeben, so werden diese bei der Zuordnung eines Layers zu einer Stelle gesetzt.
 
<br><br>
 
<br><br>
 +
 +
=== Stellenbezogene Layereigenschaften ===
 +
Über den Menüpunkt '''Stellenverwaltung''' > '''Stellen anzeigen''' gelangt man zur Übersicht der Layer, die zu der jeweiligen Stelle gehören. [[Datei:Layer-der-Stelle-Button.png|30px|Button zur Übersicht der stellenbezogenen Layereigenschaften]]
 +
 +
Darin können die Zeichen- und Legendenreihenfolge der Layer in der Stelle am Stück angepasst sowie zu den stellenbezogenen und Layereinstellungen gewechselt werden.
 +
 +
[[Datei:Stellenbezogene-Layereinstellungen.png|600px|Übersicht der stellenbezogene Layereinstellungen]]
 +
 +
Für die Änderung allgemeiner Layereieigenschaften wird in den [[Admin-Dokumentation#Neuen_Layer_anlegen | Layereditor]] gewechselt, siehe auch [[Admin-Dokumentation#Der_Generische_Layereditor_GLE | GLE]].
 +
Die stellenbezogenen Layereigenschaften werden in einem gesonderten Formular bearbeitet.
 +
 +
[[Datei:StellenbezogeneLayereigenschaften.png]]
 +
 +
Die in diesem Editor vorgenommen Einstellungen wirken sich auf den Layer nur in der gewählten Stelle aus. Werden hier keine Angaben geändert gelten die Default-Werte des Layers, die im Layereditor gesetzt sind. Wird im Layereditor im Tab "Stellen-Zuweisung" der Link "Default-Werte an Stellen übertragen" angeklickt werden die stellenbezogenen Eigenschaften des Layers in allen Stellen auf Default gesetzt zu denen der Layer gerade zugeordent ist.
 +
* Unter Layergruppen kann man eine Layergruppe auswählen zu der der Layer nur in dieser Stelle gehören soll.
 +
* Layer können in der Karte nur abgefragt werden wenn in abfragbar ja ausgewählt wird. Geometrie übernehmbar bezieht sich auf die Übernahme von Geometrien im Geometrieeditor. Layer bei denen hier nein steht erscheinen nicht in der Auswahl der Layer von denen Geometrien übernommen werden können.
 +
* Unter Offsite kann eine Farbe angegeben werden die Transparent dargestellt werden soll, mit den 3 RGB Werten: "0 0 0", RGB hexadecimal: "#rrggbb" oder RGBA (translucence): "#rrggbbaa". Die Eigenschaft wirken sich nur auf Rasterlayer aus.
 +
* Transparency wird in % angegeben. Höhere Werte sind mehr durchscheinend.
 +
* Wenn Post label cache eingeschaltet ist, werden die Texte des Layers erst ganz zum Schluss über allen anderen Layern gezeichnet.
 +
* Der Filter grenzt die in der Karte und Sachdatenanzeige dargestellten Feature des Layers ein. Es wird ein WHERE Ausdruck erwartet. Mehrere können mit logischen Operatoren AND, OR usw. verknüpft werden.
 +
* Template, Header und Footer werden nur verwendet wenn der Layer in einem WMS ausgegeben werden soll. Die Vorlagen werden dann für die HTML-Ausgabe von GetFeatureInfo-Anfragen verwendet.
 +
* Symbol scale gibt an in welchem Maßstab die Styles die angegebene normale Größe haben sollen. Wird der Maßstab größer werden auch die Symbole größer wenn z.B. Max-Width größere Werte hat als Width und umgekehrt kleiner wenn der Maßstab kleiner wird. (Für die Maßstabszahl gilt das Reziproke)
 +
* Unter Requires kann ausgewählt werden zu welchem anderen Layer dieser Layer gehören soll. Wird hier ein andere ausgewählt, erscheint der Layer aus diesem Formular nicht mehr in der Legende, nur seine Klassen falls er welche hat. Wird der bei Requires ausgewählte Layer in der Legende der Karte eingeschaltet erscheinen auch die Features der Layer die diesen als Requires eingestellt haben. Abfragen in der Karte fragen gleichzeitig auch die mit Requires zugeordneten Layer ab. So kann man mehrere Layer wie einen Layer aussehen lassen.
 +
* Layer bei denen "aktiv bei Gast" ausgewählt ist sind in Gast-Stellen nach dem Anmelden immer aktiv gestellt.
 +
* Aktivitäten von Layern für die "wird geloggt" eingeschaltet ist, können vom Admin geloggt werden.
  
 
==Layergruppenverwaltung==
 
==Layergruppenverwaltung==
Zeile 2.930: Zeile 3.499:
  
 
===Layergruppen ändern===
 
===Layergruppen ändern===
[[Datei:Layergruppe_aendern.png|400px]]
+
[[Datei:Layergruppe Aendern.png|400px]]
  
 
Im Formular zum Ändern von Layergruppen werden folgende Informationen eingetragen:
 
Im Formular zum Ändern von Layergruppen werden folgende Informationen eingetragen:
Zeile 2.937: Zeile 3.506:
 
* obergruppe ... Id der Obergruppe in der die Gruppe eingeordnet werden soll. Wird hier nichts angegeben, ist die Gruppe auf der obersten Stufe und keiner anderen untergeordnet.
 
* obergruppe ... Id der Obergruppe in der die Gruppe eingeordnet werden soll. Wird hier nichts angegeben, ist die Gruppe auf der obersten Stufe und keiner anderen untergeordnet.
 
* order ... Reihenfolge der Layergruppe in der Legende.
 
* order ... Reihenfolge der Layergruppe in der Legende.
 +
 +
Wenn der Gruppeneditor mit dem Parameter selected_layer_id aufgerufen wurde und dieser eine positive Zahl hat, wird ein Link zum Sprung auf den Layer mit dieser ID angezeigt.
  
 
==Menüverwaltung==
 
==Menüverwaltung==
Zeile 2.949: Zeile 3.520:
 
Mit dem Link "Ändern" kommt man zum Editor für die einzelnen Punkte.
 
Mit dem Link "Ändern" kommt man zum Editor für die einzelnen Punkte.
  
Hier stehen die folgenden Optionen zur Verfügung:
+
[[Datei:Menue_Form_mit_Link.png|500px|Menüeditor]]
 +
 
 +
Wenn in Links javascript:void(0) angegeben ist, wird statt dessen der Link im Feld Onclick verwendet.
 +
 
 +
Mit dem Button rechts neben dem Eingabefeld kann der angegebene Link getestet werden.
 +
 
 +
Am Ende stehen die folgenden Optionen zur Verfügung:
 
* "zurück": Springt in die Liste der Menüpunkte zurück
 
* "zurück": Springt in die Liste der Menüpunkte zurück
 
* "Ändern": Speichert die eingestellten Änderungen für den aktuellen Menüpunkt
 
* "Ändern": Speichert die eingestellten Änderungen für den aktuellen Menüpunkt
Zeile 2.955: Zeile 3.532:
 
* "Als neuen Menüpunkt Eintragen": Legt einen neuen Menüpunkt an mit den aktuellen Werten aus dem Formular
 
* "Als neuen Menüpunkt Eintragen": Legt einen neuen Menüpunkt an mit den aktuellen Werten aus dem Formular
  
[[Datei:Menue_editor.png|500px|Menüeditor]]
 
  
 
Über den Button "Neues Menü" kann man einen neuen Menüpunkt anlegen. Dieser Button erscheint aber nur, wenn die Eigenschaft display im Style #neuer_datensatz_button auf block gesetzt ist.
 
Über den Button "Neues Menü" kann man einen neuen Menüpunkt anlegen. Dieser Button erscheint aber nur, wenn die Eigenschaft display im Style #neuer_datensatz_button auf block gesetzt ist.
Zeile 2.984: Zeile 3.560:
 
  INSERT INTO `u_menues` ( `id` , `name` , `links` , `obermenue` , `menueebene` , `target` )
 
  INSERT INTO `u_menues` ( `id` , `name` , `links` , `obermenue` , `menueebene` , `target` )
 
  VALUES (NULL , 'Druckvorschau', 'index.php?go=Druckausschnittswahl', '<id für Obermenü>', '2', NULL);
 
  VALUES (NULL , 'Druckvorschau', 'index.php?go=Druckausschnittswahl', '<id für Obermenü>', '2', NULL);
 +
 +
Wenn beim Speichern eine Validierung fehlschlägt, wird am entsprechenden Attribut eine Meldung angezeigt.
 +
 +
[[Datei:Validationmsg.png]]
  
 
===Parametrisierter Menüpunkt-Link===
 
===Parametrisierter Menüpunkt-Link===
Zeile 3.001: Zeile 3.581:
 
  index.php?go=Layer-Suche&titel=Fachdatensuche&selected_layer_id=50303999&operator_gemarkungsname=LIKE
 
  index.php?go=Layer-Suche&titel=Fachdatensuche&selected_layer_id=50303999&operator_gemarkungsname=LIKE
 
  index.php?go=Layer-Suche&selected_layer_id=50303787&value_gemeindeverband=5362&operator_gemeindeverband==
 
  index.php?go=Layer-Suche&selected_layer_id=50303787&value_gemeindeverband=5362&operator_gemeindeverband==
 +
* "anzahl": Übergibt dem Anwendungsfall "go=Layer-Suche" die anzuzeigende Trefferanzahl. Beispiel:
 +
index.php?go=Layer-Suche&selected_layer_id=50303997&anzahl=100
 +
* "go_plus=Suchen": Führt die definierte Suche direkt aus, ohne dass der Nutzer das "go=Layer-Suche" durchläuft. Beispiel:
 +
index.php?go=Layer-Suche&go_plus=Suchen&anzahl=20&selected_layer_id=50303645
 
* Im Text des Menülinks können auch Layerparameter vorkommen. Diese werden wie gewohnt mit dem Präfix $ eingetragen. Das ist hilfreich z.B. zur Vorbelegung von Werten beim Anlegen neuer Datensätze. Verwendet werden können auch die Parameter $stelle_id, $user_id, $language und $hist_timestamp z.B:
 
* Im Text des Menülinks können auch Layerparameter vorkommen. Diese werden wie gewohnt mit dem Präfix $ eingetragen. Das ist hilfreich z.B. zur Vorbelegung von Werten beim Anlegen neuer Datensätze. Verwendet werden können auch die Parameter $stelle_id, $user_id, $language und $hist_timestamp z.B:
 
  index.php?go=neuer_Layer_Datensatz&selected_layer_id=105&attributenames[0]=kartiergebiet_id&values[0]=$kartiergebietfilter
 
  index.php?go=neuer_Layer_Datensatz&selected_layer_id=105&attributenames[0]=kartiergebiet_id&values[0]=$kartiergebietfilter
 
Die Übersetzung dieser Parameter erfolgt vor der Ausgabe im Menü. In den Links sind also bereits die ersetzten Werte der Parameter zu sehen.
 
Die Übersetzung dieser Parameter erfolgt vor der Ausgabe im Menü. In den Links sind also bereits die ersetzten Werte der Parameter zu sehen.
 +
* "overwrite_layer_name": Wird im Link eine Layersuche mit go=Layer-Suche_Suchen und selected_layer_id aufgerufen, kann der Parameter overwrite_layer_name angegeben werden um den Namen des Layers zu ändern. Das ist hilfreich, wenn Filterausdrücke angegen sind und sich dies in der Überschrift des Suchergebnisses ausdrücken soll. Das Beispiel gibt den Titel "Nur aktuelle Kartierungen" aus:
 +
index.php?go=Layer-Suche_Suchen&selected_layer_id=105&overwrite_layer_name=Nur aktuelle Kartierungen&value_aktuell=1&operator_aktuell==
  
 
===Zuordnen des Menüs zur Stelle===
 
===Zuordnen des Menüs zur Stelle===
Zeile 3.029: Zeile 3.615:
 
* '''untermenue''': Untermenüpunkte.
 
* '''untermenue''': Untermenüpunkte.
 
* '''ausgewaehltes-menue''': Menüpunkt, bei dem die Parameter aus dem Attribut ''links'' mit denen in der URL oder Formularen übergebenen Parametern übereinstimmen. (sieht standardmäßig so aus als wäre nichts ausgewählt)
 
* '''ausgewaehltes-menue''': Menüpunkt, bei dem die Parameter aus dem Attribut ''links'' mit denen in der URL oder Formularen übergebenen Parametern übereinstimmen. (sieht standardmäßig so aus als wäre nichts ausgewählt)
 +
 +
==Multilingualität==
 +
kvwmap unterstützt für die Darstellung der Oberfläche und Sachdaten verschiedene Sprachen. Es wird ein Konzept verwendet in dem prinzipiell jede Sprache verwendet werden kann. Aktuell sind nicht noch nicht alle Texte der Oberfläche übersetzungsfähig. Bei Bedarf lassen sich diese aber auch einfach über das verwendete Konzept der Multilingualität übersetzen. Bei den Daten hängt die Multilingualität davon ab welche Texte die Sachdaten enthalten.
 +
Es wird unterschieden in feste und austauschbare Texte. Fest Texte können durch den Administrator vergeben werden und somit nur eine bestimmte Sprache unterstützt werden. Austauschbare Texte ändern sich wenn der Nutzer eine andere Sprache einstellt.
 +
=== Unterstützte Sprachen ===
 +
Der Admin stellt unter Administratorfunktionen in der Variable supportedLanguages die zu unterstützenden Sprachen ein.
 +
 +
[[Datei:ConstantSupportedLanguage.png]]
 +
 +
Die Sprachen werden kommasepariert im Array angegeben. Aktuell sind folgende Sprachen berücksichtigt und müssen auch so geschrieben werden.
 +
* english
 +
* german
 +
* low-german
 +
* polish
 +
* vietnamese
 +
Diese Bezeichnungen müssen genau so für die im folgenden beschriebenen Language-Dateien verwendet werden. Weitere Sprachen, z.B. danish, können hinzugefügt werden. Für diese müssen dann aber jeweils auch die Language-Dateien angelegt werden, zusätzliche Felder im Datenmodell der MariaDB und die Auswahlliste bei den Optionen im Software-Core ergänzt werden. Anfragen dazu bitte auf die Wunschliste setzen. Die in der Variable supportedLanguages angegebenen Sprachen lassen sich dann unter Optionen durch den Benutzer auswählen.
 +
 +
[[Datei:optionsLanguages.png]]
 +
 +
Die Sprache wird so pro Stelle für die Nutzer in der Rolle hinterlegt. Beim Laden von kvwmap wird die Variable $GUI->user->rolle->language mit der vom Nutzer in der Stelle gewählten Sprache gesetzt und an folgenden Stellen verwendet.
 +
=== Language-Dateien ===
 +
Language-Dateien befinden sich im Verzeichnis layouts/languages und enthalten die Texte die in der Oberfläche verwendet werden sollen. Es gibt für jede Sprache eine globale Language-Datei (german.php, english.php, etc.)
 +
Des Weiteren kann es für jedes Snippets im Ordner layouts/snippets ein oder mehrere gleichnamige Language-Dateien geben mit dem Postfix _Sprache, z.B. layer_formular_german.php, layer_formular_english.php, etc). Aktuell gibt es für jedes Snippet mindestens die Language-Datei _german und ggf. _english. Für die anderen Sprachen sind die Lanuguage-Dateien noch nicht immer vorhanden, können aber bei Bedarf im Software-Core hinzugefügt werden. Die Language-Dateien bestehen in der Regel aus Zuweisungen von Texten zu Variablen. Die Variablen in den globalen Language-Dateien sind Klassenvariablen des GUI-Objektes und können somit überall verwendet werden. Darin sind Wörter und Texte enthalten die an verschiedenen Stellen der GUI verwendet werden wie Layer, Stelle, Nutzer oder Kurzwörter (und, in, oder). Die Variablen der Snippets sind lokal definiert und fangen in der Regel mit dem Prefix $str an.
 +
=== Sprachen in der Layer-Definition ===
 +
Wie an verschiedenen anderen Stellen der Dokumentation schon erwähnt, kann man die Variable $language in der Definition von Layern verwenden. Die Variable $language ist ein sogenannter globaler Layerparameter. Das heißt die Variable wird immer vor dem Lesen von Daten in der Datenbank durch den entsprechenden Wert des Nutzers ersetzt. Steht in dem Layer z.B. column_$language als Attributname im Query-Statement wird für die Abfrage z.B. column_german, column_english etc. verwendet.
 +
=== Attribute für verschiedene Sprachen ===
 +
In einigen Tabellen wie classes, layer, stelle u_groups gibt es für eine Spalte mehrere Language-Varianten, z.B. name_german, name_english, etc. Je nachdem welche Sprachen als supportedLanguage ausgewählt wurden kommen die Formularfelder in der Adminoberfläche zur Anzeige.
 +
 +
[[Datei:MultilingualLayerNameFormular.png]]
 +
 +
Auch die Attribute können dann verschiedene Namensspalten enthalten.
 +
 +
[[Datei:MultilingualAttributeNameFormular.png]]
 +
 +
=== Custom Language-Dateien ===
 +
Da es vorkommen kann, dass die Übersetzungen von einem zum anderen System unterschiedlich ausfallen sollen, gibt es dafür auch ein Konzept. Es sieht vor, dass es im Ordner custom/layouts/languages jeweils Dateien geben kann, die Variablen enthalten können, die die Variablen in den Dateien im Ordner layouts/languages überschreiben. Durch das Überschreiben von Language-Variablen kann auch die Ausprägung in einer einzelnen Sprache angepasst werden. Soll z.B. im Layer-Editor unter Allgemeine Einstellungen nicht mehr "Query" stehen sondern "SQL für Sachdatenabfrage und Suche" und statt "Data" "SQL für Kartendarstellung" ist die Datei custom/layouts/languages/layer_formular.php mit folgenden Variablen anzulegen:
 +
 +
  $strData = "SQL für Kartendarstellung";
 +
  $strPath = "SQL für Sachdatenabfrage und Suche";
 +
 +
Auf diese Weise lassen sich viele Texte in der GUI individuell anpassen. Damit die individuellen Language-Dateien auch greifen muss in den Snippets die Datei "languages/_include_language_files.php" zum Überladen der custom-Dateien Verwendung finden. Das wird nach und nach je nach Bedarf in die Snippets eingebaut. Wer Änderungen vornehmen möchte, meldet das bitte in der Wunschliste an.
 +
Außerdem muss die Konstante OVERRIDE_LANGUAGE_VARS aus der Gruppe Layout auf true gesetzt sein.
 +
 +
[[Datei:OVERRIDE_LANGUAGE_VARS.png]]
  
 
==Druckrahmenverwaltung==
 
==Druckrahmenverwaltung==
Zeile 3.343: Zeile 3.973:
 
Schwierigkeiten bereiten möglicherweise komplexe SQL-Befehle, z.B. wenn oids uneindeutig werden. In diesen Fällen bietet sich an, die eigentliche Abfrage in einen View zu schreiben und in ''Query'' (vielleicht auch in ''Data'') auf diesen View zuzugreifen. Möglicherweise ist es beim View dann allerdings nötig, Rules zu schreiben, die die INSERT-, UPDATE- und DELETE-Anweisungen durchführen.
 
Schwierigkeiten bereiten möglicherweise komplexe SQL-Befehle, z.B. wenn oids uneindeutig werden. In diesen Fällen bietet sich an, die eigentliche Abfrage in einen View zu schreiben und in ''Query'' (vielleicht auch in ''Data'') auf diesen View zuzugreifen. Möglicherweise ist es beim View dann allerdings nötig, Rules zu schreiben, die die INSERT-, UPDATE- und DELETE-Anweisungen durchführen.
  
Die Sachdatenanzeige erfolgt über den [[Dokumentation#Generischer_Layereditor|Generischen Layereditor]]. Bei besonderen Darstellungen kann alternativ auch ein [[Dokumentation#Vektor_Layer|Template]]" angelegt werden, dessen Dateiname im Feld "template" der Tabelle [[Dokumentation#Tabelle_.22used_layer.22|used_layer]] eingetragen wird.
+
Die Sachdatenanzeige erfolgt über den [[Dokumentation#Generischer_Layereditor|Generischen Layereditor]]. Bei besonderen Darstellungen kann alternativ auch ein [[Admin-Dokumentation#Templates_.28eigene_Snippets.29|Template]] angelegt werden, dessen Dateiname im Feld "template" der Tabelle [[Dokumentation#Tabelle_.22used_layer.22|used_layer]] eingetragen wird.
  
 
'''Data'''
 
'''Data'''
Zeile 3.530: Zeile 4.160:
  
 
Ob die Zugriffe auf die mit "1" gekennzeichneten Layer tatsächlich in der Tabelle [[Dokumentation#Tabelle_.22u_consume2layer.22|u_consume2layer]] protokolliert werden, entscheidet die Einstellung des Feldes "logconsume" der jeweiligen [[Dokumentation#Tabelle_.22stelle.22|Stelle]], in der dieser Layer aufgerufen wird.
 
Ob die Zugriffe auf die mit "1" gekennzeichneten Layer tatsächlich in der Tabelle [[Dokumentation#Tabelle_.22u_consume2layer.22|u_consume2layer]] protokolliert werden, entscheidet die Einstellung des Feldes "logconsume" der jeweiligen [[Dokumentation#Tabelle_.22stelle.22|Stelle]], in der dieser Layer aufgerufen wird.
 +
 +
'''kurzbeschreibung'''
 +
 +
Freitext zur Beschreibung des Layers und dessen Inhalt. Kann thematische, zeitliche und räumliche Beschreibungen enthalten. Bei WMS entspricht das dem was in Abstract steht.
 +
 +
'''datasource'''
 +
 +
Quellenangabe zu den Daten, die in dem Layer angezeigt werden.
 +
 +
'''dataowner_name''', '''dataowner_email''', '''dataowner_tel'''
 +
 +
Name, E-Mail-Adresse und Telefonnummer des Eigentümers der Daten
 +
 +
'''uptodateness'''
 +
 +
Aktualität der Daten, die im Layer angezeigt werden.
 +
 +
'''updatecycle'''
 +
 +
Angaben darüber wann, wie oft und wie die Daten aktualisiert werden.
 +
 +
'''metadatalink'''
 +
 +
Ein Link zu einem Dokument in dem weiterführende Beschreibungen zum Layer oder dessen Daten enthalten sind, z.B. zu einem Metadatendokument in einem Metainformationssystem oder dem Capabilities-Dokument eines Dienstes.
 +
 +
'''version'''
 +
 +
Ein String zu Versionierung des Layers. Wird für die Synchronisierung mit kvmobile verwendet. Neue Versionen müssen bei alphanumerischer Sortierung weiter unten sein. z.B. 1.0.0 ist älter als 1.1.0
 +
 +
'''comment'''
 +
 +
Ein Kommentar zum Layer. Dieser wird z.B. dafür verwendet um dem Client mitzuteilen was sich an der Konfiguration des Layers geändert hat und warum. Ansonsten kann der Kommentar auch einfach nur für die Administratoren verwendet werden.
  
 
====Tabelle "layer_attributes"====
 
====Tabelle "layer_attributes"====
Zeile 3.696: Zeile 4.358:
  
 
In dieser Tabelle werden Parameter beschrieben, mit denen dynamische Layer definiert werden können. Siehe auch selectable_layer_params in Tabelle [[Dokumentation#Tabelle_.22stelle.22|stelle]]
 
In dieser Tabelle werden Parameter beschrieben, mit denen dynamische Layer definiert werden können. Siehe auch selectable_layer_params in Tabelle [[Dokumentation#Tabelle_.22stelle.22|stelle]]
 +
 +
====Tabelle "notifications"====
 +
Speichert die Benachrichtigungen, die der Admin für die Nutzer angelegt hat.
 +
 +
 +
'''id''' ID der Benachrichtigung. Primärschlüssel.
 +
 +
'''veroeffentlichungsdatum''' Datum ab wann die Benachrichtigung zu sehen sein soll.
 +
 +
'''ablaufdatum''' Datum bis zu dem die Benachrichtigung angezeigt werden soll.
 +
 +
'''stellen_filter''' Eine kommaseparierte Liste von Stellen-ID's oder 'nicht in Gaststellen'. Ohne Eintrag oder mit leerem String werden die Benachrichtiungen in allen Stellen angezeigt.
 +
 +
'''notification''' Der Text, der angezeigt werden soll. Kann HTML-Tags enthalten.
  
 
====Tabelle "m_grids"====
 
====Tabelle "m_grids"====
Zeile 3.808: Zeile 4.484:
  
 
Speichert die ID der Farbe aus der Tabelle ''colors'', die für die Anzeige von Suchergebnissen verwendet werden soll.
 
Speichert die ID der Farbe aus der Tabelle ''colors'', die für die Anzeige von Suchergebnissen verwendet werden soll.
 +
 +
'''redline_text_color'''
 +
 +
Speichert die Farbe in der die Texte der Redline-Funktion gezeichnet werden sollen (varchar(7) Farbwert in HTML-Farbnotation, NOT NULL, default '#ff0000')
 +
 +
'''redline_font_family'''
 +
 +
Speichert die Font-Family in der die Texte der Redline-Funktion gezeichnet werden sollen (varchar(25) NOT NULL, default 'Arial', im Auswahlfeld im Quellcode von rollenwahl.php fest vorgegebene Optionen: 'Arial', 'Courier', 'Helvetica', 'Verdana')
 +
 +
'''redline_font_size'''
 +
 +
Speichert die Font-Größe in der die Texte der Redline-Funktion gezeichnet werden sollen (integer NOT NULL, default 16, im Auswahlfeld im Quellcode von rollenwahl.php fest vorgeben von min 10 bis max 40 Schrittweite 1, verwendet als Größe in Pixel)
 +
 +
'''redline_font_weight'''
 +
 +
Speichert die Schriftschnitt in der die Texte der Redline-Funktion gezeichnet werden sollen (varchar(25) NOT NULL, default 'bold', im Auswahlfeld im Quellcode von rollenwahl.php fest vorgegebene Optionen: 'normal', 'bold', 'bolder', 'lighter', 'initial', 'inherit', '100', '200', '300', '400', '500', '600', '700', '800', '900')
  
 
====Tabelle "rollenlayer"====
 
====Tabelle "rollenlayer"====
Zeile 3.943: Zeile 4.635:
  
 
Nutzer Id der default Rolle. Die Einstellungen dieser Rolle werden für das Anlegen neuer Rollen für diese Stelle verwendet. Ist dieser Wert nicht angegeben oder die angegebene Rolle existiert nicht, werden die Defaultwerte der Rollenoptionen bei der Zuordnung eines Nutzers zu dieser Stelle verwendet. Die Angabe ist nützlich, wenn die Einstellungen in Gaststellen am Anfang immer gleich sein sollen. Außerdem werden die für den Default-Nutzer in der Stelle gespeicherten Themeneinstellungen aus der Tabelle [[Dokumentation#Tabelle_.22rolle_saved_layers.22|rolle_saved_layers]] für jeden Gast mit angelegt, damit die Gäste ebenfalls darauf zugreifen können.
 
Nutzer Id der default Rolle. Die Einstellungen dieser Rolle werden für das Anlegen neuer Rollen für diese Stelle verwendet. Ist dieser Wert nicht angegeben oder die angegebene Rolle existiert nicht, werden die Defaultwerte der Rollenoptionen bei der Zuordnung eines Nutzers zu dieser Stelle verwendet. Die Angabe ist nützlich, wenn die Einstellungen in Gaststellen am Anfang immer gleich sein sollen. Außerdem werden die für den Default-Nutzer in der Stelle gespeicherten Themeneinstellungen aus der Tabelle [[Dokumentation#Tabelle_.22rolle_saved_layers.22|rolle_saved_layers]] für jeden Gast mit angelegt, damit die Gäste ebenfalls darauf zugreifen können.
 +
 +
'''version'''
 +
 +
Ein String zu Versionierung der Stelle. Wird für die Synchronisierung mit kvmobile verwendet. Neue Versionen müssen bei alphanumerischer Sortierung weiter unten sein. z.B. 1.0.0 ist älter als 1.1.0
 +
 +
'''comment'''
 +
 +
Ein Kommentar zur Stelle. Dieser wird z.B. dafür verwendet um dem Client mitzuteilen was sich an der Konfiguration der Stelle geändert hat und warum. Ansonsten kann der Kommentar auch einfach nur für die Administratoren verwendet werden.
  
 
'''Tabellenstruktur:'''
 
'''Tabellenstruktur:'''
 
  CREATE TABLE `stelle` (
 
  CREATE TABLE `stelle` (
 
   `ID` int(11) NOT NULL,
 
   `ID` int(11) NOT NULL,
   `Bezeichnung` varchar(255) CHARACTER SET latin1 COLLATE latin1_german2_ci DEFAULT NULL,
+
   `Bezeichnung` varchar(255) NOT NULL DEFAULT '',
 
   `Bezeichnung_low-german` varchar(255) DEFAULT NULL,
 
   `Bezeichnung_low-german` varchar(255) DEFAULT NULL,
   `Bezeichnung_english` varchar(255) CHARACTER SET cp1250 DEFAULT NULL,
+
   `Bezeichnung_english` varchar(255) DEFAULT NULL,
   `Bezeichnung_polish` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
+
   `Bezeichnung_polish` varchar(255) DEFAULT NULL,
   `Bezeichnung_vietnamese` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
+
   `Bezeichnung_vietnamese` varchar(255) DEFAULT NULL,
 
   `start` date NOT NULL DEFAULT '0000-00-00',
 
   `start` date NOT NULL DEFAULT '0000-00-00',
 
   `stop` date NOT NULL DEFAULT '0000-00-00',
 
   `stop` date NOT NULL DEFAULT '0000-00-00',
Zeile 3.958: Zeile 4.658:
 
   `maxxmax` double DEFAULT NULL,
 
   `maxxmax` double DEFAULT NULL,
 
   `maxymax` double DEFAULT NULL,
 
   `maxymax` double DEFAULT NULL,
   `epsg_code` varchar(6) DEFAULT '2398',
+
  `minzoom` int(11) NOT NULL DEFAULT '8',
 +
   `epsg_code` int(5) NOT NULL DEFAULT '2398',
 
   `Referenzkarte_ID` int(11) DEFAULT NULL,
 
   `Referenzkarte_ID` int(11) DEFAULT NULL,
 
   `Authentifizierung` enum('0','1') NOT NULL DEFAULT '1',
 
   `Authentifizierung` enum('0','1') NOT NULL DEFAULT '1',
 
   `ALB_status` enum('30','35') NOT NULL DEFAULT '30',
 
   `ALB_status` enum('30','35') NOT NULL DEFAULT '30',
   `wappen` varchar(150) NOT NULL DEFAULT 'stz.gif',
+
   `wappen` varchar(150) NOT NULL DEFAULT 'wappen_doberan.png',
 
   `wappen_link` varchar(255) DEFAULT NULL,
 
   `wappen_link` varchar(255) DEFAULT NULL,
  `alb_raumbezug` set('','Kreis','Amtsverwaltung','Gemeinde') NOT NULL DEFAULT '',
+
   `logconsume` enum('0','1') DEFAULT NULL,
  `alb_raumbezug_wert` varchar(255) NOT NULL DEFAULT '',
+
   `logconsume` enum('0','1') CHARACTER SET latin1 COLLATE latin1_german2_ci DEFAULT NULL,
+
  `pgdbhost` varchar(25) NOT NULL DEFAULT 'localhost',
+
  `pgdbname` varchar(25) DEFAULT NULL,
+
  `pgdbuser` varchar(25) DEFAULT NULL,
+
  `pgdbpasswd` varchar(25) DEFAULT NULL,
+
 
   `ows_title` varchar(255) DEFAULT NULL,
 
   `ows_title` varchar(255) DEFAULT NULL,
 
   `wms_accessconstraints` varchar(255) DEFAULT NULL,
 
   `wms_accessconstraints` varchar(255) DEFAULT NULL,
Zeile 3.980: Zeile 4.675:
 
   `ows_fees` varchar(255) DEFAULT NULL,
 
   `ows_fees` varchar(255) DEFAULT NULL,
 
   `ows_srs` varchar(255) DEFAULT NULL,
 
   `ows_srs` varchar(255) DEFAULT NULL,
 +
  `protected` enum('0','1') NOT NULL DEFAULT '0',
 
   `check_client_ip` enum('0','1') NOT NULL DEFAULT '0',
 
   `check_client_ip` enum('0','1') NOT NULL DEFAULT '0',
 
   `check_password_age` enum('0','1') NOT NULL DEFAULT '0',
 
   `check_password_age` enum('0','1') NOT NULL DEFAULT '0',
 
   `allowed_password_age` tinyint(4) NOT NULL DEFAULT '6',
 
   `allowed_password_age` tinyint(4) NOT NULL DEFAULT '6',
 
   `use_layer_aliases` enum('0','1') NOT NULL DEFAULT '0',
 
   `use_layer_aliases` enum('0','1') NOT NULL DEFAULT '0',
   `selectable_layer_params` text,
+
   `selectable_layer_params` mediumtext,
 
   `hist_timestamp` tinyint(1) NOT NULL DEFAULT '0',
 
   `hist_timestamp` tinyint(1) NOT NULL DEFAULT '0',
   `default_user_id` int(11) DEFAULT NULL
+
   `default_user_id` int(11) DEFAULT NULL,
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
  `style` varchar(100) DEFAULT NULL,
 +
  `show_shared_layers` tinyint(1) DEFAULT '0',
 +
  `pgdbhost` varchar(255) NOT NULL,
 +
  `pgdbname` varchar(255) NOT NULL,
 +
  `pgdbuser` varchar(255) NOT NULL,
 +
  `pgdbpasswd` varchar(255) NOT NULL,
 +
  `postgres_connection_id` int(11) NOT NULL,
 +
  `version` varchar(10) NOT NULL DEFAULT '1.0.0',
 +
  `comment` text
 +
) ENGINE=InnoDB DEFAULT CHARSET=utf8 PACK_KEYS=0;
  
 
====Tabelle "stelle_gemeinden"====
 
====Tabelle "stelle_gemeinden"====
Zeile 4.212: Zeile 4.917:
 
'''template'''
 
'''template'''
  
Angabe eines PHP-Snippets, wenn NICHT der Generische Layereditor für die Sachdatenanzeige verwendet werden soll. Wenn Layer in verschiedenen Stellen unterschiedliche Sachdatenanzeigen bekommen sollen, können verschiedene Snippets zur Anzeige definiert werden. (Beispiel: biotope_amt1.php, biotope_amt2.php, etc.)
+
Angabe eines PHP-Snippets, wenn NICHT der Generische Layereditor für die Sachdatenanzeige verwendet werden soll. Wenn Layer in verschiedenen Stellen unterschiedliche Sachdatenanzeigen bekommen sollen, können verschiedene [[Admin-Dokumentation#Templates_.28eigene_Snippets.29|Templates]] zur Anzeige definiert werden. (Beispiel: biotope_amt1.php, biotope_amt2.php, etc.)
  
 
'''symbolscale'''
 
'''symbolscale'''
Zeile 4.254: Zeile 4.959:
  
 
Hier können eine oder mehrere mit ; getrennte IP Adressen oder Hostnamen (z.B. bei Nutzung von dynDNS bei keiner festen IP) eingetragen werden, von denen der Nutzer aus auf kvwmap zugreifen darf. Tritt aber nur in Kraft, wenn in Tabelle [[Dokumentation#Tabelle_.22stelle.22|stelle]] in die Spalte check_client_ip eine 1 eingetragen wurde. Wenn check_client_ip=1 ist und in dieser Spalte ips steht nichts, bekommt der User keinen Zugang.
 
Hier können eine oder mehrere mit ; getrennte IP Adressen oder Hostnamen (z.B. bei Nutzung von dynDNS bei keiner festen IP) eingetragen werden, von denen der Nutzer aus auf kvwmap zugreifen darf. Tritt aber nur in Kraft, wenn in Tabelle [[Dokumentation#Tabelle_.22stelle.22|stelle]] in die Spalte check_client_ip eine 1 eingetragen wurde. Wenn check_client_ip=1 ist und in dieser Spalte ips steht nichts, bekommt der User keinen Zugang.
 +
 +
'''password'''
 +
Hier wird das mit der Methode SHA1 verschlüsselte Passwort gespeichert. Passwörter sind mit der Methode SHA1() zu codieren sind dann 40 Zeichen lang.
 +
 +
'''passwort'''
 +
In dem Attribut wurden bis zum 05.09.2022 Passwörter mit der Methode MD5 codiert hinterlegt. Bei der Umstellung auf SHA1 Passwörter prüft kvwmap bei der Anmeldung ob das MD5 codierte Passwort zum angegebenen Passwort passt und wenn ja, wird das Passwort sha1 codiert in dem Attribut password hinterlegt. Die Authentifizierung erfolgt nur noch über das Attribut password. Wenn das SHA1 Passwort im Attribut password hinterlegt wird, wird gleichzeitig das MD5 verschlüsselte Passwort gelöscht.
  
 
'''password_setting_time'''
 
'''password_setting_time'''
Zeile 4.266: Zeile 4.977:
  
 
Hier wird die Stelle angegeben, der dieser User beim ersten Start von kvwmap zugeordnet sein soll.
 
Hier wird die Stelle angegeben, der dieser User beim ersten Start von kvwmap zugeordnet sein soll.
 +
 +
====Tabelle "user2notifications" ====
 +
Speichert die Zuordnung der Nutzer zu den Benachrichtigungen. Wenn der Nutzer eine Benachrichtigung nicht mehr sehen will, wird die Zuordnung zwischen der Benachrichtigung und dem Nutzer in der Tabelle user2notifications entfernt.
 +
 +
 +
'''user_id''' ID des Nutzers aus der Tabelle user.
 +
'''notification_id''' ID der Benachrichtigung in der Tabelle notifications.
  
 
====Tabelle "u_attributfilter2used_layer" ====
 
====Tabelle "u_attributfilter2used_layer" ====
Zeile 4.571: Zeile 5.289:
  
 
Mehrere Varianten der Bezeichnung der Einheit als Array.
 
Mehrere Varianten der Bezeichnung der Einheit als Array.
 +
 +
===MySQL-Tabellen in PostgreSQL nutzen===
 +
Zur Einbindung von MySQL-Tabellen, z.B. user in Postgres kann der fdw_mysql verwendet werden. Hier wird beschrieben welche Schritte dafür erforderlich sind.
 +
* Einrichten eines MySQL-Nutzers mit dem von Postgres aus auf die MySQL-Datenbank zugegriffern werden soll. Wenn man den kvwmap-Nutzer verwendet kann das Anlegen eines neuen Nutzers und dessen Rechteeinstellung entfallen. Ggf. die IP des Postgres-Containers anpassen.
 +
<pre>
 +
mysql> create user 'fdw_user'@'172.0.10.%' identified by 'secret_password';
 +
</pre>
 +
* Festlegung der Rechte für den Nutzer in MySQL.
 +
<pre>
 +
mysql> grant select,insert,update,delete on EMP to fdw_user@'%';
 +
mysql> grant select,insert,update,delete on DEPT to fdw_user@'%';
 +
</pre>
 +
* Installation von fdw_mysql auf dem Postgres-Server. Ist bei Verwendung des Images pkorduan/docker-postgis schon enthalten.
 +
<pre>pgsql-server$ apt-get update; apt-get install postgresql-<PG_MAJOR>-mysql-fdw</pre>
 +
* Installieren der Erweiterung in der kvwmap-Datenbank
 +
<pre>postgres=# create extension mysql_fdw;</pre>
 +
* Definition einer Serverdefinition, die auf den MySQL-Server verweist.
 +
<pre>postgres=# CREATE SERVER mysql_kvwmapdb FOREIGN DATA WRAPPER mysql_fdw OPTIONS (host 'mysql', port '3306');</pre>
 +
* Definition eines User mappings. Ggf. fdw_user durch kvwmap ersetzen
 +
<pre>postgres=# CREATE USER MAPPING FOR PUBLIC SERVER mysql_kvwmapdb OPTIONS (username 'fdw_user',password 'secret_password');</pre>
 +
* Anlegen der Fremdtabelle in Postgres auf Basis einer existierenden MySQL-Tabelle. Im Beispiel wird die Tabelle admin.nutzer angelegt auf der Basis der MySQL-Tabelle user.
 +
<pre>
 +
CREATE FOREIGN TABLE admin.nutzer(
 +
  id integer NULL,
 +
  login_name text NULL COLLATE pg_catalog."default",
 +
  name text NULL COLLATE pg_catalog."default",
 +
  vorname text NULL COLLATE pg_catalog."default",
 +
  phon text NULL COLLATE pg_catalog."default",
 +
  email text NULL COLLATE pg_catalog."default",
 +
  organisation text NULL COLLATE pg_catalog."default",
 +
  "position" text NULL COLLATE pg_catalog."default"
 +
)
 +
SERVER mysql_server
 +
OPTIONS (dbname 'kvwmapdb', table_name 'user');
 +
</pre>
 +
Diese Tabelle kann dann als ganz normale Postgres-Tabelle verwendet werden. Beim Schreiben in die Tabelle bitte Vorsicht. Abhängigkeiten zu anderen Tabellen in MySQL müssen berücksichtigt werden.
 +
Ein weiteres Beispiel für die Einbindung der Layer aus MySQL:
 +
<pre>
 +
CREATE FOREIGN TABLE admin.layer(
 +
  layer_id integer NULL,
 +
  name character varying NULL COLLATE pg_catalog."default",
 +
  alias character varying NULL COLLATE pg_catalog."default",
 +
  maintable character varying NULL COLLATE pg_catalog."default"
 +
)
 +
SERVER mysql_server
 +
OPTIONS (dbname 'kvwmapdb', table_name 'layer');
 +
</pre>
 +
 +
===Datenbank-Migration===
 +
 +
kvwmap-Installationen die PostgreSQL < Version 12 verwenden, nutzen häufig die OID in der Layerdefinition. Ab Version 12 werden OIDs außerhalb des system catalog nicht mehr unterstützt. Für ein Upgrade auf eine aktuelle PostgresQL-Version müssen die OID-Spalten somit aus Layer-Definitionen, Tabellen, Views, Indizes, Constraints und Funktionen entfernt bzw. durch eine Alternative ersetzt werden.
 +
Für PostgreSQL-Details siehe
 +
[https://www.postgresql.org/docs/12/release-12.html#id-1.11.6.6.11 PostgreSQL 12 Release Notes]
 +
 +
====Layer anpassen====
 +
 +
Eine Übersicht der anzupassenden Objekte liefert <code>/kvwmap/index.php?go=layer_check_oids</code>
 +
Layer können hier halbautomatisch angepasst werden.
 +
 +
Die Tabelle mit den Layern enthält die Spalten
 +
* Layer - Bezeichnung des Layers mit Checkbox zur Auswahl des Layers
 +
* ID-Spalte
 +
* Query
 +
* Data
 +
* oid-Alternative - wenn möglich, wird hier eine Alternative zur bisherigen OID ermittelt, diese wird hier angezeigt
 +
* Haupttabelle
 +
* Fehlermeldungen, falls die Analyse des Layers nicht problemlos möglich war
 +
 +
Ein Layer kann in 3 Feldern oids verwenden: als ID-Spalte, im Query-Feld und im Data-Feld. Wenn bei einem Layer hier eine oid verwendet wird, erscheint die Tabellenzelle rot. Das bedeutet, dass hier Anpassungsbedarf besteht.
 +
 +
Wenn eine oid-Alternative ermittelt werden konnte, kann diese in den 3 Feldern ID-Spalte, Query und Data gegen die oid ersetzt werden. Dazu dienen die 3 Schaltflächen oben rechts. Klickt man auf die Schaltflächen, wird die entsprechende Aktion für alle selektierten Layer durchgeführt. Für das Query- und das Data-Feld wird außerdem in einer gelben Zelle angezeigt, wie Query bzw- Data nach der Ersetzung aussehen werden. Bei Bedarf kann man hier auch von Hand Anpassungen vornehmen. Bei Klick auf die entsprechende Schaltfläche wird der Inhalt aus dem gelb hinterlegten Textfeld verwendet.
 +
 +
====Datenbankobjekte anpassen====
 +
 +
Die Seite zeigt unterhalb der Layer-Tabelle zeigt auch anzupassende Datenbankobjekte. Tabellen werden hier nicht aufgeführt, da diese auch ohne OID-Spalte wiederhergestellt werden können. Dies erzeugt nur eine Warnung. Verwenden aber von den Tabellen abhängige Objekte (Views, Constraints, Funktionen, Indizes) die OID-Spalte, so muss diese entfernt oder durch eine alternative Spalte ersetzt werden.
 +
Die Tabellen geben einen Überblick über die betreffenden Objekte.
 +
Die Abfragen zu den Tabellen finden Sie auch in diesem [https://github.com/dudehro/postgis_migration/tree/main/migration_checks Repository.]
 +
 +
====Migration testen====
 +
 +
Zum Testen der Migration gibt es im kvwmap-server Repository den Service ''pg15migration''. Dieser kann mit <code>dcm create serivce pg15migration kvwmap_prod</code> eingerichtet werden. Bei der Einrichtung wird nach dem Passwort für den User ''postgres'' auf dem alten Cluster gefragt. Ebenfalls werden Pfade zur .pgpass und zum DumpVerzeichnis des alten Clusters abgefragt. Im alten Cluster bietet es sich an einen Ordner /dumps im Container zu mounten und den hostseitigen Pfad bei der Einrichtung des ''pg15migration''Services bereitzustellen. So kann das dump aus dem alten Cluster und restore ins neue Testcluster automatisiert erfolgen.
 +
 +
In den dump-Ordner des alten Clusters kann die ./scripte/dump.sh aus dem Verzeichnis des Testclusters kopiert werden. In diesem Script sind evtl. die zu dumpenden DBs und User anzupassen. Bei Schemen mit vielen Daten kann pg_dump um --schema-only erweitert werden.
 +
 +
Über ./export-import.sh im Ordner neues Clusters kann die Testmigration gestartet werden. Aus dem alten Cluster werden alle in dump.sh definierten DBs im Custom-Format gedumpt und ins neue Testcluster eingespielt.
 +
Dabei werden für jede DB 2 Logdateien (stdout, stderr) im Verzeichnis ./dumps/logs erzeugt. Diese geben Aufschluss über mögliche Fehler.
 +
 +
====Postgis====
 +
 +
Neben dem Ersetzen von OIDs kann es durch die Postgis-Extension zu weiteren Problemen kommen. Insbesondere wenn die Extension nicht über <code>CREATE EXTENION postgis;</code> sondern über die SQL-Scripte installiert wurde. In diesem Fall landen die Postgis-Funktionen als Referenz auf die externen Bibliotheken im Dump. Beim restore kann die Referenz zur Bibliothek nicht aufgelöst werden, da sich die Versionsnummer im Pfad geändert hat. Hier hilft ein Custom-Format dump und das Wiederherstellen über postgis_restore.pl in eine neue Datenbank in der die Postgis-Extenion installiert sowie das postgis legacy.sql eingespielt wurde.
 +
Dieser Prozess wurde mit dem pg15migration-Service automatisiert. In der ./import-dumps.sh des Testclusters ist der Aufruf <code>docker exec -it "$CONTAINER" bash -c /scripts/restore.sh</code> durch  <code>docker exec -it "$CONTAINER" bash -c /scripts/restore-legacy.sh</code> zu ersetzen.
  
 
== API Doc ==
 
== API Doc ==
Zeile 4.601: Zeile 5.410:
 
=Sicherung=
 
=Sicherung=
  
==mit kvwmap==
+
zur Sicherung stellt die GDI Service das github-Repo [https://github.com/dudehro/kvwmap-backup.git] zur Verfügung. Dies bietet alle notwendigen Scripte um eine Standard-kvwmap-server Installation zu sichern. Für erweiterte Installationen ist die Konfiguration der Sicherungswerkzeuge entsprechend anzupassen.
  
kvwmap bietet ein eingebautes Modul zum einrichten und regelmäßigen Ausführen von Sicherungen. Die Einrichtung findet über die kvwmap-Oberfläche über den Anwendungsfall
+
Gesichert werden müssen mindesten
index.php?go=Sicherungen_anzeigen
+
* Datenverzeichns <code>/home/gisadmin/networks</code> mit Borg
statt.
+
* PostgreSQL mit pgBackRest
 +
* mysql/mariadb mit mariabackup
  
Eine Sicherung besteht aus Angaben zum Ausführungszeitpunkt und Speicherort. Im Kontext einer Sicherung gibt es Sicherungsinhalte. Dies können
+
== Batchjob ==
* Verzeichnissicherung
+
Im Standard gibt es eine /etc/cron.d/gdi_sicherung mit folgendem Inhalt
* mySQL-Dump
+
<code>
* PostgreSQL-Dump
+
  SHELL=/bin/bash
* Verzeichnisinhalte kopieren
+
  PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
sein.
+
  00 22 * * * root runjob.py /etc/backup/jobs.json borg
 +
</code>
 +
Der Batchjob startet die Ablaufsteuerung <code>runjob.py</code> mit den Jobdefinitionen und dem zu startenden Job (hier borg).
  
===Architektur und Konfiguration des Hosts===
+
== Ablaufsteuerung ==
  
Die Sicherungen werden in der kvwmap-Oberfläche erstellt und deren Konfiguration in der mySQL-DB ''kvwmapdb'' gespeichert. In der Oberfläche gibt es den Button "Cronjobs erstellen". Dieser schreibt die Konfiguration der Sicherungen sowie einen Crontab in das im Container gemountete Verzeichnis
+
Im Rahmen einer Sicherung werden die in <code>/etc/backup/jobs.json</code> definierten Programme nacheinander aufgerufen. Der Aufruf erfolgt durch <code>runjob.py /etc/backup/jobs.json borg</code>. Dem runjob-Script wird die Definition der abzuarbeitenden Jobs und der Name des Startjobs übergeben. In der Definition <code>jobs.json</code> wird auch das Workspace-Verzeichnis definiert. Dieses Verzeichnis steht allen aufgerufenen Jobs im Environment zu Verfügung. runjob.py schreibt in dieses Verzeichnis das Log <code>joblog.json</code> in dem StdOut, StdErr sowie die Exitcodes der aufgerufenen Programme dokumentiert werden.
/var/www/
+
Dieses ist im Host standardmäßig gemountet auf
+
/home/gisadmin/www/
+
Auf dem Host ist das Script
+
/home/gisadmin/kvwmap-server/scripte/sicherung/copy_backup_crontab
+
als stündlicher Cronjob in
+
/etc/cron.hourly/copy_backup_crontab
+
einzurichten. Das Script sucht stündlich in
+
/home/gisadmin/www/sicherungen
+
nach neuen Crontabs. Wird ein Crontab gefunden, wird dieser nach
+
/etc/cron.d/
+
verschoben.
+
  
===neue Sicherung erstellen===
+
=== Konfiguration ===
  
Folgende Felder stehen beim Anlegen einer Sicherung zur Verfügung:
+
Alles an Konfiguration liegt unter <code>/etc/backup</code>.
 +
* jobs.json
 +
** Definition der abzuarbeitenden Programme für eine Sicherung
 +
** Workspace-Verzeichnis: Arbeitsverzeichnis für die aktuelle Sicherung. Das Verzeichnis steht allen aufgerufenen Programmen im environment zur Verfügung. <code>runjob.py</code> schreibt hier die <code>joblog.json</code> rein in der alle Ausgaben (stderr, stdout) und die Exitcodes der ausgeführten Programme gelogt werden.
  
* Name und Beschreibung, sind beide erforderlich
+
Eine Job-Definition hat die Form
* Zielverzeichnis ist das lokale Verzeichnis in welches die Sicherungsinhalte gespeichert werden. Dieses ist optional, da es Sicherungsinhalte gibt die auf entfernten Hosts gespeichert werden.
+
<code>
* Intervall kann täglich, wöchentlich oder monatlich eingestellt werden. Diese Angaben werden zusammen mit der Ausführungszeit in einen Cronjob übernommen.
+
        {
Zudem bestimmt das Intervall über die dynamische Erweiterung des Zielverzeichnisses.
+
            "name":"postgresql"
** tägliche Sicherung: Zielverzeichnis/Jahr[YYYY]/Monat[01..12]/Tag des Monats[1..31]
+
            ,"command":["pgbackrest.sh", "kvwmap_prod_pgsql15", "incr"]
** wöchentliche Sicherung: Zielverzeichnis/Jahr[YYYY]/Woche des Jahres[0..53]
+
            ,"next-job":"mariadb"
** monatliche Sicherung: Zielverzeichnis/Jahr[YYYY]/Jahr[YYYY]/Monat[01..12]
+
            ,"start-job-on-success":"somejob1"
* Alte Sicherungen können nach x Tagen rollierend gelöscht werden.
+
            ,"start-job-on-error";"somejob2"
 +
        },
 +
</code>
 +
Sie besteht aus einem Namen und dem auszuführenden Kommando.  
 +
Optional können folgende Schlüssel übergeben werden:
 +
* next-job
 +
** Name des Jobs der im Anschluss ausgeführt werden soll
 +
* start-job-on-success
 +
** Name des Jobs der bei Erfolg (exitcode=0) ausgeführt werden soll. Existiert ein "next-job" so wird dieser im Anschluss an start-job-on-success ausgeführt.
 +
* start-job-on-error
 +
** Names des Jobs der bei Fehler (exitcode!=0) ausgeführt werden soll. xistiert ein "next-job" so wird dieser im Anschluss an start-job-on-error ausgeführt.
  
Mit einem Klick auf "Anlegen" wird die Sicherung erstellt. Anschließend können Sicherungsinhalte eingefügt werden.
+
Auf diese Weise können Jobs miteinander verkettet werden. Die Jobs werden als FIFO-Queue abgearbeitet.
  
===Sicherungsinhalte erstellen===
+
== Dateisicherung mit Borg ==
 +
[https://borgbackup.readthedocs.io/en/stable/ offizielle Borg-Dokumentation]
  
* Name, ist erforderlich
+
Borg ist ein cleveres Sicherungswerkzeug mit einigen praktischen Features. Jede Sicherung erfolgt in das gleiche Repository. Borg zerteilt eine Datei beim Speichern in kleine Teile, sogenannte Chunks, und speichert diese Chunks in einem Repository. Wird nun eine ähnliche oder veränderte Datei erneut gesichert, wird nur der Teil gespeichert der sich verändert hat. Die Deduplikation von Daten resultiert in schlanken täglichen Sicherungen.
* Methode
+
Ein weiteres praktisches Features ist das löschen von alten Sicherungen nach festgelegten Werten. Im Standard behalten wir die letzten 7 Tage, die letzten 2 Wochensicherungen und eine Monatssicherung. Alles andere wird von Borg automatisch gelöscht.
# Verzeichnissicherung, verwendet intern tar
+
#* Komprimierung mit gzip optional (längere Lauftzeit der Sicherung)
+
# mySQL-Dump über mysqldump
+
# PostgreSQL-Dump mit pg_dump
+
#* --inserts Daten werden mit INSERT-Statements exportiert anstatt mit DUMP.
+
#* --column-inserts Spaltenbezeichnungen werden explizit im INSERT-Statement angegeben.
+
#* Schemas und Tabellen ein- oder ausschließen
+
# Verzeichnisinhalte kopieren mit rsync
+
* Ziel
+
** bei Verzeichnissicherung, mySQL- und PostgreSQL-Dump ist dies der Dateiname der Sicherung im Zielverzeichnis.
+
** bei ''Verzeichnisinhalte kopieren'' kann dies ein entfernter Host in der Form
+
user@host:/dir/to/backup
+
sein. Die Authentifizung via SSH Public-Key Verfahren muss in diesem Fall eingerichtet sein.
+
  
==Was ist zu sichern?==
+
=== Konfiguration ===
 +
Beispielaufruf von Borg in der /etc/backup/jobs.lst. Übernimmt die GDI-Service Wartung und Sicherung des Servers, wird diese Konfiguration automatisch geschrieben und darf nicht händisch angepasst werden.
  
===Konfiguration===
+
<code>
des kvwmap-servers
+
borg create --compression auto,lzma,7 --one-file-system --stats --exclude-caches --patterns-from /etc/backup/file.patterns /home/gisadmin/Sicherungen/borgrepo::{hostname}-{now:%Y-%m-%d-%H%M%S}
/home/gisadmin/kvwmap-server/config/config
+
der Docker-Container
+
/home/gisadmin/etc
+
Konfiguration zusätzlicher eigener Container
+
/home/gisadmin/kwmap-server/cargo-enabled
+
  
===Anwendungen===
+
borg prune --list -v --keep-within=14d --keep-weekly=4 --keep-monthly=3 /home/gisadmin/Sicherungen/borgrepo
alle Anwendungen, empfohlen
+
/home/gisadmin/www/apps/
+
  
===Anwendungsdaten===
+
borg compact --cleanup-commits --progress /home/gisadmin/Sicherungen/borgrepo
alle Anwendungsdaten, empfohlen
+
</code>
/home/gisadmin/www/data
+
  
===Datenbanken===
+
=== Aufruf + Log ===
 +
Der Aufruf der jobs.lst erfolgt über <code> cmdlogger.py /etc/backup/jobs.lst</code>.
 +
Das Logging der letzten Ausführung kann mit <code>cmdlogger-latest.py /etc/backup/jobs.lst</code> ermittelt werden.
  
Werden die Datenbanken in Containern betrieben, sollten die Dumps auch immer innerhalb der Container gemacht werden. Nur so wird sichergestellt, dass die korrekte Version von pg_dump/mysqldump verwendet wird.
+
=== Sicherung auflisten ===
 +
Alle verfügbaren Sicherungen können mit folgendem Befehl ausgelistet werden
 +
$ borg list /home/gisadmin/Sicherungen/borgrepo/
  
Dump der PG-Datenbank kvwmapsp nach Host-Verzeichnis ''/home/gisadmin/www/kvwmapsp.dump''
+
=== Sicherung einsehen, zurückspielen ===
docker exec pgsql-server bash -c "pg_dump -Fc -U kvwmap -f /var/www/kvwmapsp.dump kvwmapsp"
+
Borg bietet verschiedene Möglichkeiten auf Sicherungen zuzugreifen. Die einfachste ist das mounten einer Sicherung.
 +
Dazu legen wir uns einen Mountpoint an und mounten die gewünschte Sicherung anschließend mit Borg in dieses Verzeichnis:
  
Dump der mySQL-Datenbank kvwmapdb nach Host-Verzeichnis ''/home/gisadmin/db/mysql''
+
$ mkdir /home/gisadmin/Sicherungen/borgmount
  docker exec -it mysql-server bash -c "mysqldump --single-transaction --user=kvwmap --databases kvwmapdb --password=""SECRET"" > /var/lib/mysql/kvwmapdb.dump"
+
  $ borg mount /home/gisadmin/Sicherungen/borgrepo/::dev-2023-05-11-122157 /home/gisadmin/Sicherungen/borgmount/
  
====Datensicherung PostgreSQL/PostGIS====
+
Die Sicherung ist nun unter /home/gisadmin/Sicherungen/borgmount/ verfügbar und kann bequem durchsucht werden.
  
Die Datenbank kann auf zwei verschiede Art und Weise gesichert werden.
+
Um mit Borg auf eine bestimmte Sicherung zuzugreifen ist die Syntax wie im Beispiel "PfadZumRepository::BezeichnungDerSicherung".
* Kopieren des gesamten Verzeichnisses einer Datenbank, Datenbank muss dazu gestoppt sein. Das wiedereinsetzen der Dateien funktioniert normalerweise nur, wenn die neue Datenbank von der selben Version ist wie die ursprüngliche.
+
* Erzeugen und Sichern eines Datenbankdumps, geht aus dem laufendem Betrieb heraus.
+
  
Die Datenbank liegt bei Suse-Servern üblicherweise in /usr/local/pgsql/data, bei Nutzung des FGS-Pakets findet man sie in $FGS_HOME/apps/pgsql/data.
+
'''Ein gemountetes Repository kann nicht gesichert werden!''' Vor dem Sichern muss also
 +
  $ borg umount /home/gisadmin/Sicherungen/borgmount
 +
ausgeführt werden.
  
 +
== pgBackRest ==
 +
Zur Sicherung des gesamten PostgreSQL-Clusters wird ab Postgres v15 pgbackrest verwendet. In unserem Docker-Image pkorduan/postgis:15-3.3 ist pgBackRest inkludiert.
 +
pgbackrest macht eine physikalische Sicherung des Clusters, es werden die Datendateien direkt gespeichert. Somit sind inkrementelle Sicherungen möglich.
 +
Zudem werden alle WAL-Dateien vom Postgres-Cluster in das pgBackRest-Repository gepusht. Somit ist ein restore zu einem beliebigen Zeitpunkt möglich.
  
Die Sicherung der Datenbank im laufenden Betrieb funktioniert über ''pg_dump'' und ''pg_restore'' und kann cron-gesteuert erfolgen. ''pg_dump'' und ''pg_restore'' finden sich im bin-Verzeichnis von pgsql bzw. bei Nutzung des FGS-Pakets in $FGS_HOME/bin.
+
=== Aufruf ===
 +
Beispielaufruf von pgBackRest in einer jobs.json
 +
<code>
 +
        {
 +
            "name":"postgresql"
 +
            ,"command":["pgbackrest.sh", "kvwmap_prod_pgsql", "full"]
 +
        },
 +
</code>
 +
Das erste Argument des Scriptes entspricht der Bezeichnung des Containers. Das zweite Argument ist full oder incr, je nach gewünschter Sicherungsart.
  
Bei einer Neuinstallation der Datenbank muss PostgreSQL mit initdb initialisiert werden. Alle Konfigurationsdateien, in denen manuelle Änderungen vorgenommen wurden, müssen wiederhergestellt sein.
+
=== Konfiguration ===
 +
Da pgBackRest direkt im Container läuft, liegt dort auch die Standardkonfiguration unter <code>/etc/pgbackrest/conf.d/pgbackrest.local.conf</code>. Die wichtigsten Einstellungen in der Konfiguration betreffen die Retention, das Verwerfen alter Sicherungen. Soll hier vom Standard (30 differenzielle Sicherungen, 2 Vollsicherungen) abgewichen werden, sollte eine entsprechende Datei von außen in den Container eingebunden werden.
  
 +
=== Wiederherstellen ===
  
Die Datensicherung erfolgt zweckmäßigerweise zweigleisig, indem zum einen das Schema, zum anderen die Daten jeweils extra gesichert werden:
+
Grundlage:
 +
Beim restore wird ein gesamtes Cluster wiederhergestellt. In den meisten Anwendungsfällen sollen jedoch nur einzelne Schemen, Tabellen oder einzelne Datensätze wiederhergestellt werden. Zu diesem Zweck wird einer Service ''pgsqlrestore'' erstellt. Dieser stellt einmal das Restore-Cluster mit den wiederhergestellten Daten sowie die Werkzeuge zur Wiederherstellung bereit.
  
  # Schemasicherung
+
  $ dcm create service pgsqlrestore kvwmap_prod
  ./pg_dump -U kvwmap -f /var/.si/dumps/pg_kvwmapsp_daily_schema.sql -s -F c kvwmapsp
+
  $ cd /home/gisadmin/networks/kvwmap_prod/services/pgsqlrestore
# Datensicherung
+
./pg_dump -U kvwmap -f /var/.si/dumps/pg_kvwmapsp_daily_data.sql -a -F c kvwmapsp
+
  
Für das Wiederherstellen der Datenbank wird zunächst über den SQL-Befehl CREATE DATABASE oder dem Hilfsprogramm createdb eine neue, leere Datenbank angelegt. Dann wird das Datenbankschema angelegt:
+
Prüfen Sie ob die Symlinks ''backup'' und ''config'' auf das produktive Cluster zeigen.
  
  ./pg_restore -U kvwmap -d kvwmapsp_neu /var/.si/dumps/pg_kvwmapsp_daily_schema.sql
+
Auflisten der verfügbaren Sicherungen mit
 +
  $ docker exec kvwmap_prod_pgsql pgbackrest info
  
Möglicherweise kann das Schema nicht angelegt werden, weil Abhängigkeiten der Tabellen untereinander bestehen, die verlangen, dass diese Tabellen in einer bestimmten Reihenfolge angelegt werden. Dann wird aus der Schema-SQL-Datei zunächst eine Listendatei erstellt (siehe [http://www.postgresql.org/files/documentation/books/pghandbuch/html/app-pgrestore.html PostgreSQL-Handbuch]):
+
Die Ausgabe enthält Details zu den Sicherungen, Beispiel
 +
$        incr backup: 20230901-220002F_20230914-220002I
 +
$            timestamp start/stop: 2023-09-14 22:00:02 / 2023-09-14 22:00:28
 +
$            wal start/stop: 00000001000000080000000F / 00000001000000080000000F
 +
$            database size: 17.2GB, database backup size: 90.4MB
 +
$            repo1: backup set size: 2.8GB, backup size: 15.9MB
 +
$            backup reference list: 20230901-220002F, 20230901-220002F_20230902-220002I, 20230901-220002F_20230903-220002I, 20230901-220002F_20230904-220001I, 20230901-220002F_20230905-220002I, 20230901-220002F_20230906-220002I, 20230901-220002F_20230907-220002I, 20230901-220002F_20230908-220001I, 20230901-220002F_20230909-220001I, 20230901-220002F_20230910-220002I, 20230901-220002F_20230911-220002I, 20230901-220002F_20230912-220001I, 20230901-220002F_20230913-220002I
  
pg_restore -l /var/.si/dumps/pg_kvwmapsp_daily_schema.sql > /home/fgs/sicherung/liste.txt
+
20230901-220002F_20230914-220002I ist das Label der Sicherung. Soll diese Sicherung wiederherstellt werden verwenden Sie
  
Anschließend können die Zeilen in der ausgegebenen Datei umsortiert oder mit Semikolon auskommentiert werden. Die Wiederherstellung berücksichtigt dann die Reihenfolge in dieser Liste:
+
& ./restore.sh 20230901-220002F_20230914-220002I
  
$ pg_restore -U kvwmap -d kvwmapsp_neu  -L /home/fgs/sicherung/liste.txt /var/.si/dumps/pg_kvwmapsp_daily_schema.sql
+
Aus der Sicherung des produktiven Clusters werden die Datendateien für das Restore-Cluster nach ''/home/gisadmin/networks/kvwmap_prod/services/pgsqlrestore/data'' geschrieben.
 +
Die restore.sh ist so gestaltet, dass das Restore-Cluster im Anschluss gestartet werden kann und und keine weiteren WAL-Dateien aus dem Archiv einspielt werden. Der Stand des Restore-Clusters entspricht somit ca. dem Stopp-Zeitpunkt der Sicherung.
 +
Für eine detaillierte Wiederherstellung über LSNs, XIDs oder andere Wiederherstellungsziele siehe [https://pgbackrest.org/command.html#command-restore offizielle pgBackRest Dokumentation].
  
Manchmal kommen so viele Fehlermeldungen, dass man die ersten auf der Konsole nicht lesen kann.
+
Ist restore.sh durchgelaufen kann das Cluster mit
Fehlermeldungen können mit 2> in eine Datei, z.B. pg_restore.err umgeleitet werden. Wenn Fehler und Ausgaben von pg_restore umgeleitet werden sollen, lautet der Befehl:
+
  $ dcm up pgsqlrestore kvwmap_prod
 
+
gestartet werden. Was mit den Daten im Restore-Cluster geschieht ist nicht Bestandteil dieser Dokumentation. Es können einzelne Tabellen, Schemen, DBs mit pg_dump exportiert werden um sie in das produktive Cluster zu importieren. Es kann auch das gesamte Datenverzeichnis mit cp oder rsync des produktiven Clusters durch das des Recovery-Clusters ersetzt werden.
  $ pg_restore -U kvwmap -d kvwmapsp_neu  -L /home/fgs/sicherung/liste.txt /var/.si/dumps/pg_kvwmapsp_daily_schema.sql > pg_restore.log 2> pg_restore.err
+
 
+
Die Verwendung der Liste ist nützlich zur Wiederherstellung einer Datenbank mit einer alten PostGIS Version in eine Datenbank mit einer neueren PostGIS Version, getestet für den Übergang von 1.3 auf 1.5. Beim Anlegen des Schemas meckert der restore rum, dass die Datei liblwgeom nicht gefunden wird. Das liegt daran, dass in Version 1.5 die Bibliothek postgis.so heißt. Einen symbolischen Link liblwgeom.so auf postgis.so bring auch nichts, weil in postgis.so zum Teil Funktionen nicht drin sind, die in liblwgeom.so von Version 1.3 noch verwendet wurden. Hier hilft z.B. Folgendes:
+
 
+
An Stelle der leeren Datenbank legt man eine Datenbank mit dem neuen postgis_template an, welches schon das neue PostGIS enthält. Dann löscht man alle PostGIS relevanten Einträge in liste.txt, die stehen meistens schon am Anfang hinter plpgsql und enden da, wo die selbst angelegten Tabellen beginnen. Die Sprachunterstützung plpgsql muss man übrigens auch rausnehmen, da diese auch schon im postgis_template enthalten ist. Um die Einträge in spatial_ref_sys wieder herstellen zu können, löscht man vorher den Inhalt der Tabelle spatial_ref_sys, sonst hat man da doppelte Einträge drin.
+
 
+
Wenn das Datenbankschema erfolgreich angelegt wurde, können die Daten eingespielt werden:
+
 
+
./pg_restore -U kvwmap -d kvwmapsp_neu /var/.si/dumps/pg_kvwmapsp_daily_data.sql
+
 
+
Oder auch unter Berücksichtigung der Listendatei, d.h. nur Wiederherstellung bestimmter Tabellen:
+
 
+
./pg_restore -U kvwmap -d kvwmapsp_neu -L /home/fgs/sicherung/liste.txt /var/.si/dumps/pg_kvwmapsp_daily_data.sql
+
 
+
=====dump.sh=====
+
Mit pg_dump erstellte Dumps beinhalten nur Informationen zum Schemaaufbau und den enthaltenen Daten. Soll ein Postgres-Cluster wiederhergestellt werden bedarf es noch Informationen über die Tablespaces und Rollen. Diese können mit pg_dumpall gedumpt werden. Der kvwmap-server kommt mit 2 Dateien für einen vollständigen dump und restore (experimentell), zu finden unter
+
/home/gisadmin/kvwmap-server/scripte/sicherung/postgres_dump_restore
+
 
+
dump.sh dumpt mit pg_dumpall die Tablespaces und Rollen. Anschließend werden alle relevanten Schemen und deren Daten mit pg_dump rausgeschrieben. Für eine vollständige Sicherung eine Clusters kann dieses Verfahren angewendet werden.
+
 
+
====Datensicherung MySQL====
+
Die Datenbank kann auf zwei verschiede Art und Weise gesichert werden.
+
* Kopieren des gesamten Verzeichnisses einer Datenbank, Datenbank muss dazu gestoppt sein, oder es ist sicher, dass keiner mehr zugreift.
+
* Erzeugen und Sichern eines Datenbankdumps, geht aus dem laufendem Betrieb heraus.
+
 
+
Zu einer Datenbank gehört immer das gleichnamige Verzeichnis unter dem Datenverzeichnis von mysql. Das ist meißtens unter /var/lib/mysql kann aber auch unter /usr/local/mysql/var o.ä. sein. Das Verzeichnis der Datenbank einfach einpacken und später dahin wieder auspacken zur Wiederherstellung.
+
 
+
Beispiel für die Sicherung eines Datenbankverzeichnisses.
+
$cd /usr/local/mysql/var
+
$tar cvfz kvwmapdb160-2006-09-09.tar.gz kvwmapdb160
+
$tar xvfz kvwmapdb160-2006-09-09.tar.gz -C /usr/local/mysql/var
+
 
+
Für die andere Variante führt man zunächst einen Dump von der laufenden Datenbank aus über die Dumpfunktion von phpMyAdmin oder das Programm mysqldump unter /usr/local/bin
+
Es ist vorteilhaft den Pfad /usr/local/bin in die PATH Variable zu schreiben:
+
 
+
$export PATH=$PATH:/usr/local/bin
+
 
+
Optionen und Nutzung von mysqldump werden ausgegeben mit
+
 
+
$./mysqldump --help
+
 
+
Eine einzelne DB wird z.B. gesichert mit:
+
 
+
$./mysqldump -u root -p kvwmapdb160 > kvwmapdb160-dump_2006-09-09.sql
+
+
Zum wiederherstellen der Datenbank muss eine neue Datenbank angelegt werden.
+
 
+
$./mysql -u root -p
+
mysql$ create database kvwmapdb160;
+
mysql$ exit
+
 
+
Einlesen des Dump mit:
+
 
+
$./mysql -u root -p kvwmapdb160 < kvwmapdb160-dump_2006-09-09.sql
+
 
+
====weitere Beispiele====
+
 
+
MySQL-Datenbank kvwmapdb
+
MySQL-Datenbank mysql
+
mysqldump -h mysql --user=${Nutzername} --password=${Password} --databases ${Datenbankname} > ${Sicherungsverzeichnis}/${Sicherungsdatei} 2>&1 ${Logverzeichnis}/${Logdatei}
+
Wobei die in {} gesetzten Bezeichner angepasst werden müssen. z.B.
+
mysqldump -h mysql --user=kvwmap --password=${secret} --databases kvwmapdb > /home/gisadmin/Sicherungen/day/3/kvwmapdb.dump 2>&1 /home/gisadmin/Sicherungen/day/3/kvwmapdb.log
+
PostgreSQL-Datenbank kvwmapsp
+
pg_dump -h pgsql -U ${Nutzername} -Fc -f ${Sicherungsverzeichnis}/${Sicherungsdatei} ${Datenbankname} 2>&1 ${Logverzeichnis}/${Logdatei}
+
Wobei die in {} gesetzten Bezeichner angepasst werden müssen. z.B.
+
pg_dump -h pgsql -U kvwmap -Fc -f /home/gisadmin/Sicherungen/day/3/kvwmapsp.dump kvwmapsp 2>&1 /home/gisadmin/Sicherungen/day/3/kvwmapsp.log
+
Die Sicherung im Beispiel sichert das Schema und die Daten. Bei bestimmten Datenbanken könnten auch nur die Daten oder nur das Schema gesichert werden. Außerdem könnte man auch einzelne Schemas oder Tabellen sichern oder zumindest eine Gesamtsicherung machen solange sich das Schema oder bestimmte Daten nicht ändern und dann nur die Daten oder nur die sich ändernden Tabellen sichern.
+
Nur Datenbankstruktur sichern (Schema)
+
pg_dump -h pgsql -U kvwmap -Fc -s -f /home/gisadmin/Sicherungen/day/3/kvwmapsp_only_schema.dump kvwmapsp 2>&1 /home/gisadmin/Sicherungen/day/3/kvwmapsp.log
+
Nur Daten sichern (Daten)
+
pg_dump -h pgsql -U kvwmap -Fc -a -f /home/gisadmin/Sicherungen/day/3/kvwmapsp_only_data.dump kvwmapsp 2>&1 /home/gisadmin/Sicherungen/day/3/kvwmapsp.log
+
Nur das Schema fachdaten sichern (Schema und Daten)
+
pg_dump -h pgsql -U kvwmap -Fc -n fachdaten -f /home/gisadmin/Sicherungen/day/3/kvwmapsp_schema_fachdaten.dump kvwmapsp 2>&1 /home/gisadmin/Sicherungen/day/3/kvwmapsp.log
+
Nur Tabelle verkehr.baustellen sichern (Schema und Daten)
+
pg_dump -h pgsql -U kvwmap -Fc -t verkehr.baustellen -f /home/gisadmin/Sicherungen/day/3/kvwmapsp_table_verkehr_baustellen.dump kvwmapsp 2>&1 /home/gisadmin/Sicherungen/day/3/kvwmapsp.log
+
 
+
Alle weiteren MySQL oder Postgresql-Datenbanken, die von kvwmap oder anderen Web-Anwendungen auf dem Server verwendet werden sind zu sichern, soweit sie Primärdaten beinhalten oder deren sonstige Herstellung zu aufwendig wäre.
+
 
+
Die Nutzer von PostgreSQL werden bei einem einfachen pg_dump nicht mit gesichert. Wenn also das gesamte Datenbankcluster wiederhergestellt werden soll, muss anschließend der kvwmap-Nutzer wieder eingerichtet werden bevor die kvwmapsp Datenbank wiederhergestellt werden kann. Das gleiche gilt auch für andere Nutzer, die ggf. auf dem Postgres eingerichtet sind. Sind mehrere Nutzer in der Datenbank angelegt lohnt sich evtl. die Sicherung der Nutzer. Dazu kann der Befehl [https://www.postgresql.org/docs/9.6/app-pg-dumpall.html pg_dumpall] mit der Option -r verwendet werden, z.B:
+
Nur die Nutzer
+
pg_dumpall -h pgsql -U kvwmap --password={Passwort} --rules-only -f sicherungsdatei.sql
+
Nutzer und Namespaces
+
pg_dumpall -h pgsql -U kvwmap --password={Passwort} --globals-only -f sicherungsdatei.sql
+
 
+
==Backup-Strategie==
+
Es wird empfohlen nach dem Generationenprinzip kombiniert mit der 3-2-1-Regel für Backups zu sichern. Die 3-2-1-Regel besagt dass man 3 Kopien auf 2 unterschiedlichen Datenträgern/Medien und eine davon off-site haben sollte. Dieses lässt sich gut mit dem Generationenprinzip vereinbaren. Hierbei werden täglich Sicherungen von allen relevanten Daten gemacht. Dies sind die Söhne. Einmal pro Woche wird die letzte Tagessicherung als Wochensicherung gesichert, dies ist eine Vater-Sicherung. Einmal im Monat wird die letzte Wochensicherung auf einem entfernten Host kopiert - die Großvater-Sicherung.
+
Die Tagessicherungen werden rollierend nach 7 Tagen gelöscht, die Wochensicherungen nach einem Monat. Auf dem Host liegen somit maximal 7 Tagessicherungen und 4 Wochensicherungen.
+
  
 
=CronJobs=
 
=CronJobs=
Zeile 4.935: Zeile 5.669:
  
 
===Geometriedaten Speichern (Update)===
 
===Geometriedaten Speichern (Update)===
 +
==== Punktdaten Speichern ====
 
Case:
 
Case:
 
* go = PointEditor_Senden
 
* go = PointEditor_Senden
Zeile 4.946: Zeile 5.681:
 
* oid = Die oid des Datensatzes dessen Punktgeometrie geändert werden soll.
 
* oid = Die oid des Datensatzes dessen Punktgeometrie geändert werden soll.
 
Controller:
 
Controller:
* $GUI->PointEditor_Senden() darin pointeditor->eintragenPunkt()
+
* $GUI->PointEditor_Senden() darin $pointeditor->eintragenPunkt()
 +
==== Polygondaten Speichern ====
 +
Case:
 +
* go = PolygonEditor_Senden
 +
Parameter:
 +
* selected_layer_id: ID des zu editierenden Layers
 +
* newpathwkt: Geometry im WKT Format
 +
Controller:
 +
* $GUI->PolygonEditor_Senden() darin $polygoneditor->eintragenFlaeche()
  
 
===Sachdaten Speichern (Update)===
 
===Sachdaten Speichern (Update)===
Zeile 4.952: Zeile 5.695:
 
* go = Sachdaten_speichern
 
* go = Sachdaten_speichern
 
Parameter:
 
Parameter:
* form_field_names = <layer_id>;<attribut_name>;<table_name>;<oid>;<formtyp>;1;<datentyp>;|...
+
* changed_<layer_id>_<oid> = 1 ...... gibt an, dass der Datensatz geändert worden ist
 +
* form_field_names = <layer_id>;<attribut_name>;<table_name>;<oid>;<formtyp>;<nullable>;<datentyp><saveable> ..... die Auflistung welche Formularfeldnamen beteiligt sind; weitere sind durch das Pipe Zeichen | getrennt
 +
* <layer_id>;<attribut_name>;<table_name>;<oid>;<formtyp>;<nullable>;<datentyp><saveable> = <Wert>  ..... die Formularfeldnamen mit ihren Werten
 
Controller:
 
Controller:
 
* $GUI->sachdaten_speichern()
 
* $GUI->sachdaten_speichern()
Beispiel:
+
Beispiel für Layer_ID=1769, Objekt-ID=12345, Tabellenname=fh_erfassung:
  
 
<code>
 
<code>
index.php?go=Sachdaten_speichern&form_field_names = 10;id;shapefiles;920233;Text;1;int4|10;filename;shapefiles;920233;Text;1;varchar|
+
index.php?
10;epsg_code;shapefiles;920233;Text;1;int4|
+
 
10;datatype;shapefiles;920233;Text;1;int2|
+
go=Sachdaten_speichern&
10;layer_id;shapefiles;920233;Text;1;int4|
+
 
10;stelle_id;shapefiles;920233;StelleID;1;int4|
+
changed_1769_12345=1&
10;konvertierung_id;shapefiles;920233;Text;1;int4|
+
 
10;bezeichnung;konvertierungen;;Text;1;varchar|
+
form_field_names=1769;buchende_stellen;fh_erfassung;12345;Text;1;_int4;1&
10;zurueck;;;dynamicLink;;|
+
 
 +
1769;buchende_stellen;fh_erfassung;12345;Text;1;_int4;1=[12,42]
 
</code>
 
</code>
  
Zeile 4.980: Zeile 5.726:
 
* go = Layer_Datensaetze_Loeschen
 
* go = Layer_Datensaetze_Loeschen
 
Parameter:
 
Parameter:
 +
* chosen_layer_id = <layer_id>
 
* check;<main_table_name>;<alias_name>;<oid> = "on"
 
* check;<main_table_name>;<alias_name>;<oid> = "on"
 
* checkbox_names_<layer_id> = "check;<main_table_name>;<alias_name>;<oid>"|...
 
* checkbox_names_<layer_id> = "check;<main_table_name>;<alias_name>;<oid>"|...
 +
optional:
 +
* mime_type = 'json'
 +
* format = 'json_result'
 +
* output = 'false'
 
Controller:
 
Controller:
 
* $GUI->layer_Datensaetze_loeschen()
 
* $GUI->layer_Datensaetze_loeschen()
 +
 
===Zoom zu einer Koordinate===
 
===Zoom zu einer Koordinate===
 
Case:
 
Case:
Zeile 5.006: Zeile 5.758:
 
Beispiel
 
Beispiel
 
* index.php?go=zoom2coord&INPUT_COORD=32433010,5896996;32433210,5897196&epsg_code=4647
 
* index.php?go=zoom2coord&INPUT_COORD=32433010,5896996;32433210,5897196&epsg_code=4647
===Zoom auf ein vorhandenes Punktobjekt===
+
=== Zoom zu einem Datensatz eines Layers ===
 
Parameter
 
Parameter
* oid Die ID des Objektes. Als ID wird die im Layer definierte ID-Spalte verwendet.
+
* layer_id Die ID des Layers in dem sich der Datensatz befindet.
* layer_id Die ID des Layers in dem das Objekt ist, auf das gezoomt werden soll.
+
* layer_columnname Der Name des Attributs in dem die Geometrie ist auf die gezoomt werden soll.
* layer_tablename Der für die Suche im Layer zu verwendende Tabellenname
+
* oid Die ID des Datensatzes aus der Spalte, die in der Layerdefinition als oid-Spalte definiert ist.
* layer_columnname Die im Layer zu verwendete Spalte für die Geometrie, die die Objektgeometrie beinhaltet.
+
 
* selektieren (optional) Wenn hier "zoomonly" angegeben ist, wird nur auf das Objekt gezoomt und kein Suchergebnislayer angelegt. Wird "true" angegeben, wird ein Suchergebnislayer angelegt und der betroffene Layer ausgeschaltet, so dass nur das gesuchte Objekt zu sehen ist.  
+
 
Controller
 
Controller
* $GUI->zoom_toPoint()
+
* $GUI->zoomto_dataset()
Beispiel
+
 
* index.php?go=zoomtoPoint&oid=54485&layer_tablename=pegel&layer_columnname=the_geom&layer_id=14&selektieren=zoomonly
+
===Zoom auf ein vorhandenes Linienobjekt===
+
Case
+
* go=zoomtoLine
+
Parameter
+
* wie bei [[Admin-Dokumentation#Zoom_auf_ein_vorhandenes_Punktobjekt|Zoom auf ein vorhandenes Punktobjekt]]
+
Controller
+
* $GUI->zoom_toLine()
+
Beispiel
+
* index.php?go=zoomtoLine&oid=87&layer_tablename=liniengewaesser_pumpgebiet&layer_columnname=geom&layer_id=63&selektieren=zoomonly
+
===Zoom auf ein vorhandenes Linienobjekt===
+
Case
+
* go=zoomtoPolygon
+
Parameter
+
* wie bei [[Admin-Dokumentation#Zoom_auf_ein_vorhandenes_Punktobjekt|Zoom auf ein vorhandenes Punktobjekt]]
+
Controller
+
* $GUI->zoom_toPolygon()
+
 
Beispiel
 
Beispiel
* index.php?go=zoomtoPolygon&oid=50969&layer_tablename=feldbloecke&layer_columnname=the_geom&layer_id=3&selektieren=zoomonly
+
* index.php?go=zoomto_dataset&layer_id=19&layer_columnname=the_geom&oid=54485
  
 
===Zoom zu einem gespeicherten Kartenkommentar===
 
===Zoom zu einem gespeicherten Kartenkommentar===
Zeile 5.058: Zeile 5.792:
  
 
==Kartenkonfiguration (MySQL Datenbank)==
 
==Kartenkonfiguration (MySQL Datenbank)==
 +
===Layer Anlegen===
 +
Case
 +
* go=Layereditor
 +
* go_plus=Als%20neuen%20Layer%20eintragen
 +
Parameter
 +
* id
 +
* Name
 +
* alias
 +
* und alle weiteren Parameter des Layers
 +
Controller
 +
* $GUI->LayerAnlegen()
 +
 
===Layer Bearbeiten===
 
===Layer Bearbeiten===
 
Case
 
Case
Zeile 5.105: Zeile 5.851:
 
Beispiel
 
Beispiel
 
* <code>index.php?go=Style_Label_Editor&selected_layer_id=105</code>
 
* <code>index.php?go=Style_Label_Editor&selected_layer_id=105</code>
 +
 +
===Menüverwaltung===
 +
Öffnet die Liste der Menüpunkte.
 +
Case
 +
* go=Menues_Anzeigen
 +
Controller
 +
* $GUI->MenuesAnzeigen
 +
View
 +
* layout/snippets/menuedaten.php
  
 
=Benutzung von kvwmap=
 
=Benutzung von kvwmap=
Zeile 5.236: Zeile 5.991:
  
 
= Fehlermeldungen =
 
= Fehlermeldungen =
 +
Wenn die Parameter format=json, format=json_result, mime_type=json oder content_type=application_json bei einer Anfrage angegeben werden, wird eine Fehlermeldung im JSON-Format { "success" : false, "msg" : "Fehlermeldung" } mit dem HTML-Header Content-Type: application/json ausgegeben statt mit einer HTML-Fehlermeldung und HTML-Response-Code 500.
 +
 
siehe auch [[Nutzer-Dokumentation#Fehlermeldungen|Nutzer-Dokumentation]]
 
siehe auch [[Nutzer-Dokumentation#Fehlermeldungen|Nutzer-Dokumentation]]
 
== SQL-Fehler ==
 
== SQL-Fehler ==

Aktuelle Version vom 30. Oktober 2024, 16:56 Uhr

Inhaltsverzeichnis

Weitere Informationen im kvwmap Forum

Übersicht

kvwmap setzt unter anderem auf Apache, UMN-MapServer, php-Mapscript, MySQL, Postgres mit PostGIS und OGR auf.
Dank an dieser Stelle für die Entwicklung und Bereitstellung der genannten Software.

Uebersicht Architektur.jpg

Dieses Manual wurde erstellt unter Mitwirkung von

Peter Korduan, Stefan Rahn, Markus Hentschel, Hauke Christoph, Heinz Schmidt

und vielen Anderen.

An der Entwicklung von kvwmap waren und/oder sind bisher beteiligt:

Peter Korduan, Stefan Rahn, Hauke Christoph, Conrad Gühler, Swen Hüner, Markus Hentschel, Holger Riedel, Heinz Schmidt

Vielen Dank auch für die Zuarbeiten und Hinweise aus den Katasterämtern der Landkreise Rostock, Vorpommern-Rügen, Vorpommern-Greifswald, Mecklenburgische Seenplatte, Ludwigslust-Parchim und die Landeshauptstadt Schwerin.

Dienstleistungen zu kvwmap werden angeboten von:

GDI-Service Rostock


Status des kvwmap-WIKIs: in Work!!

Die Dokumentation erhebt keinen Anspruch auf Vollständigkeit. Sie wird sowohl von den Entwicklern als auch von den Anwendern aktualisiert und laufend gehalten. Dennoch kann es vorkommen, dass bestimmte Inhalte nicht immer ganz zur aktuellsten Version passen. Als registrierter Teilnehmer dieses WIKIs können Sie Fehler selbst beheben und die Dokumentation auf dem aktuellsten Stand halten. Wenn Sie nicht registriert sind, sind Zuarbeiten, Hinweise und Korrekturvorschläge selbstverständlich genauso herzlich willkommen. Schreiben Sie an die o.g. Personen, die auch in der Teilnehmerliste auftauchen.

Die Dokumentation wird in der jeweils aktuellen Version jedem neuen Versionspaket von kvwmap im Unterordner help hinzugefügt. Für die Richtigkeit und Vollständigkeit der folgenden Angaben wird keine Garantie übernommen.

Funktionalität im Client

Folgende Funktionalitäten werden von dem Client bereitgestellt:

Anzeige

Menüs für gruppierte Funktionen und Layer
Karte und Übersichtskarte
Maßstabszahl und Maßstabsbalken
Anzeige welche Layer aktiv und im Abfragemodus sind
Legenden der Layer, ausschaltbar mit Minus.gif
Menü und Layeranzeige sind ausblendbar mit Double arror left.png und Double arror right.png
Anzeige der Koordinaten an aktueller Cursorposition in Statuszeile Statuszeile.png
Anzeige kvwmap-Version, Datum, angemeldeter Nutzer und aktuelle Stelle

Navigation

Navigationsleiste des SVG-Clients

Back.png Vorheriger Ausschnitt (History-Funktion)
Frwd.png Nächsten Ausschnitt (History-Funktion)
Pan.png Pan (durch Ziehen des Bildschirmausschnittes an eine neue Stelle)
Pan.png Zentrieren (der zu klickende Punkt wird in Kartenmitte versetzt)
Zoomin.png Zoom in (durch Aufziehen einer Box)
MausradZoom.png
Zoomin.png Zoom in (durch Klicken i. d. Karte bei wählbarem Zoomfaktor)
Zoomout.png Zoom out (durch Klicken i. d. Karte bei wählbarem Zoomfaktor)
Jumpto.png Eingabe eines konkreten Koordinatenpaars ('Koordinatenzoom')
  • Eingabe eines konkreten Maßstabs
    Massstab.png
  • Tool-Tipps einblenden
    Tooltip.png
  • Mausrad-Zoom
    • Rad Richtung Bildschirm drehen zum Reinzoomen
    • Rad vom Bildschirm weg drehen zum Rauszoomen
  • Gesten auf Touchpads
    • Zwei Finger auseinander ziehen zum Reinzoomen
    • Zwei Finger aufeinander zubewegen zum Rauszoomen
    • Zwei Finger im gleichen Abstand in eine Richtung ziehen zum Verschieben der Karte
  • Schnellsprung-Zoom, zum schnellen Zoom auf z.B. Gemeinde, Amt, usw.
    • Über die Konstante LAYER_ID_SCHNELLSPRUNG in der config.php kann ein beliebiger Polygonlayer dafür verwendet werden
    • Der Layer muss die ID-Spalte der Haupttabelle as Attribut "oid" abfragen
    • Das Attribut "oid" muss im Attributeditor als Auswahlfeld mit z.B. folgendem SQL: "select oid as value, name as output from gemeinden order by name" definiert sein

Themenbaum

Legende
  • Gruppierung der Layer
    • Anzeige der Gruppennamen
    • Zuordnung der Layer zu den Gruppen
    • Auf- und Zuklappen der Legende einzelner Gruppen (Plus.gif|Minus.gif vom Gruppennamen)
    • Gleichzeitiges De- oder Aktivieren aller Layer der Gruppe für die Informationsabfrage Pfeil.gif
    • Gleichzeitiges Ein- oder Ausschalten der Sichtbarkeit aller Layer der Gruppe Pfeil.gif
  • Layer
    • Ein- und Ausschalten des Layers für die Anzeige Checkbox.png
    • Ein- und Ausschalten des Layers für die Sachdatenabfrage Checkbox.png
    • Zoom auf die maximale Ausdehnung des Layers (MaxLayerExtent.gif hinter dem Layernamen, geht derzeit nur für aktuell eingeblendete PostGIS Layer)
    • Ein- und Ausschalten der Klassen des Layers (Plus.gif|Minus.gif hinter dem Layernamen)
    • Ausschalten aller Layer für die Anzeige und Abfrage (Symbole ganz oben in der Legende). Letzters ist auch möglich über die go-Variablen "go=reset_layers" bzw. "go=reset_querys"

Legende

Bei einigen Anwendungen wird zusätzlich zu dem Themenbaum auch eine Legende angezeigt. Zwischen Themen und Legende kann mit einem Klick auf die entsprechenden Reiter gewechselt werden, siehe Abbildung.

Abfragen

Das Abfrageergebnis wird in einem eigenen Fenster angezeigt. Spaltenbezeichnungen und Layouteinstellungen können in Vorlagen angepasst werden

  • Auswahl der abfragbaren Layer in Legende
  • Anklicken eines entsprechenden Objekts Query.png
  • Aufziehen einer Box um betreffende Objekte Query.png
  • Abfrage eines Objektes und aller angrenzenden Objekte Touchquery.png
  • Klick in die Karte und Angabe eines Abfrageradius' Query-radius.png
  • Zeichnen eines Abfragepolygons Polyquery.jpg
  • Koordinatenabfrage coord query.PNG
  • Abfrage der ALKIS-Daten beim Flurstückslayer, Ausgabe in PDF im amtlichen Format

Suche

Alle Suchfunktionen funktionieren natürlich nur, wenn die entsprechenden Daten in kvwmap eingebunden sind und auch in der Stelle in der die Suche stattfinden soll verfügbar sind.

  • Flurstücke (Gemeinde-Gemarkung/Flur/Flurstück)
  • Adressen (Gemeinde/Strasse/Hausnummer)
  • Grundbuchblätter (Grundbuchbezirksschlüssel/Grundbuchbezirk-Auswahl/Grundbuchblatt)
  • Namen (Name, Vorname Geburtsname/Firma/geboren am/Firmenzusatz/Strasse Hausnummer/PLZ Ort/Grundbuchbezirk/Grundbuchblatt/Gemarkung, Gemeinde - Auswahl)
  • Festpunkte (Kilometerquadrat/Punktkennzeichen)
  • Jagdbezirke (laufende Nummer/Name/Art)
  • Layer (Layername/zum Layer gehörende Attribute)
Mit der Layersuche lassen sich sowohl PostGIS-Layer als auch WFS-Layer durchsuchen. Die Suchfunktion ist generisch. Das heißt, das Suchfenster wird für die jeweiligen zu durchsuchenden Layer automatisch an Hand der vordefinierten Attribute bereitgestellt. Bei WFS-Layern stehen alle Sachattribute, die der WFS anbietet für die Suche zur Verfügung. Bei PostGIS-Layern können die Attribute durchsucht werden, für die der Nutzer mindestens Leserecht hat.
Layersuche.png

Merkliste

Es gibt die Möglichkeit gefundene Datensätze auf eine Merkliste zu setzen. Für einen einzelnen Datensatz geschieht das in der Sachdatenanzeige über den Button "Datensatz merken" MerklisteEinenDatensatzHinzufuegen.png. Mehrere ausgewählte oder alle Datensätze können mit dem Button "merken" MerklisteAlleDatensaetzeHinzufuegen.png am Ende der Sachdatenanzeige eines Layers auf die Merkliste gesetzt werden.

Die Anzeige der Merkliste erfolgt über den Anwendungfall "go=Zwischenablage" für den ein Menüpunkt angelegt werden sollte.

Die Merkliste selbst zeigt die Layer und die Anzahl der Objekte pro Layer an.

Merkliste.png

Man kann alle Objekte eines Layers von der Liste entfernen oder die gesamte Merkliste leeren. Klickt man auf einen Layernamen oder die Anzahl der Objekte werden die gemerkten Objekte angezeigt. Die gemerkten Objekte haben statt des Button "merken" jetzt den Button "" MerkenEinesDatensatzesLoeschen.png . Am Ende der Sachdatenanzeige des Layers erscheint ein Button "" MerkenAllerDatensaetzeLoeschen.png.

Geo-Namen-Suche

Es gibt die Möglichkeit einen Geo-Namen-Such-Dienst für eine schnelle Adresssuche zu verwenden. Für die Definition des Dienstes sind die beiden config-Parameter GEO_NAME_SEARCH_URL und GEO_NAME_SEARCH_PROPERTY zuständig.

In GEO_NAME_SEARCH_URL wird die URL des Dienstes mit allen benötigten Parametern eingetragen. Z.B. für

geocodr : https://geo.sv.rostock.de/geocodr/query?shape=centroid&limit=20&out_epsg=4326&key=<API-Key>&type=search&class=address&query=
nominatim: https://nominatim.openstreetmap.org/search.php?format=geojson&q=

In GEO_NAME_SEARCH_PROPERTY wird das Attribut eingetragen, welches in der Trefferliste angezeigt werden soll. Z.B. für

geocodr: _title_
nominatim: display_name

Um die Geo-Namen-Suche in die Oberfläche zu integrieren, fügt man einfach dieses Stückchen Code in den eigenen Header an geeigneter Stelle ein:

<? include(SNIPPETS.'geo_name_search.php'); ?>

Um die Suche räumlich einzugrenzen, kann man die nominatim-URL um folgende Parameter erweitern:

https://nominatim.openstreetmap.org/search.php?format=geojson&viewbox=11.9987,54.04853,12.23795,54.20613&bounded=1&q=

und die geocodr-URL um diese hier:

https://geo.sv.rostock.de/geocodr/query?shape=centroid&limit=20&out_epsg=4326&key=<API-Key>&type=search&class=address&bbox=11.9987,54.04853,12.23795,54.20613&bbox_epsg=4326&query=

Messen

Streckenmessung mit 2 gefangenen Eckpunkten (rot) und einem über "Ortho-Fang" gefangenen Lotfusspunkt (grün)
  • Koordinaten bestimmen
    Koordinaten.png
  • Streckenmessungen
    Mesure.png Tooltip strecke.png
  • Flächenmessungen
    Polyquery.jpg Flaecheninhalt.gif
Unterhalb der Karte lässt sich ein Punktfang aktivieren. Dadurch werden alle (aber max. 10000) Eckpunkte der in den aktiven PostGIS-Layern vorhandenen Geometrien in der Karte als fangbare Punkte zur Verfügung gestellt. Bewegt man die Maus über einen solchen Punkt, erscheint die tatsächliche Koordinate millimetergenau in der Koordinatenanzeige.
Bei der Streckenmessung lassen sich die Fangpunkte mit in den gemessenen Streckenzug aufnehmen. Außerdem steht hier ein sog. "Ortho-Fang" zur Verfügung. Beim Ortho-Fang ist ein Fangen der Kanten zwischen den Geometrie-Eckpunkten möglich, wobei der Lotfusspunkt auf der Kante berechnet und als fangbarer Punkt zur Verfügung gestellt wird. Dadurch lässt sich der orthogonale Abstand eines beliebigen Punktes zu einer Kante messen.
Die gemessene Strecke wird mit Millimetergenauigkeit angezeigt solange nur gefangene Punkte und keine Freihandpunkte in die Streckenmessung aufgenommen wurden. Sobald Freihandpunkte verwendet werden, wird die Strecke nur so genau angegeben, wie es der aktuelle Maßstab zulässt.

Redlining

  • Freihandpolygon zeichnen Freepolygon.png
  • Text hinzufügen Freetext.png
  • Pfeil hinzufügen Freearrow.png


Der Generische Layereditor GLE

Der generische Layereditor (GLE) stellt zur Laufzeit Oberflächen zur Verfügung, die dynamisch ("generisch") aus den rollenbasierten Nutzerrechten und der layerbasierten Definition erzeugt werden. Diese Oberflächen stehen teilweise nur den Administratoren, teilweise aber auch den Nutzern von kvwmap zur Verfügung:

  • Sachdatensuche (go=Layer-Suche)
  • Sachdatenanzeige und -bearbeitung
  • Erfassung neuer Datensätze
  • Sachdatendruckeditor
  • Filterverwaltung
  • Layerattribut-Definition
  • Layerattribut-Rechteverwaltung

In der Sachdatensuche stellt der GLE die Attribute zusammen, die dem Nutzer in dieser Stelle angezeigt werden. In den Attributen kann dieser dann mit Hilfe von verschiedenen Operatoren umfangreich recherchieren. Die Sachdatensuche kann räumlich eingeschränkt werden, dazu ist der Geometrie-Editor zur Erstellung eines Polygons in die Oberfläche integriert.

In der Sachdatenanzeige (die Ergebnis einer Sachdatensuche oder einer Infoabfrage aus der Karte heraus sein kann) werden die Attribute angezeigt, die dem Nutzer in dieser Stelle per Rechtedefinition zur Verfügung stehen. D.h. der GLE erzeugt an Hand der im Query-Statement des Layers vorkommenden Attribute und den entsprechenden Rechten der aktuellen Stelle ein Layereditor-Formular. Hier ist es dem Nutzer möglich, die Attribute von Postgis-Layern zu bearbeiten - wenn er das Recht dazu hat. Je nach Formularelementtyp des Attributs können verschiedene Möglichkeiten zur Verfügung stehen: einzeilige oder mehrzeilige Textfelder, Auswahlfelder, Checkboxen etc. Mit dem Klick auf 'speichern' werden die geänderten Datensätze in die entsprechende(n) Tabelle(n) geschrieben.

Ein Link ermöglicht die Bearbeitung der Geometrie im Geometrie-Editor. Um Sach- oder Geometriedaten zu verändern, muß das entsprechende Recht in der Layerattribut-Rechteverwaltung gesetzt sein.

Wie die Sachdatenanzeige aussieht, wird durch das stellenbezogene Feld "Template" bestimmt. Es gibt derzeit 3 verschiedene Varianten:

  • Zeilenweise Variante (Standard): Datensätze untereinander und Attribute zeilenweise untereinander: Die standardmäßige Darstellungsvariante des GLE (Feld Template ist leer) sieht so aus, dass die Datensätze untereinander und in jedem Datensatz auch die Attribute zeilenweise untereinander angezeigt werden. Diese Variante eignet sich für die meisten Layer, da es durch die Untereinanderanordnung keine Einschränkung in der Attributanzahl gibt. Im Attributeditor kann man die Anordnung der Attribute optimieren und z.B. mehrere Attribute in einer Zeile darstellen.
  • Spaltenweise Variante: Attribute spaltenweise und Datensätze zeilenweise untereinander: Hat ein Layer nur wenige Attribute und Abfragen auf diesen Layern liefern aber meist sehr viele Datensätze, eignet sich evt. die listenförmige Darstellung (Feld Template="generic_layer_editor.php"). Hier werden die Attribute spaltenweise nebeneinander und die Datensätze zeilenweise in einer Tabelle angezeigt. In dieser Variante hat man außerdem die Möglichkeit, mehrere Datensätze auf einmal zu bearbeiten.
  • Rasterförmige Variante: Diese Darstellungsvariante ("Raster" meint eher "Schachbrett") eignet sich besonders für Dokumente (Feld Template="generic_layer_editor_doc_raster.php"). Damit werden die Datensätze rasterförmig neben- und untereinander angezeigt, wobei in jedem Datensatz nur bestimmte Attribute sichtbar sind. Erst wenn man mit der Maus in einen Datensatz klickt, werden die restlichen Attribute eingeblendet. Im Attributeditor kann man einstellen, welche Attribute anfangs sichtbar sein sollen. Mit dieser Variante lässt sich so z.B. eine schnelle Bildsuche realisieren, indem man nur das Bild-Attribut sichtbar schaltet, so dass nur die Vorschaubilder angezeigt werden. Bewegt man die Maus über eines der Vorschaubilder, erscheint es außerdem vergrößert am rechten Bildschirmrand.

Für die Erfassung von neuen Datensätzen stellt der GLE eine eigene Oberfläche zur Verfügung, in der die Attribute des Layers angezeigt werden, die dem Nutzer in dieser Stelle per Rechtedefinition zur Verfügung stehen. Auch hier kann der Nutzer nur die Attribute bearbeiten, für die er das Recht dazu hat. Der Geometrie-Editor zur Erfassung der Geometrie ist in die Oberfläche integriert.

Damit ein Postgis-Layer mit dem generischen Layereditor bearbeitet werden kann, müssen folgende Voraussetzungen geschaffen sein:

  • In der sog. "Query" der Layerdefinition muss eine SQL-Abfrage formuliert werden, die die Attribute des Layers sammelt, die in der Fachdatenanzeige eine Rolle spielen sollen.
  • Die sog. "Haupttabelle" muss oids besitzen (Das Feld wird beim Anlegen oder Speichern eines Layers automatisch gefüllt, wenn es leer ist. Sollte bei einer Layerdefinition über mehrere Tabellen hinweg dort jedoch die falsche Tabelle stehen, kann man den Namen der Haupttabelle von Hand korrigieren.)
  • Dem Layer darf in der jeweiligen Stelle kein Template zugeordnet sein (mit Ausnahme des Raster-Templates "generic_layer_editor_doc_raster.php", siehe oben)

Über den Template-Eintrag lässt sich also steuern, ob für einen Layer der generische Layereditor oder ein Snippet zur Sachdatenanzeige verwendet werden soll.

Es werden sowohl Punkt-, Linien-, als auch Polygon-Layer unterstützt. Falls die Geometrien auch editiert werden sollen, ist bei den Polygon- und Linienlayern ist darauf zu achten, dass die entsprechenden Geometriespalten als 'MULTIPOLYGON' bzw. 'MULTILINESTRING' angelegt werden. Die Polygon- bzw. Linien-Geometrien die mit dem Geometrie-Editor von kvwmap erzeugt werden, werden nämlich immer als Multi-Geometrien in die Datenbank geschrieben.

Bei der Speicherung der Layerdefinition holt der GLE eine Reihe von Datenbankmerkmalen der jeweiligen Attribute aus der Postgis-DB und verwendet diese in den verschiedenen GLE-Oberflächen (z.B. Constraints, NOT NULL, Defaults etc.).

Die Einstellungen der Layer für den GLE erfolgen über den Layereditor. Der Layereditor unterteilt sich in die Allgemeinden Einstellungen, Klasseneditor, Style- und Labeleditor, Attributeditor, Stellenzuweisung und Rechteeditor. Man gelangt über die Reiter zu den jeweiligen Einstellungen bzw. Editoren. Je nach Layertyp sind nicht alle Einstellungen / Reiter vorhanden.

Layereditor

Die Layerattribut-Rechteverwaltung des generischen Layereditors

Mit dem generischen Layereditor (GLE) ist es möglich, die Daten von Postgis-Layern zu verändern. Damit nicht jeder beliebige Nutzer Daten ändert, gibt es ein Rechtesystem, welches jeder Stelle Privilegien zuordnet, die den Zugriff auf die Attribute eines Layers regeln. Die Layerattribut-Rechteverwaltung wird über die go-Variable Layerattribut-Rechteverwaltung aufgerufen. Zunächst wählt man den gewünschten Layer aus. Jeder Layer hat sog. Default-Rechte, die den "Standardzugriff" auf die Attribute definieren. Diese werden links angezeigt und daneben alle Rechte der Stellen, die diesem Layer zugeordet sind.

Layerattribut-Rechteverwaltung

  • Die Layerzugriffsrechte bestimmen, ob die Nutzer einer Stelle in einem Layer nur lesen bzw. editieren dürfen, ob sie zusätzlich neue Datensätze erzeugen dürfen oder darüber hinaus Datensätze außer erzeugen auch löschen dürfen.
  • Die Layerexportrechte bestimmen, welche Exportmöglichkeiten die Nutzer einer Stelle in einem Layer haben. Man kann den Export entweder ganz verbieten, den Export auf die Sachdaten beschränken oder den Export für Sach- und Geometriedaten erlauben.
  • Darunter werden alle Attribute des Layers untereinander aufgelistet. Diese Liste von Attributen ergibt sich aus dem Query-Statement des Layers. Jedem Attribut ist ein Privileg zugeordnet. Zur Auswahl stehen nicht sichtbar, nur exportieren, lesen und editieren. Standardmäßig sind alle Attribute eines Layers nur lesbar. In der jeweiligen Stelle, der der Layer zugeordnet ist, können entweder die Default-Rechte verwendet oder (i.d.R. bei der Stelle des "Datenherrens") individuelle Rechte vergeben werden.
  • Attribute, die einem Layer im Layereditor nachträglich hinzugefügt werden, erhalten in den Stellen zunächst das Recht "nicht sichtbar". Dieses Recht kann anschließend für jede Stelle angepasst oder von der Default-Rechteeinstellung übernommen werden.

Attributeditor - Formularelementtypen

Die Formularfelder des Generischen Layereditors können verschiedene Typen haben. Um einem Attribut manuell einen Formulartyp zuzuweisen, gibt es den Attributeditor. Dieser läßt sich entweder aus dem Layer-Definitions-Formular über den Button 'erweiterte Einstellungen' oder direkt über 'go=Attributeditor' aufrufen. Der Attributeditor zeigt alle Attribute des ausgewählten Layers an. Attributeditor

Folgende Formularelementtypen stehen zur Auswahl:

Eingabefeld

Im generischen Layereditor erscheint ein einzeiliges Eingabefeld.

Ist das Attribut in der Datenbank vom Typ "date", "timestamp" oder "time", wird neben dem Namen des Attributes in der Suche und der Sachdatenanzeige ein Kalendersymbol angezeigt. Ein Klick auf das Symbol öffnet einen Kalender zur Auswahl eines Datums bzw. einer Uhrzeit. Das Datum und/oder die Zeit kann jedoch auch manuell in das Textfeld eingetragen werden. Dabei ist jedoch die deutsche Formatvariante "Tag.Monat.Jahr Stunde:Minute:Sekunde" zu beachten. Ist es ein Attribut vom Typ "date" kann das Datum in verkürzter Schreibweise ohne .Jahr z.B. 2.9 oder mit einer zweistelligen Jahreszahl wie 2.9.20 eingegeben werden. Beide Varianten werden im Beispiel zu 2.9.2020 vervollständigt.

Text automatisch generieren
Es gibt die Möglichkeit den Wert des Textfelds automatisch generieren zu lassen. Im Optionenfeld kann man ein beliebiges SQL definieren, welches auch dynamisch sein kann, indem die Werte der anderen Attribute über $<attributename> einbezogen werden können. Hat ein Textfeld einen Eintrag im Optionenfeld, erscheint neben dem Attribut ein Button "automatisch generieren", der den neuen Wert entsprechend des SQL-Statements berechnet.
automatisch generieren.png
Beispiel: Man hat einen Layer Rechnungen und will für das Attribut Rechnungsnummer den Wert generieren lassen. Die Rechnungsnummer hat folgende Form: <Jahr>-<KundenNr>-<laufendeNummer>. Eine neue Rechnungsnummer soll sich also aus dem aktuellen Jahr, der Kundennummer des aktuellen Auftrags und der um 1 erhöhten laufenden Nummer der letzten Rechnungsnummer des Kunden ergeben.
Im Optionenfeld definiert man dazu folgendes SQL:
SELECT substr(EXTRACT(YEAR FROM CURRENT_DATE)::text, 3) ||'-'|| substr(r.rechnungsnummer, 4, 4) || lpad((substr(r.rechnungsnummer, 8, 3)::integer + 1)::text, 3, '0')
FROM buchung.rechnungen as r, buchung.auftraege as a 
WHERE substr(r.rechnungsnummer, 4, 3) = lpad(a.kunde_id::text, 3, '0') 
AND a.auftrag_id = $auftrag_id
ORDER BY rechnungsnummer DESC limit 1
Text mit einem Eingabewerkzeug generieren
Es gibt die Möglichkeit den Wert des Textfeldes mit Hilfe eines separaten Eingabewerkzeugs zu generieren. Mit Eingabewerkzeug ist hier eine eigenständige Webseite gemeint, welche die ID des Textfelds übergeben bekommt und am Ende den generierten Text in das Textfeld zurückschreibt. Wie der Text auf der Webseite generiert wird, ist völlig beliebig. Beispiele für Eingabewerkzeuge sind z.B. ein SQL-Query-Builder, ein RGB-Color-Chooser oder ein Date-Picker.
Die URL der Webseite, die verwendet werden soll, wird in das Optionenfeld eingetragen. Die URL kann auch dynamisch sein, indem die Werte der anderen Attribute über $<attributename> einbezogen werden können. Neben dem Textfeld erscheint dadurch ein Button "Eingabewerkzeug verwenden". Klickt man auf diesen, wird die Webseite über ein iframe aufgerufen und der Parameter "field_id" übergeben. Das ist die ID des Textfelds, welche von der Webseite am Ende verwendet werden kann, um den generierten Text in das Textfeld zu schreiben. Dies kann auf der Webseite z.B. folgendermaßen ablaufen:
Es gibt ein Hidden-Feld, welches die übergebene ID aufnimmt:
<input type="hidden" id="field_id" value="<? echo $_REQUEST['field_id']; ?>">
Es gibt eine Funktion setValue, welche am Ende, z.B. bei Klick auf einen "Übernehmen"-Button, den Text in das Textfeld schreibt:
function setValue(){
	field_id = document.getElementById('field_id').value;
	top.document.getElementById(field_id).value = 'neuer Wert';
	top.closeCustomSubform();
}
Der String 'neuer Wert' ist in der Funktion natürlich durch eine Variable zu ersetzen, welche den generierten Text enthält.
Zahl mit Tausendertrennzeichen
Dieser Typ kann für numerische Werte verwendet werden. Die Zahlen werden mit einem Punkt als Tausendertrenner und einem Komma als Dezimaltrenner angezeigt (1.234.567,89).
Textfeld
Im generischen Layereditor erscheint ein mehrzeiliges Eingabefeld. Genauso wie beim Typ "Text" besteht auch hier die Möglichkeit den Wert automatisch generieren zu lassen oder ein Eingabewerkzeug zu verwenden.
Auswahlfeld
Im generischen Layereditor erscheint ein Auswahlfeld. Um die Optionen der Auswahl zu generieren, gibt es mehrere Möglichkeiten:


  • In der Datenbank wird zu dem entsprechenden Attribut ein Check-Constraint definiert, das die möglichen Eingabewerte einschränkt, wie z.B.
CONSTRAINT art CHECK (art::text = 'gjb'::text OR art::text = 'ejb'::text OR art::text = 'tjb'::text)
In diesem Fall wird der Formularelementtyp dieses Attributes automatisch vom Typ Auswahlfeld und kann auch nicht verändert werden. Im GLE erscheint ein Auswahlfeld mit den durch das Constraint bzw. dem ENUM-Datentyp vorgegebenen Werten als Optionen. Bei Auswahl einer Option durch den Nutzer wird genau der Text der Auswahl in das entsprechende Attribut geschrieben.
Hinweis: Constraints, die auf Datenbankebene verwendet werden, um Eingaben mittels regulärer Ausdrücke zu überprüfen, kann kvwmap nicht verarbeiten. Solche Prüfungen sollten mittels Rule oder Trigger erfolgen.


  • Für das Attribut in der Datenbank wird einen ENUM-Datentyp definiert, der die möglichen Eingabewerte einschränkt, z.B. so:
CREATE TYPE bezirksarten AS ENUM ('gjb', 'ejb', 'tjb');
CREATE TABLE jagdbezirk (
   name text,
   art bezirksarten 
);
Auch in diesem Fall wird der Formularelementtyp dieses Attributes automatisch vom Typ Auswahlfeld und kann auch nicht verändert werden. Im GLE erscheint ein Auswahlfeld mit den durch das Constraint bzw. dem ENUM-Datentyp vorgegebenen Werten als Optionen. Bei Auswahl einer Option durch den Nutzer wird genau der Text der Auswahl in das entsprechende Attribut geschrieben.


  • Im Feld Optionen können die Auswahlmöglichkeiten festgelegt werden. Dabei wird dieselbe Syntax verwendet, wie bei Definition eines ENUM-Typs (die Werte dürfen allerdings kein Komma enthalten). Also
'Wert1','Wert2','Wert3'


  • Die Auswahlmöglichkeiten können aus einer Schlüsseltabelle ausgelesen werden. Im Optionen-Feld wird ein entsprechendes SQL-Statement angegeben. Es muss definiert werden, aus welchem Feld der Schlüsseltabelle der Text der Auswahlmöglichkeiten kommt und aus welchem Feld der Schlüsseltabelle der Wert kommt, der in die Datenbank geschrieben werden soll. Das Statement hat dabei folgende Form:
select <Ausgabespalte> as output, <Schlüsselspalte> as value from <Tabellenname>
Beispiel: Man hat eine Tabelle "projekte", mit den Spalten "projektnr" und "projektname". Im Auswahlfeld sollen nun die Projektnamen aufgelistet werden. Wählt man einen der Projektnamen aus, soll nach Absenden des Formulars die zugehörige Projektnummer übergeben werden. Dazu muß das SQL-Statement folgendermaßen aussehen:
select projektname as output, projektnr as value from projekte
Um doppelte Nennungen zu vermeiden, verwendet man noch ein "distinct":
 select distinct <Ausgabespalte> as output, <Schlüsselspalte> as value from <Tabellenname>
Eine alphabetische Sortierung der Optionen in der Auswahl (hier Projektnamen) erhält man durch ein angehängtes ORDER BY output
 select <Ausgabespalte> as output, <Schlüsselspalte> as value from <Tabellenname> ORDER BY output


  • Auch ohne Schlüsseltabelle können Anzeigetext und zu speichernder Wert definiert werden. Im Optionen-Feld wird ein entsprechendes SQL-Statement angegeben. Sollen z.B. als Werte 0 oder 1 gespeichert und im Auswahlfeld "nein" oder "ja" angezeigt werden, kann man das SQL-Statement z.B. so definieren:
select 'f' as value, 'nein' as output UNION select 't' as value, 'ja' as output
(Achtung: Hier wird nach value sortiert!)
  • Die Schreibweise mit UNION kann auch realisiert werden mit VALUE. Dies ist insbesondere nützlich wenn man viele Werte in der Auswahl haben möchte. Man spart sich jeweils das SELECT, AS value, AS output und UNION, siehe Beispiel:
SELECT
  column1 AS output, column2 AS value
FROM ( VALUES
  ('ja', 1),
  ('nein', 0),
  ('vielleicht', 2)
) AS options
Verknüpfungen von Layern
Wenn es einen Layer gibt, der den Daten im Auswahlfeld entspricht, hat man die Möglichkeit, beide Layer zu verknüpfen. Dazu werden im Optionenfeld nach dem SQL weitere Optionen angehängt. Diese werden mit einem ";" eingeleitet. Durch die Angabe von "layer_id=???" wird der zweite Layer definiert. Im Beispiel könnte das z.B. so aussehen:
select projektname as output, projektnr as value from projekte;layer_id=12
Im GLE erscheint dadurch, wenn das entsprechende Recht gesetzt ist, hinter dem Auswahlfeld ein Link "neu". Dieser öffnet ein neues Fenster und führt direkt zur Erfassung eines neuen Datensatzes des zweiten Layers (im Beispiel ein neues Projekt). Weiterhin hat man die Möglichkeit, die Erfassung des neuen Datensatzes auch ohne ein neues Fenster zu öffnen direkt im Hauptformular durchzuführen. Dazu fügt man im Optionenfeld die Option "embedded" hinzu (durch ein Leerzeichen getrennt). Im Beispiel also so:
select projektname as output, projektnr as value from projekte;layer_id=12 embedded
Dadurch erscheint mit dem Klick auf "neu" das Formular zur Erfassung des neuen Datensatzes direkt unter dem Auswahlfeld. Man kann nun den neuen Datensatz erzeugen und nach dem Klick auf Speichern schließt sich das eingebettete Formular und der neue Datensatz wird den Auswahlmöglichkeiten des Auswahlfeldes hinzugefügt und selektiert. Diese Variante der Layerverknüpfung entspricht einer n:1 Beziehung und ist eine Alternative zu "SubformFK".


Attributabhängige Auswahllisten
Die Optionen in einem Auswahlattribut können von der Auswahl in einem anderen Attribut abhängig sein. Der generische Layereditor ermöglicht die Definition von sogenannten attributabhängige Auswahllisten. Dafür muss immer ein Attribut definiert werden, dass die übergeordnete Auswahl ermöglicht sowie ein Attribut, dass die abhängige Auswahl liefert. Hier ein Beispiel: Es gibt ein Auswahlattribut flurnummer, welches die Fluren einer bestimmten Gemarkung anzeigen soll. Die Gemarkung wird zuvor in einem Auswahlattribut gemarkung ausgewählt.
Das übergeordnete Attribut gemarkung, welches die Gemarkungen auflistet, hat z.B. folgende SQL-Definition Optionen-Feld:
select gemarkung_schluessel as value, gemarkung_name as output from regis.gemarkungen <required by>flurnummer</required by>
Das abhängige Attribut flurnummer, das nur die Fluren der zuvor ausgewählten Gemarkung listet, hat z.B. folgende SQL-Definition Optionen-Feld:
select flur as value, flur as output from regis.fluren as f WHERE f.gemarkung_schluessel = <requires>gemarkung</requires>
Sortierungen mit "ORDER BY" am Ende sind möglich: Bei <requires>...</requires> dahinter, bei <required by>...</required by> davor.
Es ist darauf zu achten, dass das übergeordnete Attribut im Query-Statement des Layers VOR dem abhängigen Attribut aufgezählt wird (hier: gemarkung vor flurnummer). Also in der logischen Reihenfolge, in der man als Nutzer auch beide Auswahlfelder im GLE nacheinander auswählen würde. Die Anzahl der abhängigen Attribute ist jedoch nicht auf ein Attribut beschränkt, so dass sich auch mehrere abhängige Attribute, durch Komma getrennt, definieren lassen. Beispiel:
select gemarkung_schluessel as value, gemarkung_name as output from regis.gemarkungen <required by>flur,gemeinde</required by>
Auch die Anzahl der erforderlichen Attribute in der Definition eines abhängigen Attributes ist nicht auf ein Attribut beschränkt. Beispiel für ein Attribut flurstueckskennzeichen, welches von gemarkung und flurnummer abhängig sein soll:
select flurstuecksnummer as value, flurstuecksnummer as output from regis.flurstuecke where flur = <requires>flurnummer</requires> AND gemarkung_schluessel = <requires>gemarkung</requires>


Das abhängige Attribut muss nicht unbedingt ein Auswahlfeld sein. Es kann auch vom Typ Text sein. Dann wird es nur mit dem ersten Datensatz, die die SQL-Abfrage zurückliefert befüllt.


Auch das übergeordnete Attribut muss nicht unbedingt ein Auswahlfeld sein. Es kann ebenfalls vom Typ Text sein (das abhängige Attribut muss dann aber zwingend ein Auswahlfeld sein). Es ist nur darauf zu achten, dass im übergeordneten Attribut der richtige (richtig geschriebene) Wert steht.


Stellen- und Nutzerabhängige Auswahllisten
Es besteht auch die Möglichkeit, die Auswahlmöglichkeiten abhängig von der aktuellen Stelle oder dem aktuellen Nutzer zu machen. Dafür kann man im SQL die Schlüsselwörter $stelleid und $userid verwenden, welche dann durch die aktuelle Stellen-ID bzw. User-ID ersetzt werden. Dies macht insbesondere dann Sinn, wenn die Auswahlmöglichkeiten auch einem Layer entsprechen und verschiedene Stellen bzw. Nutzer in diesem Layer neue Auswahlmöglichkeiten erfassen können aber jede Stelle bzw. jeder Nutzer nur die eigenen Auswahlmöglichkeiten sehen soll. Wenn in diesem Layer ein Attribut vom Typ StelleID oder NutzerID existiert, wodurch jedesmal automatisch die Stellen-ID bzw. Nutzer-ID gespeichert wird, kann diese Spalte dann im Auswahlfeld-SQL zusammen mit dem Schlüsselwort $stelleid oder $userid verwendet werden, um die Auswahlmöglichkeiten auf die Stelle bzw. den Nutzer einzuschränken.
Auswahlfeld mit Bild

Mit diesem Formularelementtyp wird ein Auswahlfeld erzeugt, welches in jeder Auswahlmöglichkeit ein Bild und einen Ausgabetext anzeigt. Die Definition der Auswahlmöglichkeiten sieht so aus:

select <Ausgabespalte> as output, <Schlüsselspalte> as value, <Bildpfadspalte> as image from <Tabellenname>

Die <Bildpfadspalte> muss den Pfad zu einem Browser-kompatiblen Bildtyp (z.B. jpg, png, gif) enthalten.

Autovervollständigungsfeld

Ein Attribut dieses Formularelementtyps wird zunächst als normales Textfeld dargestellt. Bei jeder Tasteneingabe in diesem Feld wird jedoch eine Liste an möglichen Werten angezeigt, die die bisherige Eingabe vervollständigen. Eine dieser Möglichkeiten kann dann ausgewählt und der Wert übernommen werden. Es ist nicht möglich einen Wert in das Feld einzutragen, den es im Datenbestand nicht gibt. Der Wert des Feldes wird in diesem Fall immer wieder auf den Ausgangswert zurückgesetzt. Damit erfüllt dieser Formularelementtyp die gleiche Funktion wie das Auswahlfeld, indem beliebige Nutzereingaben unterbunden werden. Auch die Definition der Auswahlmöglichkeiten erfolgt nach dem gleichen Schema, wobei hier am Ende immer eine WHERE-Bedingung stehen muss:

select <Ausgabespalte> as output, <Schlüsselspalte> as value from <Tabellenname> where 1=1

Dieser Formularelementtyp eignet sich insbesondere für Attribute, bei denen die Liste an Auswahlmöglichkeiten sehr lang ist und ein normales Auswahlfeld ungeeignet wäre. Z.B. ist dieser Formularelementtyp bei SubFormFK-Layerverknüpfungen als Typ für das Verknüpfungsattribut zu empfehlen, falls dieses editiert werden soll.

weitere Optionen

Im Optionenfeld können nach der SQL-Abfrage der Auswahlmöglichkeiten weitere Optionen definiert werden. Diese werden mit einem ";" eingeleitet und untereinander mit einem Leerzeichen " " getrennt.

Verknüpfungen von Layern
Wenn es einen Layer gibt, der den Daten im Auswahlfeld entspricht, hat man, wie auch schon beim Auswahlfeld, die Möglichkeit, beide Layer zu verknüpfen. Durch die Angabe von "layer_id=???" in den weiteren Optionen wird der zweite Layer definiert.
Im GLE erscheint dadurch, wenn das entsprechende Recht gesetzt ist, hinter dem Autovervollständigungsfeld ein Link "neu". Dieser öffnet ein neues Fenster und führt direkt zur Erfassung eines neuen Datensatzes des zweiten Layers. Weiterhin hat man die Möglichkeit, die Erfassung des neuen Datensatzes auch ohne ein neues Fenster zu öffnen direkt im Hauptformular durchzuführen. Dazu fügt man im Optionenfeld in den weiteren Optionen die Option "embedded" hinzu. Dadurch erscheint mit dem Klick auf "neu" das Formular zur Erfassung des neuen Datensatzes direkt unter dem Autovervollständigungsfeld.
Suche im gesamten Text
Standardmäßig ist die Funktion des Autovervollständigungsfeldes so, dass bei jeder Tasteneingabe eine Liste mit Auswahlmöglichkeiten erscheint, die mit dem eingegebenen Text beginnen. Wenn man möchte, dass der eingegebene Text irgendwo im Text einer Auswahlmöglichkeit vorkommen kann, fügt man die Option "anywhere" hinzu.

Ein Beispiel für die Verwendung mehrerer zusätzlicher Optionen:

select <Ausgabespalte> as output, <Schlüsselspalte> as value from <Tabellenname> where 1=1;layer_id=42 embedded anywhere
zweispaltiges Autovervollständigungsfeld

Das zweispaltige Autovervollständigungsfeld wird genauso definiert wie das einfache. Die Ausgabespalte "output" muss hier allerdings immer aus zwei Begriffen bestehen, die durch ein Leerzeichen getrennt sind. Also z.B. "racomitrium aquaticum".

Bei der Eingabe in diesem Feld wird zunächst im ersten Begriff gesucht. Sobald man ein Leerzeichen eingibt, wird zum zweiten Begriff gesprungen und man kann nun durch Eingabe weiterer Zeichen in diesem Begriff suchen.

Gibt man bespielsweise folgende Zeichenfolge ein: "raco a", so würde "racomitrium aquaticum" gefunden werden.

Farbauswahl

Hier wird ein Auswahlfeld mit den Farben aus der Tabelle colors angezeigt. Gespeichert werden die RGB-Werte in der Form 123 231 123.

Radiobutton

Auch dieser Formularelementtyp stellt mehrere Auswahlmöglichkeiten zur Verfügung. Die Auswahlmöglichkeiten werden untereinander als Radiobuttons dargestellt. Die Definition der Auswahlmöglichkeiten erfolgt wie beim Auswahlfeld auch entweder über eine Aufzählung:

'Wert1','Wert2','Wert3'

oder über eine SQL-Abfrage:

select <Ausgabespalte> as output, <Schlüsselspalte> as value from <Tabellenname>

Weitere Optionen (werden mit einem ";" abgetrennt):

  • horizontal - bewirkt, dass die Radiobuttons nebeneinander angeordnet werden
  • horizontal=<Zahl> - bewirkt, dass die Radiobuttons nebeneinander angeordnet werden, wobei maximal <Zahl> Auswahlmöglichkeiten in einer Zeile stehen
SubformPK

Mit diesem Formularelementtyp lassen sich 2 Layer miteinander verknüpfen. Der Benutzer kann in kvwmap über einen Link, der in einem Layer erscheint, direkt in einen zweiten Layer "springen", der Daten enthält, die in Abhängigkeit zum ersten Layer stehen. Das "PK" steht für Primärschlüssel und damit für die Art der Verknüpfung.

Beispiel: Man hat einen ERSTEN Layer 'Verpachtungen' und einen ZWEITEN Layer 'verpachtete Flurstücke'. Beide Layer bilden eine 1:n Beziehung, d.h. eine Verpachtung kann mehrere Flurstücke haben, ein verpachtetes Flurstück ist aber immer genau einer Verpachtung zugeordnet. Der zweite Layer wird auch "Subform-Layer" genannt.


Ein eindeutiger Identifikator des ersten Layers, meistens gleichzeitig der Primärschlüssel auf Datenbankebene, wird als sog. "Verknüpfungsattribut" verwendet.

Beispiel: Der Primärschlüssel der Verpachtungen sei hier 'lfdnr'. Im zweiten Layer 'verpachtete Flurstücke' gibt es ebenfalls ein Attribut 'lfdnr', darüber sind beide Layer verknüpft. Weiß man die lfdnr einer Verpachtung, kann man auch alle zugehörigen Flurstücke abfragen.


Um 2 Layer über SubformPK auf diese Weise zu verknüpfen, müssen folgende Voraussetzungen erfüllt sein:

  • Der ERSTE Layer muss einen eindeutigen Identifikator besitzen,
  • Der ZWEITE Layer muss ein Attribut besitzen, welches genau so heißt wie der eindeutige Identifikator des ersten Layers,
  • Außerdem muss in der Query des ERSTEN Layers ein Attribut definiert werden, welches die Verlinkung zum ZWEITEN Layer herstellt. Der Wert dieses Attributs erscheint als Link und dient als "Vorschau" auf die entsprechenden Datensätze des ZWEITEN Layers.
Beispiel: Der zweiten Layer 'verpachtete Flurstücke' enthält ein Attribut "flurstueckskennzeichen", das als Vorschau herangezogen werden kann.
  • Für den ERSTEN Layer muss im Attributeditor beim Vorschau-Attribut als Typ 'SubformPK' ausgewählt werden. Im Feld Optionen wird die Layer-ID des ZWEITEN Layers eingetragen und, durch Komma getrennt, der eindeutige Identifikator (das Primärschlüsselattribut) des ERSTEN Layers.
Beispiel: "152,lfdnr"
Wenn beide Layer über mehrere Attribute verknüpft sind, muss man die entsprechenden Attribute, mit Kommas getrennt, hinter das Primärschlüsselattribut schreiben.
Beispiel: "152,lfdnr,gemkgschl,flur,flurstkennz"

Auch wenn die Verknüpfung nur über ein Attribut erfolgt, können trotzdem noch mehr Attribute des ersten Layers hinter das Primärschlüsselattribut geschrieben werden. Das macht dann Sinn, wenn im Subform-Layer (dem ZWEITEN Layer) ein neuer Datensatz angelegt werden soll. Dann stehen die Werte der übergebenen Attribute bereits zur Verfügung und können beim Anlegen des Datensatzes verwendet werden (z.B. bei der Definition von Dateinamen, siehe Abschnitt "dynamische Dateipfade" in Dokument). Natürlich müssen die entsprechenden Attribute auch in der Query des zweiten Layers enthalten sein.

Weitere Optionen (werden mit einem ";" abgetrennt):

  • no_new_window - bewirkt, dass der Link zum verknüpften Layer kein neues Fenster öffnet


Im Query-Statement des ersten Layers kann für das Vorschau-Attribut eine Aggregationsfunktion verwendet werden, um die verknüpften Datensätze zusammenzufassen. Also beispielsweise die Ausgabe der Anzahl der Flurstücke oder die Hintereinanderreihung der Flurstückskennzeichen. Das ist deswegen sinnvoll, damit der Nutzer in der Suche in diesem Verknüpfungsattribut auch suchen kann. Solange im abhängigen zweiten Layer noch kein Datensatz angelegt wurde, der mit einem Datensatz im übergeordneten ersten Layer verknüpft ist, ergibt sich eine Anzahl von 0 Treffern. Damit der "anzeigen"-Button in diesem Fall nicht erscheint, kann die Aggregationsfunktion mit einem CASE ergänzt werden, der für den Fall 0 Treffer einfach einen Leertext ausgibt (In SQL: 2 Hochkomma). Beispiel:

select array2string(array(
 select case when gml_id is not null then buchungsart else '' end from alkis.ax_buchungsstelle where ...
)) 


Bei einer 1:n Beziehung möchte man meistens, dass wenn man im ersten Layer einen Datensatz löscht, dann auch die nachgeordneten Datensätze des zweiten Layers (automatisch) gelöscht werden. Das geht am elegantesten, wenn man auf Datenbankebene einen CONSTRAINT in Form eines FOREIGN KEY in der Tabelle des zweiten Layers eingefügt (hierfür MUSS der eindeutige Identifikator wirklich auch ein Primärschlüssel sein):

ALTER TABLE <Name der Tabelle des zweiten Layers>
ADD CONSTRAINT "<irgendein Constraint-Name>" Foreign KEY (<Tabellen-Attributname des zweiten Layers, das der Verknüpfung dient>)
     REFERENCES <Name der Tabelle des ersten Layers> (<Name des Primärschlüsselattributs>) MATCH SIMPLE
     ON UPDATE NO ACTION ON DELETE CASCADE
Beispiel:
 ALTER TABLE flurstuecke_verpachtet
 ADD CONSTRAINT "fkfstverpachtet" Foreign KEY (lfdnr)
     REFERENCES verpachtungen (lfdnr) MATCH SIMPLE
     ON UPDATE NO ACTION ON DELETE CASCADE



SubformFK

Auch mit diesem Formularelementtyp lassen sich 2 Layer miteinander verknüpfen. Das "FK" steht für Foreign Key (Fremdschlüssel) und damit für die Art der Verknüpfung.

Beispiel: Der erste Layer sei wieder 'Verpachtungen'. Der zweite Layer ist diesmal ein Layer 'Personen'. Verknüpft ist jeweils die Person, die die Pacht bezahlt (Zahler).


In diesem Fall gibt es eine n:1 Beziehung, da eine Verpachtung nur einen Zahler haben kann aber ein Zahler mehrere Verpachtungen. Hier kann also nicht der Primärschlüssel der Verpachtung als Verknüpfungsattribut verwendet werden, da ein Zahler nicht eindeutig einer Verpachtung zugeordnet ist. Stattdessen muss im zweiten Layer ein eindeutiger Identifikator vorhanden sein, der für die Verknüpfung verwendet werden kann. Dieser muss als Attribut auch im ersten Layer vorhanden sein.

Beispiel: Im zweiten Layer existiert ein Primärschlüsselattribut 'personennr'. Im Layer 'Verpachtungen' gibt es auch ein entsprechendes Attribut 'personennr' und darüber sind beide Layer verknüpft. Weiß man die personennr einer Verpachtung kann man den entsprechenden Datensatz im Layer 'Personen' abfragen.


Um 2 Layer auf diese Weise zu verknüpfen, müssen folgende Voraussetzungen erfüllt sein:

  • Der zweite Layer muss einen eindeutigen Identifikator besitzen,
  • Der erste Layer muss ein entsprechendes Attribut besitzen, welches genauso heißen muss,
  • Außerdem muss es ein Attribut geben, welches im ersten Layer einen Bezug zum zweiten Layer herstellt. Dieses Attribut dient als eine Art Vorschau auf den entsprechenden Datensatz des zweiten Layers.
Beispiel: Im Layer 'Personen' gibt es ein Attribut 'Zahler'.

Im Query-Statement können für dieses Attribut auch einige Spalten des zweiten Layers zusammengefasst abgefragt werden, um zu einer sprechenden Vorschau-Anzeige zu kommen.


  • Für den ersten Layer muss im Attributeditor beim Vorschau-Attribut als Typ 'SubformFK' ausgewählt werden.
  • Im Feld Optionen wird die Layer-ID des zweiten Layers eingetragen und, durch Komma getrennt, der eindeutige Identifikator des ersten Layers.
Beispiel: "137,personennr"


Wenn beide Layer über mehrere Attribute verknüpft sind, muss man die entsprechenden Attribute, mit Kommas getrennt, hinter das Primärschlüsselattribut schreiben.

Beispiel: "481,bezirk,blatt,bvnr"

Außerdem ist es hier nicht notwendig, dass die Verknüpfungsattribute in beiden Layern gleich heißen müssen. Man kann hier auch erst den Namen des Attributs im untergeordneten Layer, dann einen Doppelpunkt und dann den Namen des Attributs im übergeordneten Layer angeben.

Beispiel: "481,bezirk:bezirk_id,blatt:blatt_id,bvnr"


Weitere Optionen (werden mit einem ";" abgetrennt):

  • no_new_window - bewirkt, dass der Link im gleichen Browser-Fenster bzw. Browser-Tab angezeigt wird.


In kvwmap muss ein Layer nicht notwendigerweise eine Geometrie haben. Wie im oben genannten Beispiel kann es z.B. einen Layer 'Personen' geben, dessen Datensätze dann nur über die Layer-Suche oder über Verknüpfungen mit anderen Layern erreichbar sind. Für einen solchen Layer setzt man minscale und maxscale einfach auf "-1", damit erscheinen diese dann auch nicht in der Legende.

Das folgende Bild zeigt, wie der GLE für die 3 verschiedenen Beispiel-Layer aussieht. Hinter den beiden Vorschauattributen 'Flurstücke' und 'Zahler' gibt es 2 Links 'bearbeiten' und 'neu', über die man die entsprechenden Datensätze der beiden verknüpften Layer aufrufen, bzw. neue erzeugen kann.

Subformpk.jpg



SubformEmbeddedPK

Dieser Formularelementtyp kann anstelle des SubfromPK-Typs verwendet werden, wenn die Datensätze des verknüpften Layers nicht in einer extra Sachdatenanzeige dargestellt werden sollen, sondern in Listenform eingebettet innerhalb des Hauptformulars.

Es wird eine Liste der verknüpften Datensätze angezeigt, wobei hier ausgewählte Attribute des zweiten Layers als Vorschau verwendet wird. Diese Vorschau ist gleichzeitig ein Link, der zur normalen Sachdatenanzeige des entsprechenden Datensatzes des zweiten Layers führt.

Über den Button "alle anzeigen" werden die Datensätze des verknüpften Layers entweder separat angezeigt oder, wenn die Option "embedded" gesetzt ist, im Listen-Editier-Modus, in dem sich alle untergeordneten Datensätze direkt bearbeiten lassen.

Die Einstellungen im Attribut-Editor sind die gleichen, wie bei SubformPK, nur dass hier noch der Name des Vorschau-Attributes im Optionen-Feld angehangen wird: <Layer-ID>,<primarykey>,<Name Vorschau-Attribut>

Beispiel: "152,vorhaben_id,vorgangsart"

Es können auch mehrere Attribute des zweiten Layers und auch zusätzlicher Text in der Vorschau verwendet werden. Wichtig ist nur, dass jedes Attribut mit einem Leerzeichen von anderen Attributen bzw. zusätzlichem Text abgetrennt ist.

Beispiel: "152,vorhaben_id,Vorgangsart: vorgangsart vorgangs_id"

Außerdem ist es hier nicht notwendig, dass die Verknüpfungsattribute in beiden Layern gleich heißen müssen. Man kann hier auch erst den Namen des Attributs im übergeordneten Layer, dann einen Doppelpunkt und dann den Namen des Attributs im untergeordneten Layer angeben.

Beispiel: "152,id:vorhaben_id,Vorgangsart: vorgangsart vorgangs_id"


Weitere Optionen (werden mit einem ";" eingeleitet und untereinander mit einem Leerzeichen getrennt):

  • no_new_window - bewirkt, dass der Link zum verknüpften Layer kein neues Fenster öffnet
  • embedded - bewirkt, dass die Formulare des verknüpften Layers direkt im Hauptformular erscheinen
  • list_edit - bewirkt, dass alle Datensätze des untergeordneten Layers nur im Listen-Editier-Modus angezeigt werden
  • reload - bewirkt, dass beim Ändern oder Neuanlegen im verknüpften Layer die gesamte Sachdatenanzeige neu geladen wird
  • show_count - bewirkt, dass die Anzahl der Datensätze des untergeordneten Layers angezeigt wird
Beispiel: "152,vorhaben_id,vorgangsart;embedded"


Die Datensätze des verknüpften Layers werden in Listenform angezeigt. Mit der Zusatzoption "embedded" wird das Formular des verknüpften Layers direkt im Hauptformular angezeigt.


Das Attribut, das der Verknüpfung dient (im obigen Beispiel "Vorgänge"), ist nicht Bestandteil des ersten Layers, sondern wird in der Query eingefügt. Das heißt, der (scheinbare) Inhalt des Attributs (die "Vorschau") erscheint weder im CSV-Export noch in der Fachdatensuche. Damit im CSV-Export trotzdem der angezeigte Vorschau-Inhalt als Feld-Inhalt erscheint bzw. damit man in der Fachdatensuche trotzdem auch in diesem Attribut nach Inhalten suchen kann, muss ein sog. "Array" für dieses Feld definiert werden. Im Query-Statement steht sowas wie

SELECT vorhaben_id, ..., '' as vorgaenge, ..., FROM bauvorhaben WHERE 1=1

Statt der beiden Hochkommas wird nun ein Array erzeugt und als Text ausgegeben:

SELECT vorhaben_id, ..., 
array2string(array(select vorgangsart from bauantraege as a where a.vorhaben_id=v.vorhaben_id)) as vorgaenge,
..., FROM bauvorhaben AS v WHERE 1=1

array2string ist eine Funktion, die PostgreSQL nicht kennt. Sie muss angelegt werden:

CREATE OR REPLACE FUNCTION array2string(text[])
 RETURNS text AS
$BODY$SELECT array_to_string($1,cast(', ' as text))$BODY$
 LANGUAGE sql IMMUTABLE STRICT
 COST 100;

Wenn man 2 Layer über SubformEmbeddedPK verknüpft hat und beide Layer eine Geometrie haben, dann wird beim Klick auf "neu" zum Erfassen eines neuen Datensatzes im untergeordneten Layer auf das Objekt des übergeordneten Datensatzes gezoomt.

Beispiel: Man hat einen Layer 'Strassen' und einen verknüpften Layer 'Verkehrsschilder'. Beide haben Geometrien. Jetzt sucht man über die Layersuche nach einer Strasse und bekommt die Sachdatenanzeige dieser Strasse. Wenn man jetzt zu dieser Strasse ein neues Verkehrsschild erfassen möchte und auf "neu" klickt, wird automatisch auf das Strassenobjekt gezoomt.

Ist das Vorschau-Attribut im verknüpften Layer vom Typ "Dokument", so werden die Vorschau-Bilder der jeweiligen Dokumente untereinander in Listenform angezeigt:

Dokumente.jpg



Zeitstempel
Dieser Attributtyp setzt immer zum Zeitpunkt der Speicherung automatisch einen Zeitstempel.
Im Optionenfeld kann optional "update", "insert" oder "export" eingetragen werden.
Wenn nichts eingetragen ist, erfolgt die Eintragung in jedem Fall.
Bei update erfolgt der automatische Eintrag nur bei Speicherung eines vorhandenen Datensatzes.
Bei insert wird der Zeitstempel nur bei der Erfassung eines Datensatzes gesetzt.
Bei export wird der Zeitstempel gesetzt wenn ein Datensatz exportiert wird.
Mit der Option "export" läßt sich automatisch kenntlich machen welche Datensätze wann zuletzt exportiert wurden und vor allem ob sie schon mal exportiert wurden. Möchte man also z.B. einem Dritten immer neue Datensätze zum Download anbieten, kann man eine Suchanfrage speichern oder im Menüpunkt hinterlegen, die immer nur die Datensätze anzeigt, deren Export-Zeitstempel leer sind. Der Download enthält dann immer nur die seit dem letzten Download neuen Datensätze.
Wenn der Typ in der Datenbank text, character, character varying oder eine Form von time ist, setzt sich der Zeitstempel aus Datum und Zeit zusammen. Ist der Typ date, wird nur das aktuelle Datum gespeichert.
Felder vom Typ Zeitstempel sind nicht editierbar, egal welche Rechte gesetzt sind.
Wenn der Datenbanktyp time oder date ist, wird in der Suche und der Sachdatenanzeige ein Kalendersymbol neben dem Attributnamen angezeigt.
Das Kalendersymbol ist jedoch beim Typ Zeitstempel nicht anklickbar, weil das Feld nicht editierbar ist.
Wer ein Zeit oder Datumsfeld editierbar haben möchte, muss andere editierbare Typen wie Text oder Auswahlfeld benutzen.
Dokument
Über den Formularelementtyp "Dokument" kann eine beliebige Datei auf den Server hochgeladen und im Datensatz gespeichert werden. Dabei gibt es 2 verschiedene Varianten, wie die Dateien auf dem Server verfügbar gemacht werden:
  1. Sicherer Dateizugriff: Die Dateien werden in einem nicht über das Web verfügbaren Ordner abgelegt. Die in der Sachdatenanzeige enthaltenen Links zu den Dateien werden unter Berücksichtigung der Rechteeinstellungen zur Laufzeit generiert und haben zufällige Anteile, so dass sie nicht erratbar sind. Außerdem funktionieren sie nur eine begrenzte Zeit. Dadurch ist sichergestellt, dass nur der Nutzer in kvwmap Zugriff auf die Dateien hat, der auch die Rechte dazu hat. In der entsprechenden Datenbanktabelle werden die absoluten Dateipfade der Dateien auf dem Server gespeichert.
  2. Öffentliche URLs: Die Dateien werden in einem über das Web verfügbaren Ordner abgelegt. Die in der Sachdatenanzeige enthaltenen Links zu den Dateien sind dauerhaft verfügbar (Permalink) und von jedermann auch ohne Zugang zu kvwmap aufrufbar. Außerdem sind hier anstatt der Dateipfade die kompletten URLs in der Datenbanktabelle gespeichert.
Welche der beiden Varianten verwendet wird, richtet sich nach dem Feld "Dokumente URL" in der Layerdefinition. Wenn hier eine URL auf einen Web-Ordner eingetragen wird, wird die 2. Variante verwendet, ansonsten die 1. Variante.
Speicherort auf dem Server
Der Ordner, in dem die Dateien abgelegt werden sollen, wird über das Feld "Dokumente Ordner" in der Layerdefinition definiert, siehe Admin-Dokumentation#Dokumente_Ordner. Wenn hier nichts angegeben wird, wird der Ordner 'CUSTOM_IMAGE_PATH' aus der config.php verwendet.
Die Felder "Dokumente Ordner" und "Dokumente URL" entsprechen einander, d.h. sie verweisen auf den selben Ordner.
Bei der ersten Variante werden die Dateien standardmäßig auf dem Server nicht mit ihren ursprünglichen Dateinamen abgelegt, sondern bekommen einen Namen, der sich aus dem Zeitstempel und einer Zufallszahl zusammensetzt. Bei der zweiten Variante setzt sich der Name standardmäßig aus dem ursprünglichen Dateinamen und einer Zufallszahl zusammen. Dadurch werden die Dateien nicht überschrieben, wenn gleichnamige Dateien hochgeladen werden. Bei der Anzeige bzw. dem Download der Dateien in kvwmap erscheint in der 1. Variante wieder der ursprüngliche Dateiname.
dynamische Dateipfade
Neben dieser standardmäßigen Variante der Dateiablage auf dem Server lassen sich die Dateinamen und auch die Verzeichnisstruktur unterhalb des Dokumentenordners bzw. der Dokumenten-URL für jedes Attribut vom Typ "Dokument" frei definieren. Dazu besteht die Möglichkeit im Attributeditor im Optionenfeld des Dokumenten-Attributs eine beliebige SQL-Abfrage zu definieren, die mit SELECT beginnt. Die Abfrage kann eine Ordnerstruktur und Variablen mit $ beinhalten sowie mit einem Dateinamen ohne Dateierweiterung oder mit '/' enden.
Beispiele für eine hochgeladene Datei mit dem Namen Draft.pdf bei gesetztem Dokument-Pfad /var/www/data/upload/, User-ID: 54, Stelle-ID: 2, Datensatz-ID: 123 und Dokumenttyp: 'Entwurf':
  • SELECT 'antragsdokumente/' => /var/www/data/upload/antragsdokumente/Draft.pdf
  • SELECT 'antragsdokumente/$USER_ID/' => /var/www/data/upload/antragsdokumente/54/Draft.pdf
  • SELECT 'antragsdokumente/$STELLE_ID/$datensatz_id' => /var/www/data/upload/antragsdokumente/2/123.pdf
  • SELECT 'antragsdokumente/$dokumententyp/' || now() => /var/www/data/upload/antragsdokumente/Entwurf/2024-09-03 14:23:15.pdf

Wenn der Pfad mit einem / endet, wird also der Name der Hochgeladenen Datei verwendet, ansonsten wird nur die Dateiendung angehängt.

Beispiel:
select 'container-' || '$container_id'

Feststehende Texte werden in Hochkommata notiert, Attribute des Layers mit $-Zeichen in Hochkommata: '$<attributname>'. Vorsicht bei Verwendung von Serial-Attributen: Das Select muss berücksichtigen, dass es den Datensatz bei einem INSERT noch gar nicht gibt und dass das Serial-Attribut in diesem Fall keinen Wert liefert. Abhilfe schafft die Eintragung des nextval-Strings aus der Layerdefinition (nextval('xyz_seq'::regclass)). Diese wird von kvwmap bei Attributen vom serial Typ mittlerweile automatisch in die Attribut-Definition eingetragen. Verwendet werden können nur die Realname der Attribute, nicht die Aliasnamen. Ist ein Attribut z.B. mit id AS konvertierung_id definiert setzt man in der Option für das document $id statt $konvertierung_id.

Handelt es sich um einen Subform-Layer, können aus dem übergeordneten Layer Attribute übergeben werden, die dann bei der Erzeugung des Dateinamens verwendet werden können:

select 'befliegung-' || '$befliegungsnummer' || '$dokumente_id'
Wenn man die Dateien in einem Unterordner "kvwmap-like" ablegen will, d.h. mit einem Zufallsnamen bestehend aus timestamp und sechstelliger Zufallszahl, dann kann die Option beispielsweise so formuliert sein:
select 'unterordner/' || to_char(current_timestamp, 'YYYY-MM-DD_HH_MM_SS') || '-' || ceil(random() * 1000000)
Es lassen sich sogar variabel weitere Unterordner in diesem Unterordner anlegen.
Beispiel: Man hat einen Dokumentenlayer mit einem fortlaufenden Attribut "doc_id". In diesem Layer gibt es sehr viele Dokumente und da diese nicht alle einzeln im Dokumentenordner des Layers liegen sollen, möchte man weitere Unterordner dazwischen einfügen. Es sollen maximal 100 Dateien in jedem Unterordner abgelegt werden. Dazu definiert man im Optionenfeld folgende SQL-Abfrage:
select doc_id/100 || '/' || doc_id from (select CASE WHEN '$doc_id' = '' THEN last_value + 1 ELSE ('$doc_id'||0)::integer / 10 END as doc_id from dokumente_doc_id_seq) as foo
Auf Basis der fortlaufenden Nummer "doc_id" wird ein Pfad generiert, welcher z.B. für die doc_id "3456" folgendermaßen aussieht: "34/3456". Die Datei bekommt also den Namen der doc_id "3456" und wird in einem Unterordner "34" abgelegt. Die Unterabfrage mit der CASE-Bedingung dient dazu, die beiden Fälle Änderung und Neuerfassung zu unterscheiden. Bei einer Änderung eines bestehenden Datensatzes soll die vorhandene doc_id genommen werden und bei Erfassung eines neuen Datensatzes die nächsthöhere Nummer aus der entsprechenden Sequenz.
Anzeige der Dateien
Je nach Dateityp erscheint in der Sachdatenanzeige ein passendes Vorschaubild mit einem Link auf das Original. Bei Video-Dateien (mp4) gibt es die Möglichkeit diese direkt in der Sachdatenanzeige abzuspielen. Das Video wird dabei gestreamt. Dafür muss das Video als URL direkt zur Verfügung stehen, im Layer muss also eine Dokument-URL angegeben werden.
Wenn in der Layer-Definition Template="generic_layer_editor_doc_raster.php" eingetragen wird, werden die Datensätze im GLE rasterförmig neben- und untereinander angezeigt.
Link
Verwendet den Wert des Attributes des Datensatzes als href für einen Link. Ist der Link vollständig, also beginnt mit http, wird der Link in einem neuen Tab geöffnet (target=_blank) ansonsten, bei einer relativen URL z.B. index.php?go=xy, nicht.
Bei Schreibrecht erscheint der Link über dem Eingabefeld. Bei nur Leserecht erscheint nur der Link.
Im Optionenfeld kann ein Linktext eingegeben werden, wird nichts eingegeben, wird der Teil der URL als Linktext angezeigt, der nach dem letzten Schrägstrich "/" folgt:
https://geoport.lk-vr.de/biotopboegen/0108-443B4002.PDF

Der Linktext kann so auch in der Query definiert werden. Damit der Teil, der nach dem letzten Schrägstrich "/" folgt, nicht Teil der aufzurufenden URL wird, muss ein "&" vor dem Schrägstrich stehen, Beispiel:

'index.php?go=neuer_Layer_Datensatz&selected_layer_id=50303913&/Neue Zuordnung erfassen' as link

Das kann insbesondere dann Sinn machen, wenn das Attribut ein Array ist und der Linktext für jedes Element im Array anders formuliert wird.

dynamischer Link
Der dynamische Link ermöglicht es, eine URL aufzurufen, die von bestimmten Attributen des Layers abhängig ist. D.h. die URL besteht zum einen aus festen Teilen, die immer gleich sind und aus variablen Teilen, welche sich aus den Attributwerten des jeweiligen Datensatzes ergeben. Der dynamische Link wird im Unterschied zum normalen Link-Typ nicht in einer PostGIS-Datenbanktabelle gespeichert, d.h. hier wird keine Tabellenspalte benötigt, stattdessen wird ein Pseudo-Attribut in das Query-Statement aufgenommen. Die dynamische URL zu diesem Attribut wird im Attributeditor im Optionenfeld definiert. Die variablen Teile der URL, die dann später durch die Attributwerte ersetzt werden, werden in der Form $<attributname> in die URL aufgenommen. Wichtig dabei ist, dass nur die Attributnamen als Variablen verwendet werden können, die das Layer-Recht lesen oder editieren haben und auch das Pseudo-Attribut auf lesen gesetzt sein muss.
Ein Beispiel: Man hat einen Layer Schulen. Dieser besitzt u.a. zwei Attribute lat und long, für die geografische Breite und Höhe. Es gibt außerdem eine externe Webanwendung, die eine Bushaltestellensuche über einen URL-Aufruf anbietet. Man kann nun der Sachdatenanzeige des Layers Schulen einen dynamischen Link hinzufügen, welcher alle Bushaltestellen in der Umgebung der Schule sucht. Dazu erweitert man das Query-Statement des Layers Schulen um ein Pseudo-Attribut bushaltestellen. Also z.b. so
SELECT *, '' as bushaltestellen FROM schulen WHERE 1=1
Im Attributeditor kann man nun für das Attribut bushaltestellen den Formularelementtyp "dynamischer Link" auswählen. Im Optionenfeld trägt man nun folgendes ein:
http://www.bushaltestellensuche.de?latitude=$lat&longitude=$long&umkreis=10
Dadurch erhält man in der Sachdatenanzeige für jede Schule einen Link, der die Bushaltestellen in der Umgebung sucht.
Weitere Optionen (werden mit einem ";" abgetrennt):
  • <Linktext> - 1. Option nach der URL kann ein Linktext angegeben werden, der dann anstatt der kompletten URL angezeigt wird
  • no_new_window - 2. Option bewirkt, dass der Link im selben Fenster geöffnet wird
  • root - 2. Option bewirkt, dass der Link im Hauptfenster geöffnet
  • embedded - 2. Option bewirkt, dass der Link nicht auf eine neue Seite verweist, sondern den Inhalt der aufgerufenen Seite direkt im Hauptformular anzeigt
  • all_not_null - 3. Option bewirkt bei URL's mit mehreren Variablen, dass der Link nur angezeigt wird, wenn alle in der URL angegebenen Attribut-Variablen einen Wert != '' haben.
Es ist nur möglich, den "<Linktext>" mit jeweils einer der beiden 2. Optionen "no_new_window" oder "embedded" zu kombinieren.
Wenn all_not_null nicht gesetzt ist, wird ein Link schon gezeichnet, wenn nur eine der in der URL verwendeten Attribut-Variable != '' ist.


Der dynamische Link ist auch eine Alternative der Verknüpfung von zwei Layern, insbesondere wenn es sich um eine 1:1-Verknüpfung handelt. Da auf denselben Server verwiesen wird, kann dieser Teil der URL entfallen, Beispiel:
index.php?go=Layer-Suche_Suchen&selected_layer_id=38&value_fundplatzid=$fundplatzid&operator_fundplatzid==;anzeigen;no_new_window


siehe auch backlink Parameter für Rücksprung zur vorherigen Seite.

MailTo
Dieser Formularelementtyp kann für Email-Adressen verwendet werden. Sie werden damit als mailto-Link dargestellt und mit dem Email-Programm geöffnet.
Nutzer
Hier kann nichts eingegeben werden, stattdessen wird der aktuelle Nutzer gespeichert. Im Optionenfeld kann optional "update" oder "insert" eingetragen werden. Bei "update" erfolgt der automatische Eintrag nur bei Speicherung eines vorhandenen Datensatzes. Bei "insert" nur bei der Erfassung eines Datensatzes. Wenn nichts eingetragen ist, erfolgt die Eintragug in beiden Fällen.
NutzerID
Hier kann nichts eingegeben werden, stattdessen wird die aktuelle Nutzer-ID gespeichert. Im Optionenfeld kann optional "update" oder "insert" eingetragen werden. Bei "update" erfolgt der automatische Eintrag nur bei Speicherung eines vorhandenen Datensatzes. Bei "insert" nur bei der Erfassung eines Datensatzes. Wenn nichts eingetragen ist, erfolgt die Eintragug in beiden Fällen.
Die Nutzer-ID kann in der Filterverwaltung verwendet werden, um Datensätze in einer Stelle nutzerbezogen zu filtern.
Stelle
Hier kann nichts eingegeben werden, stattdessen wird die aktuelle Stelle des Nutzers gespeichert. Im Optionenfeld kann optional "update" oder "insert" eingetragen werden. Bei "update" erfolgt der automatische Eintrag nur bei Speicherung eines vorhandenen Datensatzes. Bei "insert" nur bei der Erfassung eines Datensatzes. Wenn nichts eingetragen ist, erfolgt die Eintragug in beiden Fällen.
StelleID
Hier kann nichts eingegeben werden, stattdessen wird die aktuelle Stellen-ID des Nutzers gespeichert. Im Optionenfeld kann optional "update" oder "insert" eingetragen werden. Bei "update" erfolgt der automatische Eintrag nur bei Speicherung eines vorhandenen Datensatzes. Bei "insert" nur bei der Erfassung eines Datensatzes. Wenn nichts eingetragen ist, erfolgt die Eintragug in beiden Fällen.
Die Stellen-ID kann in der Filterverwaltung verwendet werden, um Datensätze in einer Stelle auf eine konkrete Stelle zu filtern.
Fläche
Hier kann nichts eingegeben werden, stattdessen wird die Fläche der Polygon-Geometrie gespeichert.
Länge
Hier kann nichts eingegeben werden, stattdessen wird die Länge der Linien-Geometrie gespeichert.
Winkel
Dieser Typ kann bei Punktlayern verwendet werden. Im Geometrieeditor erscheint dann neben dem Punktsymbol ein Richtungspfeil, welchen man über einen Slider drehen und den Winkel einstellen kann. Das Winkel-Attribut kann dann z.B. als Labelangleitem verwendet werden.
Checkbox
Erzeugt eine Checkbox, welche angehakt werden kann. Dieser Typ ist für Attribute vom Datentyp "boolean" gedacht. Auf Datenbankebene sollten diese Attribute als NOT NULL definiert werden, weil sonst in der Sachdatenanzeige nicht erkennbar ist, ob der Wert NULL oder FALSE ist.

Als Option kann ein JSON-Text in der Form

{"print": {"true":"ja", "false":"nein"}}

angegeben werden. Der Text "ja" und "nein" kann durch beliebigen Text, z.B. "x" oder " " ersetzt werden. Diese Texte erscheinen dann beim Druck in der Vorschau und den PDF-Dokumenten.

Style
Attribute dieses Typs tauchen in der Sachdatenanzeige nicht auf. Stattdessen wird der Wert eines solchen Attributs als CSS-Style für den gesamten Datensatz verwendet. Die Style-Definition kann ein Inline-Style sein, also z.B.
'background-color: lightgreen' as style

oder eine CSS-Klasse, die dann z.B. in der eigenen custom-CSS-Datei definiert ist:

'hintergrund_gruen' as style

Neben solchen festen Styles sind natürlich auch dynamische Styles möglich, die sich nach den Eigenschaften des Datensatzes richten. Z.B.:

CASE WHEN handlungsbedarf = 'nein' THEN 'background-color: lightgreen' ELSE 'background-color: orange' END as style

kontrolle ok.PNG kontrolle nicht ok.PNG

Auch bei Verwendung in einer SubFormEmbeddedPK-Verknüpfung wird der Style angewandt:

kontrollen.PNG

Wichtig: Obwohl dieses Attribut in der Sachdatenanzeige nicht erscheint, muss es einen Gruppennamen bekommen (wenn Gruppennamen verwendet werden)!


Editiersperre
Attribute dieses Types müssen true oder false zurückliefern und definieren ob der Datensatz editierbar ist oder nicht. Man muss also in der Layerdefinition bei Query nur ein Attribut definieren, welches die Bedingung für die Editiersperre definiert, also z.B.
status > 1 AS editiersperre.
Zusammen mit Ersetzungsparametern in der Layerdefinition (Query) kann man z.B. auch einstellen, dass man in einem Layer alle Datensätze lesen kann aber nur die eigenen editieren z.B.
user_id != $user_id AS editiersperre
Exif-Koordinate
Übernimmt die LatLong-Koordinaten beim Upload eines Fotos aus dem Exif-Header falls vorhanden. (Format: Latitude Longitude Dezimal). Im Optionen-Feld muss der Attributname des Dokument-Attributs angegeben werden, von dem der Exif-Header gelesen werden soll.
Exif-Richtung
Übernimmt die Richtung beim Upload eines Fotos aus dem Exif-Header falls vorhanden. (Format: Float Dezimal). Im Optionen-Feld muss der Attributname des Dokument-Attributs angegeben werden, von dem der Exif-Header gelesen werden soll.

Wenn man zusätzlich die Himmelsrichtung (N, NO, SSW etc.) haben will in Abhängigkeit der Richtung in Grad (im Beispiel in einem Attribut exif_richtung), kann man einen Trigger einrichten mit folgender Triggerfunktion.

CREATE TYPE meinschema.himmelsrichtung AS ENUM
   ('N', 'NNO', 'NO', 'ONO', 'O', 'OSO', 'SO', 'SSO', 'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW');
ALTER TABLE meinschema.meinetabelle ADD COLUMN himmelsrichtung type meinschema.himmelsrichtung;
CREATE FUNCTION meinschema.calc_himmelsrichtung()
  RETURNS trigger
  LANGUAGE 'plpgsql'
  COST 100
AS $BODY$
  DECLARE
  BEGIN
    IF NEW.exif_richtung IS NOT NULL THEN
      NEW.himmelsrichtung = ((array['N', 'NNO', 'NO', 'ONO', 'O', 'OSO', 'SO', 'SSO', 'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW', 'N'])[abs(round(NEW.exif_richtung / 22.5))+1])::meinschema.himmelsrichtung;
    END IF;
    RETURN NEW;
  END;
$BODY$;
COMMENT ON FUNCTION meinschema.calc_himmelsrichtung()
  IS 'Berechnet die Abkürzung für die Himmelsrichtung wenn exif_richtung gesetzt ist. Setzt Enum-Typ meinschema.himmelsrichtung voraus.';
CREATE TRIGGER tr_calc_himmelsrichtung
  BEFORE INSERT OR UPDATE 
  ON meinschema.meintetabelle
  FOR EACH ROW
  EXECUTE PROCEDURE meinschema.calc_himmelsrichtung();
Exif-Erstellungszeit
Übernimmt den Zeitstempel des Aufnahmezeitpunkts beim Upload eines Fotos aus dem Exif-Header falls vorhanden. (Format: YYYY-MM-DD hh:mm:ss). Im Optionen-Feld muss der Attributname des Dokument-Attributs angegeben werden, von dem der Exif-Header gelesen werden soll.

Attributeditor - Aliasname

Wenn ein Attribut in den Formularen und der Sachdatenanzeige nicht so angezeigt werden soll, wie er in der Layerdefinition benannt ist, kann ein Aliasname vergeben werden. Der Aliasname kann Lehr- und Sonderzeichen sowie Groß- und Kleinschreibung beinhalten.

Attributeditor - Gruppierung von Attributen

Damit die Attribute in der Sachdatenanzeige gruppiert angezeigt werden, kann man ihnen im Attributeditor Gruppennamen zuordnen. Alle Attribute mit dem selben Gruppennamen werden zu einer Gruppe zusammengefasst, wobei die Attribute schon in der richtigen Reihenfolge sein müssen.

Die Gruppen lassen sich im GLE auf- und zuklappen. Hängt man an den Gruppennamen noch ";collapsed" an, ist diese Gruppe schon zu Beginn zugeklappt.

Wenn Gruppen verwendet werden, muss jedes Attribut einer Gruppe zugeordnet ist. Beim Speichern füllt der Attributeditor daher leere Gruppenfelder automatisch mit der letzten Gruppe auf.

Die Gruppen können wiederum in mehrere Tabs aufgeteilt werden. Im Attributordner ordnet man den Attributen entsprechende Tab-Namen zu. Auch hier gilt: Wenn Tabs verwendet werden, muss jedes Attribut einer Gruppe und jede Gruppe einem Tab zugeordnet sein. Wenn der Gruppenname identisch ist mit dem Tabnamen, wird der Gruppenname nicht angezeigt. Wenn die Sachdaten eines Layers mit Tabs über eine URL aufgerufen werden, kann mit opentab=<Tabnummer> der geöffnete Tab angegeben werden. <Tabnummer> beginnt bei 0.

Attributeditor - Anordnung von Attributen

Die Attribute werden immer in der Reihenfolge angezeigt, wie sie über das Query-SQL abgefragt werden. In der zeilenbasierten Darstellungsvariante wird standardmäßig jedes Attribut in eine neue Zeile geschrieben. Links steht der Attributname bzw. Aliasname und rechts daneben das eigentliche Attribut.

Mit den Feldern "Anordnung" und "Beschriftung" hat man die Möglichkeit, das Layout der Attribute anders zu gestalten. Über das Feld "Anordnung" kann die Anordnung jedes Attributs festgelegt werden. Dieses Feld hat die beiden Auswahlmöglichkeiten "unter dem vorigen" und "neben dem vorigen", wobei der erste Wert der voreingestellte Standardfall ist. Das Attribut wird "unter dem vorigen", also in einer neuen Zeile nach dem vorigen dargestellt. Wählt man "neben dem vorigen", wird es in der selben Zeile dargestellt. Man kann so beliebig viele Attribute nebeneinander anordnen. Über das Feld "Beschriftung" lässt sich einstellen, wie die Beschriftung des Attributs, also der Attribut- bzw. Aliasname dargestellt werden soll. Hier gibt es die Auswahlmöglichkeiten "links neben dem Attribut", "über dem Attribut" und "ohne", wobei der erste Wert wieder der voreingestellte Standardfall ist. Der Attributname wird "links neben dem Attribut" in einer extra Spalte dargestellt. Wählt man "über dem Attribut" wird er in der Zeile über dem Attribut dargstellt. Bei Auswahl von "ohne" wird er gar nicht angezeigt. Mit den geeigneten Einstellungen lässt sich das Layout der Sachdatenanzeige optimieren, so dass der zur Verfügung stehende Platz bestmöglich ausgenutzt wird.

ausgr1.PNG ==> ausgr2.PNG

Attributeditor - Bei der Suche

Im Attributeditor kann für jedes einzelne Attribut eingestellt werden, wie es im Suchformular verwendet werden soll. Folgende Optionen gibt es:

  • nicht sichtbar - Das Attribut wird im Suchformular nicht angezeigt, damit kann man auch nicht danach suchen.
  • anzeigen (default) - Das Attribut wird im Suchformular angezeigt und damit kann man auch danach suchen.
  • Pfichtangabe - Das Attribut wird im Suchformular angezeigt und der Nutzer muss dafür einen Suchbegriff eingeben, sonst startet die Suche nicht.

Attributeditor - Für neuen Datensatz

Für die Eingabe von neuen Datensätzen können folgende 3 Optionen ausgewählt werden:

  • nicht sichtbar - Das Attribut wird im Formular nicht angezeigt. Damit kann man dazu bei der Ersterfassung auch nichts dazu eingeben. Diese Option ist sinnvoll für Attribute, die erst später automatisch befüllt werden, wenn der Datensatz gespeichert werde, z.B. durch Verknüpfungen zu anderen Datensätzen.
  • anzeigen - Die Attribute werden wie gewohnt im Formular angezeigt und es können damit Daten erfasst werden.
  • Werte nicht übernehmen - Bei dieser Option wird das Attribut zwar angezeigt, und man kann auch was eingeben, wenn jedoch ein neuer Datensatz auf der Basis eines vorhandenen angelegt wird, wird der Wert des Attributes nicht für die Erfassung des neuen Datensatzes übernommen. Das Feld bleibt leer, bzw. bekommt den Default-Wert des Attributes.

Hinweise!

  • Wenn mehrere Attribute nebeneinander angeordnet sind, wirkt sich die Option "nicht sichtbar" nur aus, wenn es für das erste (ganz links angeordnete) Attribut eingestellt ist. In einer horizontalen Reihe kann also kein einzelnes ausgeblendet werden, sondern immer nur alle oder keines.
  • Wenn ein ausgeblendetes Attribut allein in einer Gruppe ist, wird zwar das Attribut ausgeblendet, aber derzeit noch nicht die Kopfzeile der Gruppe.

Attributeditor - sichtbar

Hier kann die Sichtbarkeit der Attribute in der Sachdatenanzeige geregelt werden. Es gibt 3 Möglichkeiten:

nein: das Attribut wird nicht angezeigt
ja: das Attribut wird angezeigt
ja, wenn: das Attribut wird unter einer bestimmten Bedingung angezeigt (abhängig vom Wert eines anderen Attributs)

Wenn die letzte Variante ausgewählt ist, erscheinen 3 extra Felder um die Sichtbarkeitsbedingung zu definieren. Hier kann das Attribut, ein Operator und ein Wert definiert werden. Folgende Operatoren werden unterstützt: "=", "!=", ">", "<" und "IN". Der Wert muss ohne Hochkomma oder ähnliches angegeben werden. Beim Operator "IN" können mehrere Werte angegeben werden, die mit "|" voneinander getrennt sind. Wenn das Attribut, welches für den Vergleich verwendet werden soll vom Typ Boolean ist, trägt man t oder f ein ohne Hochkommas.

Die Einstellung der Sichtbarkeit betrifft jedoch nur die Darstellung in der Sachdatenanzeige. Das ist nützlich, wenn das Attribut nicht angezeigt werden soll, aber dennoch im Formular, z.B. für die Bildung eines anderen Attributes, den Export, dynamische URL's oder andere Abhängigkeiten benötigt wird.

Attributeditor - Anzeige im Rastertemplate

Wird diese Option für ein Attribut gesetzt, wird es im Rastertemplate auch im zugeklappten Zustand angezeigt. Die Auswahl erfolgt in der Checkbox in der Spalte mit dem Raster bzw. Fenster-Symbol.

Templates (eigene Snippets)

In den stellenbezogenen Eigenschaften des Layers (bzw. in den Defaults der Stellenzuweisung) kann ein PHP-Template angegeben werden, welches von kvwmap für die Sachdatenazeige eines Datensatzes verwendet werden soll. Das Template wird standardmäßig im Ordner custom/snippets/ gespeichert.

Im Template wird kein eigenes <form> Objekt angelegt. kvwmap setzt seine eigene <form> um alles. Die Speicherung funktioniert über den normalen Speichern-Button. Allerdings kann der Speichern-Button auch mit in das Template gezogen werden. Dafür muss der eigentliche Speichern-Button im CSS aus dem HTML-genommen werden:

#nds_submit {
  display: none;
}

Anschließend wird das <div> mit dem Speichern-Button im Template an geigneter Stelle eingebaut:

<div id="ticket-send">
   <input type="button" name="go_plus" id="sachdatenanzeige_save_button" value="Speichern" onclick="save_new_dataset();">
 </div>

Jedes Attribut im Template muss einen <name> Tag aufweisen. Der Name besteht aus 8 Elementen, die mit Semikolon getrennt werden:

  • (1) Die LayerID des zugehörigen Layers (das Attribut muss in der Query des Layers genannt sein)
  • (2) Der Spaltenname in der Datenbanktabelle
  • (3) Der Name der Datenbanktabelle
  • (4) Der Wert der ID-Spalte zum Datensatz
  • (5) Der Formularelementtyp des Attributs aus dem Attributeditor
  • (6) 0 oder 1. Wenn 0, dann ist es ein NOT NULL Attribut
  • (7) Der Datentyp des Feldes auf Datenbankebene
  • (8) 0 oder 1. Wenn 0, dann entspricht das Attribut im Template einem Feld in der Datenbanktabelle, ist also speicherbar

Beispiel:

<input id="vorname" name="50304601;vname;ansprechpartner;;Text;0;varchar;1" aria-required="true" maxlength="30"></input>

Die Formularelementtypen werden nicht nach ihrem "lesbaren" Namen angegeben, sondern nach dem Value aus den Optionen der Auswahlliste:

Text
Zahl
Textfeld
Auswahlfeld
Auswahlfeld_Bild
Autovervollständigungsfeld
Autovervollständigungsfeld_zweispaltig
Farbauswahl
Radiobutton
Checkbox
Time
User
UserID
StelleID
Link
mailto
Länge
Style
ExifRichtung
ExifErstellungszeit

Am Ende des Templates müssen alle "name" Tags noch einmal gemeinsam in eine Variable geschrieben werden, die beim Speichern des Datensatzes an kvwmap übergeben wird. Die Variable lautet $this->form_field_names und die einzelnen "Namen" werden mit Pipe getrennt.

Beispiel:

<?php
 $this->form_field_names = '50304601;anrede;ticket;;Auswahlfeld;0;varchar;1|50304601;vname;ticket;;Text;0;varchar;1|50304601;nname;ticket;;Textfeld;0;text;1|50304601;email;ticket;;mailto;0;varchar;1|50304601;erstellt_von;ticket;;UserID;0;int4;1';
?>

Wenn ein neuer Datensatz über das Template gespeichert wird, sollen der gespeicherte Datensatz anschließend im Template angezeigt werden. Dafür wird der qlayerset von kvwmap verwendet, wobei $this->qlayerset den ersten (und hier einzigen, deswegen "0") Layer bezeichnet und ['shape'] der Array für die Datensätze ist (hier auch "0", weil nur ein Datensatz zurück kommt):

Beispiel:

<?php
 $vorname = $this->qlayerset[0]['shape'][0]['vorname'];
 ...
?>

Beispiel für ein Attribut:

<input id="vorname" name="50304601;v_name;ansprechpartner;;Text;0;varchar;1" aria-required="true" maxlength="30" value="<?php echo $vorname; ?>"></input>

Validierung von Nutzereingaben

Attributbezogene Validierung

Der GLE unterstützt verschiedene Varianten, die Gültigkeit von Nutzereingaben zu überprüfen. Alle diese Varianten haben ihre Grundlage in der PostGIS-Datenbank, d.h. die Einschränkungen, die in der Datenbank für eine Tabelle gemacht werden, werden von kvwmap erkannt und in die Oberfläche des GLEs in Form von Validierungstests übertragen. Einige dieser Tests finden statt während der Nutzer eine Eingabe macht (z.B. Test auf Zahl) und einige werden erst durchgeführt, wenn der Nutzer versucht zu speichern (z.B. Test auf NOT NULL).

Folgende Attribut-Informationen werden beim Speichern der Layerdefinition erkannt:

  • NOT NULL: Im GLE erscheint hinter dem Attributnamen ein Sternchen (*), das dem Nutzer signalisiert, dass hier eine Eingabe oder Auswahl Pflicht ist. Bleibt ein Attribut leer, obwohl es "NOT NULL" ist, erscheint beim Speichern eine entsprechende Meldung.
  • DEFAULT: Im GLE erscheint beim Anlegen eines neuen Datensatzes im Wertfeld dieser Default. Bei Auswahlfeldern ist die entsprechende Option bereits ausgewählt etc.
  • CONSTRAINT: Ein Check-Constraint, welches die möglichen Werte einer Spalte auf eine bestimmte Menge einschränkt, wird im GLE automatisch in ein entsprechendes Auswahlfeld übertragen.
  • der Datentyp eines Attributs: Der GLE reagiert, wenn der Nutzer etwas einzutragen versucht, was dem Datentyp widerspricht. Z.B. werden Eingaben von Buchstaben in einem Attribut mit einem Zahlentyp (numeric oder integer) unterdrückt. Außerdem wird bei Zahlentypen die Angabe der (Nachkomma-)Stellen berücksichtigt und bei Fehleingaben erscheint eine entsprechende Meldung.


Validierung über Triggerfunktionen

Nicht mehr empfohlen: Validierung über Regeln (Rules). Insbesondere, wenn mehrere Regeln bei einer Tabelle ausgeführt werden sollen, sind die Limitierungen von Regeln klar erkennbar. Triggerfunktionen bieten die gleichen Möglichkeiten der Validierung bei deutlich mehr Übersichtlichkeit. Darüber hinaus bieten Triggerfunktionen die Möglichkeit, beliebigen SQL-Code auszuführen. Die nicht mehr empfohlene Methode der Validierung über Regeln wird hier anhand der Validierung von Nutzereingaben über mehrere Rules beschrieben.

Die attributbezogene Validierung bietet einen Set an Einschränkungen. Speziellere Anforderungen an die Validierung von Nutzereingaben können damit nicht abgedeckt werden. Triggerfunktionen erlauben es, jede beliebige Eingabe zu prüfen und mit einem Hinweis, einer Warnung oder einer Fehlermeldung zu beantworten. Z.B. kann es die Forderung geben, dass in einer Tabelle entweder Spalte A oder Spalte B mit einem Wert versehen sein muss (die "NOT NULL"-Einschränkung ist hier also nicht ausreichend). Oder eine bestimmte Eingabe (auch eine leere) soll mit einem ganz bestimmten Hinweis beantwortet werden. Oder neue bzw. geänderte flächenhafte Objekte dürfen sich geometrisch nicht mit vorhandenen Objekten aus derselben Tabelle überlappen.

Validierungen wie diese werden in der PostGIS-DB über die Definition einer Triggerfunktion im Schema und eines Triggers bei der entsprechenden Tabelle realisiert. Triggerfunktionen haben folgenden Aufbau:

CREATE OR REPLACE FUNCTION <schema>.<name der funktion>()
  RETURNS trigger
  LANGUAGE plpgsql
  AS $function$
  DECLARE

  BEGIN

    // Definition der Prüfung

    RETURN NEW;
  END;
 $function$
;

In der Triggerfunktion kann die Anwendungsoperation unterschieden werden, also INSERT oder UPDATE oder DELETE. Dafür wird je ein IF notiert in der Form

IF (TG_OP = 'INSERT') THEN
 ...
END IF;
IF (TG_OP = 'UPDATE') THEN
 ...
END IF;
IF (TG_OP = 'DELETE') THEN
 ...
END IF;

Wenn diese IFs weggelassen werden, wird die Prüfung bei allen im Trigger definierten Anwendungsoperationen ausgeführt. Diese IFs können auch schon weitere Bedingungen enthalten, es ist aber übersichtlicher, die Prüfung in ein eigenes IF zu schreiben. Das macht außerdem vor allem dann Sinn, wenn zu einem Anwendungsfall mehrere Prüfungen stattfinden sollen:

IF (TG_OP = 'INSERT') THEN
  IF <prüfung1> THEN
   ...
  END IF;
  IF <prüfung2> THEN
   ...
  END IF;
END IF;

Das Ergebnis der Prüfung mündet immer in einen Text, den der Nutzer zurückbekommt. Dieser Text muss ihm alle notwendigen Informationen an die Hand geben, damit er weiß, was passiert ist. Drei mögliche Zustände (am Beispiel des INSERTs):

  • Die Prüfung mündet in einen Hinweis (INSERT bzw. UPDATE bzw. DELETE soll trotzdem durchgeführt werden)
IF (TG_OP = 'INSERT') THEN
 IF <prüfung> THEN
   RAISE INFO 'Hier kommt der Hinweistext für den Nutzer';
 END IF;
END IF;
  • Die Prüfung mündet in eine Warnung (INSERT bzw. UPDATE bzw. DELETE soll trotzdem durchgeführt werden)
IF (TG_OP = 'INSERT') THEN
 IF <prüfung> THEN
   RAISE WARNING 'Hier kommt die Warnung für den Nutzer';
 END IF;
END IF;
  • Die Prüfung ergibt einen Fehler (INSERT bzw. UPDATE bzw. DELETE soll NICHT durchgeführt werden)
IF (TG_OP = 'INSERT') THEN
 IF <prüfung> THEN
   RAISE EXCEPTION 'Hier kommt die Fehlermeldung für den Nutzer';
 END IF;
END IF;



Der zugehörige Trigger wird bei der Tabelle notiert und feuert vor oder nach einem Event (INSERT, UPDATE oder DELETE). Trigger können auch bei Views eingesetzt werden und feuern dort INSTEAD OF. Im Trigger wird außerdem angegeben, welche Triggerfunktion ausgeführt werden soll. Beispiel:

CREATE TRIGGER check_entries 
BEFORE INSERT or UPDATE
ON <schema>.<tabelle> for each row execute procedure <schema>.<triggerfunktion>



Beispiele für Triggerfunktionen:

  • In einer Tabelle "denkmale" gibt es u.a. die Spalten "fundgruppe" und "fundart". Mindestens eine der beiden Spalten soll bei einer Neuerfassung ausgefüllt sein:
CREATE OR REPLACE FUNCTION denkmale_check_entries()
 RETURNS trigger
 LANGUAGE plpgsql
 AS $function$
 DECLARE

 BEGIN
  IF (TG_OP = 'INSERT') THEN
   IF (new.fundart IS NULL AND new.fundgruppe IS NULL) THEN
    RAISE EXCEPTION 'Die Fundart oder die Fundgruppe muss ausgefüllt sein!';
   END IF;
  END IF;
  RETURN NEW;
 END;
 $function$
;
  • In einer Tabelle "dokumente" wird ein Attribut "datei" gespeichert. Der Nutzer soll einen Hinweis bekommen, wenn Dateien mit gleichem Namen gespeichert werden:
CREATE OR REPLACE FUNCTION dokumente_check_entries()
 RETURNS trigger
 LANGUAGE plpgsql
 AS $function$
 DECLARE

 BEGIN
  IF (TG_OP = 'INSERT') THEN
   IF (substring(new.datei, position(new.datei, 'original_name=') + 14) IN ( SELECT substring(datei, position(datei, 'original_name=') + 14) FROM dokumente)) THEN
    RAISE INFO 'Eine weitere Datei mit diesem Namen existiert bereits!';
   END IF;
  END IF;
  RETURN NEW;
 END;
 $function$
;
  • In einer Tabelle mit Flächengeometrien "polygons" soll verhindern werden, dass dort Datensätze angelegt oder vorhandene Datensätze geändert werden, deren Geometrie sich mit der Geometrie bereits vorhandener Datensätze überlappt:
CREATE OR REPLACE FUNCTION geom_topo()
 RETURNS trigger
 LANGUAGE plpgsql
 AS $function$
 DECLARE
  b varchar;

 BEGIN

  IF (TG_OP = 'INSERT') then
   EXECUTE format(
   'SELECT true AS bool
    FROM %I.%I as z
    WHERE st_overlaps(st_buffer(%L, -0.0001), z.the_geom)
    LIMIT 1'
   , TG_TABLE_SCHEMA, TG_TABLE_NAME, new.the_geom) INTO b;
   IF (b = 't') THEN
    RAISE EXCEPTION 'Die Geometrie darf sich nicht mit einer bereits vorhandenen überlappen!';
   END IF;
  END IF;

  IF (TG_OP = 'UPDATE') THEN
   EXECUTE format(  
   'SELECT true AS bool
    FROM %I.%I as z
    WHERE st_overlaps(st_buffer(%L, -0.0001), z.the_geom) AND NOT z.the_geom = %L
    LIMIT 1'
   , TG_TABLE_SCHEMA, TG_TABLE_NAME, new.the_geom, old.the_geom) INTO b;
   IF (b = 't') THEN
    RAISE EXCEPTION 'Die Geometrie darf sich nicht mit einer bereits vorhandenen überlappen!';
   END IF;
  END IF;

  RETURN NEW;
 END;
$function$
;

Hinweise:

  • st_buffer erzeugt eine winzige Lücke, die es ermöglicht, dass direkt aneinander grenzende Flächen, die aus kvwmap kommen, von st_overlaps nicht als überlappend angesehen werden.
  • Schema- und Tabellenname werden über TG_TABLE_SCHEMA und TG_TABLE_NAME in die Funktion gegeben. Diese Funktion kann also von allen Tabellen eines Schemas benutzt werden und muss nicht für jede Tabelle neu geschrieben werden.



RAISE kann auch einen JSON-String enthalten, welcher das Attribut "msg" mit dem auszugebenden Text enthält. Dann wird nur dieser Text angezeigt.

 RAISE INFO '{"success" : true, "msg_type" : "notice", "msg" : "Meldung der Validierung"}';  

"success":true produziert den Text "Änderung erfolgreich" - unabhängig davon, ob der Datensatz gespeichert wird oder nicht!

"success":false produziert den Text "Kann Datensatz nicht speichern" - unabhängig davon, ob der Datensatz gespeichert wird oder nicht!

Achtung: Nur RAISE EXCEPTION bewirkt, dass die Verarbeitung des Datensatzes abgebrochen wird. Bei der Verwendung des JSON-Strings kann man also auch fehlerhafte Ausgaben produzieren.

RAISE gibt es auch noch als RAISE NOTICE.

 RAISE NOTICE '{"success" : false, "msg_type" : "warning", "msg" : "Meldung der Validierung"}';

Achtung: RAISE NOTICE sendet keine Mitteilung an den Client, solange client_min_messages nicht auf 'NOTICE' gesetzt wurde. Das passiert entweder durch ein vorangestelltes

 SET client_min_messages TO 'NOTICE';

oder durch dauerhafte Änderung in der postgresql.conf.

Achtung: RAISE NOTICE an sich verhindert das Verarbeiten des Datensatzes nicht. Dass Verarbeiten wird hier nur durch ein zusätzlich notiertes

 RETURN NULL;

unterbunden.

Bearbeitung von Geometrien - Geometrie-Editor

Um die Geometrie eines abgefragten Datensatzes zu bearbeiten, klickt man im generischen Layereditor in der Sachdatenanzeige auf den Link 'Geometrie bearbeiten'. Beim Neuanlegen eines Datensatzes ist der Geometrieeditor bereits integriert. Eine bereits vorhandene Geometrie erscheint blau hervorgehoben und kann bearbeitet werden. Nach Klick auf 'Speichern' wird die veränderte Geometrie in die Postgis-Tabelle eingetragen. Dabei wird nach dem Speichern wieder auf die gesamte Ausdehnung der Geometrie gezoomt. Dies kann gerade bei der Erfassung größerer Geometrien hinderlich sein, wenn man auf einen bestimmten Teil der Geometrie gezoomt hat und zwischendurch speichern möchte. Dafür gibt es den Button 'Zwischenspeichern'. Hier wird die Geometrie auch gespeichert, nur wird der Kartenausschnitt danach nicht verändert.

Je nach Geometrietyp des jeweiligen Layers bietet der Editor verschiedene Werkzeuge und Funktionen zum Bearbeiten an.

Um die Geometrie eines Polygon-Layers zu bearbeiten, gibt es folgende Werkzeuge:

Polyadd.jpg Polygon hinzufügen
Polyremove.jpg Polygon entfernen
Flurstadd.jpg Geometrie eines Layers selektieren und hinzufügen
Flurstremove.jpg Geometrie eines Layers selektieren und entfernen
Buffer.gif die aktuelle Geometrie um eine definierte Breite vergrößern oder verkleinern (negatives Vorzeichen)
buffer line.jpg gepufferte Linie hinzufügen
parallel polygon.jpg linksseitig gepufferte Linie hinzufügen
move geometry.jpg Geometrie verschieben
Vertexedit.jpg Eckpunkte bearbeiten
Coord input.gif Koordinate eingeben

Um die Geometrie eines Linien-Layers zu bearbeiten, gibt es folgende Werkzeuge:

Lineedit.gif Linien hinzufügen
Lineedit2.jpg Linien durch Zeichnen eines Polygons entfernen
Flurstadd.jpg Geometrie eines Layers selektieren und hinzufügen
Flurstremove.jpg Geometrie eines Layers selektieren und entfernen
split lines.jpg Linienzug aufsplitten
reverse.png Linienrichtung drehen
move geometry.jpg Geometrie verschieben
Vertexedit.jpg Eckpunkte bearbeiten
Coord input.gif Koordinate eingeben

Um die Geometrie eines Punkt-Layers zu bearbeiten, gibt es 2 Werkzeuge:

Pointedit.jpg Punkt setzen
Coord input.gif Koordinate eingeben

Die Darstellung der Geometrien erfolgt mit SVG und die geometrischen Operationen werden mit AJAX und Postgis realisiert.


Der Geometrie-Editor bei der Bearbeitung eines Polygonlayer-Datensatzes


In der Eckpunktbearbeitung ist es möglich, Punkte zu löschen (Doppelklick) oder Punkte an beliebiger Stelle in eine Kante (eines Linien- oder Polygonlayers) einzufügen. Bei Linienlayern können außerdem neue Punkte vor den Anfang bzw. hinter das Ende des Linienzuges gesetzt werden.


Zur Bearbeitung von Eckpunkten existiert weiterhin ein Punktfang. Wird dieser eingeschaltet (unter der Kartengrafik), erscheinen alle Eckpunkte der Geometrien aller aktuell aktiven PostGIS-Layer, die in dem aktuellen Kartenausschnitt zu sehen sind. Wenn man nun einen neuen Eckpunkt auf einen solchen Punkt setzt oder einen Punkt der gerade editierten Geometrie auf einen solchen Punkt zieht, wird dieser gefangen und die exakten Koordinaten übernommen.


Punktfang.png

Zur Unterstützung bei der Digitalisierung besteht die Möglichkeit zu zoomen ohne dass der Kartenausschnitt neu geladen wird. Dazu muss man die Strg-Taste gedrückt halten und kann über das Mausrad reinzoomen. Dadurch lassen sich z.B. nahe beieinander liegende Punkte leichter fangen. Lässt man die Strg-Taste los, wird der Zoom zurück gesetzt und die Darstellung springt auf die Ausgangslage zurück.


Im Geometrie-Editor gibt es eine Checkbox "weiterzeichnen". Damit kann rollenbezogen eingestellt werden, ob nach dem Navigieren wieder in den Zeichenmodus gewechselt wird oder nicht.

Layer-Suche

Neben der Abfragemöglichkeit über die Karte kann man auch über eine Suchmaske nach Postgis-Layern suchen und die Sachdaten im generischen Layereditor anzeigen und bearbeiten. Die go-Variable dazu heißt Layer-Suche. Hier stehen alle Layer zur Auswahl, die der aktuellen Stelle zugeordnet sind und die abfragbar sind. Nach Auswahl eines Layers kann man als Suchparameter die Layerattribute verwenden, für die man mindestens Leserecht hat. Es stehen folgende Suchoperatoren zur Verfügung:

= gleich
!= ungleich
< kleiner als
> größer als
ähnlich (SQL: LIKE) hier kann man "_" bzw. "%" als Platzhalter verwenden
nicht ähnlich (SQL: NOT LIKE) hier kann man "_" bzw. "%" als Platzhalter verwenden
ist leer (SQL: IS NULL)
ist nicht leer (SQL: IS NOT NULL)
befindet sich in (SQL: IN) hier können mehrere mögliche Werte durch ein "|" getrennt angegeben werden
zwischen (SQL: BETWEEN) hier kann ein Anfangs- und Endwert angeben werden

Das Ergebnis der Suche erscheint dann im generischen Layer-Editor bzw., falls dem Layer ein Template zugeordnet ist, das entsprechende Template.

Zurück zur vorherigen Seite

In der Sachdatenanzeige gibt es oben links einen Pfeil nach links, mit dem man normalerweise zurück zum Suchformular gelangt.

Sachdatenanzeige Kopf.png

Ist bei der Suchanfrage jedoch der Parameter backlink gesetzt, wird zu der Ressource gesprungen, die dort angegeben ist. Der Link in backlink muss jedoch URL-encoded sein. Zum encodieren kann man z.B. https://www.urlencoder.org/ verwenden. Beispiel:

 index.php?go=Layer-Suche_Suchen&selected_layer_id=743&value_rechnungsnummer=20-018-086&operator_rechnungsnummer==
   &backlink=index.php%3Fgo%3DLayer-Suche_Suchen%26selected_layer_id%3D774%26anzahl%3D500

Dieser Rücksprunglink zeigt zurück zur Sachdatenanzeige des Layers mit der ID 774.

Sachdaten-Druck

Die Sachdaten von PostGIS-Layern lassen sich neben der Anzeige im GLE auch als PDF ausgeben. Im Sachdatendruck-Layouteditor (go=sachdaten_druck_editor) lassen sich für jeden Layer verschiedene Layouts erstellen, die anschliessend den gewünschten Stellen zugewiesen werden können.

Datendrucklayouteditor.png

Links wird ein Vorschaubild des Drucklayouts angezeigt und rechts das Formular mit den Daten des Drucklayouts. Oben rechts befinden sich 3 Buttons zur schnellen Navigation im Formular (nach oben, zu den Freitexten, zu den Linien).

Das Layout wird über seinen Namen eindeutig definiert und gehört immer nur zu einem Layer. Die Druckdatei erhält beim Drucken den Namen der unter Dateiname angegeben ist. Die Ränder definieren den Bereich der für Fließtext genutzt wird. Man kann z.B. Kopf und Fußzeilen, die absolut positioniert sind auch in die Randbereiche schreiben.

Ist die Option "Leere Attributwerte nicht drucken" ausgewählt werden diese Attribute und ggf. für die Attribute angegebene Label nicht gedruckt. Nachfolgende Attribute mit relativer Positionierung dazu werden jedoch gezeichnet.

Ist die Option "Vorschaubilder verwenden statt Originale" ausgewählt werden für den Druck statt der originalen Bilder die Preview-Bilder verwendet falls sie vorhanden sind. Die Option wirkt sich auf alle Attribute mit Formularelementtype "Dokument" aus. Durch den Druck der Vorschaubilder kann die Größe der PDF-Dokumente erheblich reduziert werden. Die Option ist besonders zu empfehlen wenn der Druck von vielen Objekten gleichzeitig möglich ist oder viele Bilder zu einzelnen Features gehören und gedruckt werden können. Prüfen Sie auch ob die Größe der Vorschaubilder ausreichend ist für die Auflösung im PDF. Diese kann mit der Konstante Layout > PREVIEW_IMAGE_WIDTH auf der Admin-Seite eingestellt werden.

Das Prinzip der Layoutdefinition ist ähnlich dem der Druckrahmen für den PDF-Kartendruck. Jedes Attribut kann über einen x- und y-Wert auf der PDF-Seite positioniert und mit einer bestimmten Schriftgröße und -Art ausgegeben werden. In der Vorschau des Layouts im Layouteditor werden die Attributnamen verwendet, beim späteren Druck eines Datensatzes die Attributwerte. Auch hier können analog zum Kartendruck beliebig viele Freitexte und ein Hintergrundbild im Layout angeordnet werden. Zusätzlich ist es möglich, Linien zu "zeichnen".

Das Geometrieattribut kann dem Layout zugeordnet werden. An dieser Stelle erscheint dann ein quadratisches Kartenbild des entsprechenden Objekts in der angegebenen Breite. Wichtig: Der entsprechende Layer muss ein data-Statement besitzen!

In Freitexten können auch die Attributwerte verwendet werden. Dazu muss man einfach das Schlüsselwort $<attributname> in den Text einbauen, welches dann später durch den jeweiligen Attributwert ersetzt wird. Man kann alternativ auch die Schreibweise ${<attributname>} verwenden, um falsche Ersetzungen zu verhindern, die auftreten können, wenn der Name eines Attributs in einem anderen Attributnamen vorkommt.

Wenn man in einem Drucklayout Attribute ausgeben möchte, die Text über mehrere Zeilen enthalten und dieser Text unterschiedlich lang sein kann, ist die Positionierung der nachfolgenden Attribute und Freitexte schwierig. In diesem Fall kann man die y-Position der nachfolgenden Elemente relativ zu den vorhergehen Attributen angeben. Dazu wählt man für alle nachfolgenden Elemente im Auswahlfeld "unterhalb von" das Attribut aus, auf das sich die relative Position beziehen soll und gibt als y-Wert den Abstand zu diesem Attribut an.

Wenn ein Label angegeben ist, wird dieses vor den Wert des Attributes geschrieben. Der Wert beginnt dann vom Anfang des Labels aus gesehen im Abstand des Wertes der bei Abstand angegeben wurde. Wird '$alias' angegeben wird der Aliasname des Attributes als Label verwendet. Werden ein oder mehrere Leerzeichen eingegeben, wird kein Label ausgegeben aber trotzdem der Abstand zum Attributwert verwendet. Die Leerzeichen werden als nicht sichtbare Label gewertet. Ein Label kann fett ausgeben werden wenn es mit den Tags <b>eingeschlossen</b> ist.

Es gibt 3 verschiedene Layouttypen:

  • Typ 1: pro Datensatz eine Seite
  • Typ 2: Datensätze untereinander
  • Typ 3: eingebettet

Ein Layout vom Typ 1 erzeugt ein PDF, in dem jeder Datensatz eines zu druckenden Abfrageergebnisses einer neuen Seite im PDF entspricht.

Beim Layouttyp 2 werden die Datensätze untereinander im PDF angeordnet, so dass eine Listenform entsteht. Die Positionsangaben die man für ein solches Layout macht, gelten also für den ersten Datensatz, die folgenden Datensätze werden fortlaufend darunter angeordnet. Für Freitexte kann man bei diesem Layouttyp angeben, ob sie fixiert sein sollen, wie z.B. für Überschriften, oder auch mit jedem Datensatz untereinander angeordnet werden sollen, wie z.B. für Attributbeschriftungen.

Der Typ 3 entspricht von der Darstellung dem Typ 2, d.h. auch hier werden die Datensätze untereinander angeordnet. Allerdings wird dieser Layouttyp für eingebettete Drucklayouts verwendet.

Mit eingebetteten Layouts lassen sich die 1:n Beziehungen, die in der Sachdatenanzeige über verknüpfte Layer (SubFormPK, SubFormEmbeddedPK) abgebildet werden, auch in die Sachdaten-Drucklayouts integrieren. Das Prinzip ist, dass man für jeden der beiden Layer ein Layout definiert, wobei das für den abhängigen Layer vom Typ 3 "eingebettet" ist. Das eingebettete Layout enthält auch keinen Druckkopf oder ähnliches, sondern nur die gewünschten Attribute und Freitexte, die dann in Listenform dargestellt werden. Im Layout für den übergeordneten Layer kann man über das Pseudo-Attribut, welches vom Formularelementtyp "SubFormPK" bzw. "SubFormEmbeddedPK" ist, das andere Drucklayout einbetten. Hier erscheint eine Auswahlliste mit allen verfügbaren Layouts des verknüpften Layers, welche den Typ 3 "eingebettet" haben. Über die x-y-Werte lässt sich das gesamte eingebettete Layout positionieren.

Grunddaten.png + Kontrolldaten2.png = Kontrolldaten.png

Ist für einen Layer ein Sachdaten-Drucklayout vorhanden und der entsprechenden Stelle zugewiesen (siehe Video), so erscheint in der Sachdatenanzeige des GLE ein Link "ausgewählte Datensätze: drucken". Wenn es mehrere Layouts gibt, muss der Nutzer noch das gewünschte Layout auswählen, ansonsten erscheint beim Klick darauf eine Druckvorschau der ersten Seite des PDFs. Ein Klick auf "Drucken" erzeugt schliesslich das PDF.

Wurde dem Layer im Layereditor ein Default-Drucklayout zugeordnet wird dieses Layout in der Druckvorschau verwendet, im Beispiel 'Kartierobjekt Grünlandbogen'. Man kann dort aber auch noch andere auswählen falls es mehrere für einen Layer gibt.

sachdatendruckvorschau.png

Hat der Layer nur ein Drucklayout, wird dieses in der Vorschau verwendet und man kann kein anderes auswählen.

Die erzeugte Datei bekommt einen zufälligen Namen oder den, der im Feld Dateiname angegeben ist. Der Dateiname kann auch dynamisch sein, wenn dort ein Attributname angegeben wird in der Form ${attribut_name}. Wird das Drucklayout für einen Archivdruck verwendet, muss der Name für jeden Datensatz pro Druckpfad eindeutig sein.

Sachdatendruckvorschau stylen

Die Vorschau für den Sachdatendruck kann man in der custom CSS-Datei anpassen. So kann man z.B. die Überschrift ausblenden und in dem Falle, dass nur das Default-Drucklayout auswählbar sein soll das Select-Feld modifizieren, so dass es so aussieht als wäre es ein Titel. Die folgenden Styles ändern das Layout so, dass der Titel "Layout-Auswahl" verschwindet und statt dessen der Name des Layouts erscheint, der selektiert ist. In diesem Fall ist das das Default-Drucklayout "Kartierobjekt Grünland".

 #sachdatendruck_table_105 select[name=aktivesLayout] {
   pointer-events: none;
   -webkit-appearance: none;
   -moz-appearance: none;
   text-indent: 1px;
   text-overflow: ;
   border: none;
   background-color: transparent;
   font-size: 20;
   margin-left: -4px;
 }
 #sachdatendruck_title_105 {
   display: none;
 }

sachdatendruckvorschau custom.png

Sachdatendruck archivieren

Wird beim Sachdatendruch der Parameter archivieren=1 mit übergeben, wird das bei der Druckfunktion erzeugte PDF-Dokument nicht angezeigt bzw. zum Download angeboten sondern im Dokumentpfad des Layers gespeichert und die Datei im ersten gefundenen Attribut des Layers vom Formularelementtyp Dokument eingetragen.

Diese Funktion ermöglicht eine einfache Archivierung des aktuellen Standes eines Datensatzes in Form eines PDF-Dokumentes. Das PDF-Dokument wird erzeugt und ist anschließend als Vorschaubild im Dokumentattribut zu sehen. Zum Auslösen der Funktion bietet sich ein dynamische Link an. In diesem müssen die folgenden Parameter angegeben sein:

  • go=generischer_sachdaten_druck_Drucken
  • archivieren=1
  • chosen_layer_id - Die ID des Layers zum dem der Datensatz gehört
  • aktivesLayout - Die ID des Sachdatendrucklayoutes welches für den Druck verwendet werden soll. Das Layout muss bereits dem durch chosen_layer_id ausgewählten Layer zugeordnet sein. Das Layout muss so definiert sein, dass der Dateiname eindeutig ist, denn das Dokument wird mit dem Namen gespeichert den der Druck erzeugt. Am besten man gibt im Datendruck-Layouteditor im Feld Dateiname ein Attribut an in dem der für den Datensatz eindeutige Name steht ${dateiname}. Wird die Funktion für den gleichen Layer und Datensatz wiederholt ausgeführt, wird das vorhandene PDF-Dokument falls vorhanden überschrieben.
  • oid - Der Wert der ID-Spalte des Datensatzes der in PDF-ausgegeben und archiviert werden soll. Im dynamischen Link wird hier der Variablenname angegeben, der die ID-Spalte enthält. Der Layer muss also ein Attribut haben in dem die ID-Spalte steht damit man das dynamisch aufrufen kann.

Ein Link zum Aufruf sieht dann z.B. so aus:

kvwmap/index.php?go=generischer_sachdaten_druck_Drucken&aktivesLayout=31&chosen_layer_id=743&oid=222753&archivieren=1

Ein dynamischer Link:

kvwmap/index.php?go=generischer_sachdaten_druck_Drucken&aktivesLayout=31&chosen_layer_id=743&oid=$oid&archivieren=1;archivieren;no_new_window

Wenn das Attribut vom Typ Dokument ein Array ist, wird das erzeugte PDF als neues Array-Element angehängt ohne die bisherigen PDFs zu überschreiben. Dadurch entsteht eine Liste mit den historischen Ständen des Datensatzes.

dynamische Layerdefinitionen

kvwmap unterstützt auch die Definition von dynamischen Layern. Ein Layer ist z.B. dann dynamisch, wenn in seinem Data-SQL bestimmte Parameter verwendet werden, die verschiedene Werte annehmen können und so unterschiedliche SQL-Statements ergeben. Die Parameter können vom Administrator frei definiert werden. Die Nutzer können den aktuellen Wert jedes Parameters selbst auswählen.

Ein Beispiel: Man hat eine Gemeinde-Tabelle mit Bevölkerungs-Prognosezahlen. In der Tabelle ist die prognostizierte Bevölkerungszahl für die nächsten 20 Jahre enthalten. Jedes Jahr entspricht einer eigenen Spalte (bev_2016 - bev_2036).

Jetzt möchte man die Bevölkerungszahlen für jede Gemeinde und jedes Jahr in der Karte farblich klassifiziert darstellen. Man kann nun entweder 20 verschiedene Layer anlegen, oder einen dynamischen Layer mit variablem Data-SQL. Das Data-SQL könnte z.B. so aussehen:

the_geom from (select the_geom, name, id, bev_$jahr as bev from gemeinden) as foo using unique id using srid=25833

Hier wurde der Parameter $jahr verwendet. In diesem Beispiel wurde er so definiert, dass er die Werte 2016 - 2036 annehmen kann. Je nachdem, welchen Wert ein Nutzer für diesen Parameter auswählt, zeigt der Layer die Bevölkerungszahlen des entsprechenden Jahres an.

Definition der Parameter

Die Layer-Parameter können definiert werden, indem man einen Menüpunkt mit dem Link "index.php?go=Layer_Parameter" erstellt und aufruft.

Layer Parameter.png

Es muss ein Name, ein Aliasname, ein Standardwert und eine SQL-Abfrage für die Auswahlmöglichkeiten eingegeben werden. Die SQL-Abfrage für die Auswahlmöglichkeiten kann genauso aufgebaut sein, wie bei der Definition eines Auswahlfeldes im Attributeditor. Sie muss eine Spalte "value" für den Wert und eine Spalte "output" für den angezeigten Text liefern. Für das obige Beispiel könnte die SQL-Abfrage z.B. so aussehen:

SELECT jahr AS value, jahr AS output FROM generate_series(2016,2036) AS jahr
Verwendung der Parameter in der Layer-Definition

Die Parameter können bei der Layer-Definition in der Form "$<name>" in folgenden Feldern verwendet werden:

  • Layername
  • Aliasname
  • Connection
  • Schema
  • Query
  • Data
  • Haupttabelle
  • Classitem
  • Tileindex
  • Klassifizierung
  • Processing
  • Attributeditor->Optionen

Wenn man im Feld Klassifizierung einen dynamischen Layer-Parameter verwendet, kann innerhalb des Layers zwischen verschiedenen Klassifizierungen gewählt werden.

Auswahl der Parameter-Werte

Wenn die aktuelle Stelle Layer enthält, die dynamische Parameter verwenden, erscheint rechts oben im Header ein Optionen-Button. Ein Klick darauf öffnet ein Formular, in dem alle in der Stelle verwendeten Parameter aufgeführt sind. Hier können die Werte ausgewählt und gespeichert werden. Wenn eine eigene Header-Datei verwendet wird, kann das Parameter-Formular über die Zeile

<? include(SNIPPETS.'params.php'); ?>

in den eigenen Header an geeigneter Stelle integriert werden.

Eine andere Variante, die Parameter zu setzen, besteht beim Aufruf der Optionen ("go=Stelle_waehlen"). Wenn man hier den zusätzlichen URL-Parameter "&show_layer_parameter=1" angibt, wird ein Formular zum Setzen der Layer-Parameter angezeigt.

Wenn ein Parameter nur in einem Layer verwendet wird, erscheint beim Öffnen der Layer-Optionen in der Legende ein entsprechendes Auswahlfeld um den Parameterwert zu setzen. Wenn sich der Parameterwert auf die Kartendarstellung des Layers auswirkt, kann man mit der Maus oder den Pfeiltasten der Tastatur durch die Auswahlmöglichkeiten gehen und das Kartenbild ändert sich sofort für diesen Layer entsprechend des Parameterwertes.

vordefinierte Parameter

Neben den o.g. selbst definierten Parametern, gibt es in kvwmap auch vordefinierte Parameter, die in den Layer-Definitionen verwendet werden können.

  • $LANGUAGE: Dieser Parameter enthält die aktuell ausgewählte Sprache (german, english, ...)
  • $HIST_TIMESTAMP: Dieser Parameter enthält den in den Optionen auswählbaren Zeitpunkt für historische Daten. Dieser Zeitpunkt kann für für eine zeitliche Navigation in Daten mit Vollhistorie verwendet werden (wie z.B. bei den ALKIS-Daten).
  • $CURRENT_DATE: Das aktuelle Datum.
  • $CURRENT_TIMESTAMP: Der aktuelle Zeitpunkt.
  • $USER_ID: Die ID des aktuell angemeldeten Nutzers
  • $STELLE_ID: Die ID der Stelle in der der Nutzer aktuell angemeldet ist.
  • $SCALE: Der aktuelle Maßstab (bzw. der Nenner des Maßstabbruchs) Dieser Parameter kann im Feld "Data" verwendet werden um z.B. eine maßstabsabhängige Größenangabe für Styles zu realisieren.

Will man einen Datenbestand mit Historie führen, wird man ein Lebenszeitintervall in das Datenschema einbauen, beispielsweise lebenszeit_beginnt und lebenszeit_endet (beides date-Typ). Im Attribut-Editor müssen die beiden Attribute entsprechend gefüttert werden. Dann kann die Query des Layers so aussehen:

 SELECT id, ... , lebenszeit_beginnt, lebenszeit_ende
 FROM <tabelle>
 WHERE tsrange(lebenszeit_beginnt, lebenszeit_ende) @> COALESCE(NULLIF('$hist_timestamp', '')::timestamp, localtimestamp)

Layerduplikate

Layerduplikate sind Layer mit gleichartiger Layerdefinition. Über die Funktion zum duplizieren von Layereinstellungen kann man die Verwaltung der Layer erleichtern (Duplikate Icon rechts in der Zeile der Layer ID des Formulars des Layereditor.

DuplicateLayer0.png

Layer dessen Einstellungen immer von einem anderen übernommen (dupliziert) werden sollen, bekommen zwei zusätzliche Einstellungen

  • eine Zuordnung zu dem Layer, von dem die Einstellungen übernommen werden sollen $duplicate_from_layer_id
  • ein Unterscheidungskriterium in Form von Text $duplicate_criterion

Der Layer von dem die Einstellungen übernommen werden sollen Originallayer, muss nur selbst ein Unterscheidungskritierum haben durch das sich dieser von den anderen unterscheidet. Die Variable $duplicate_criterion kann dann an beliebiger Stelle im Query- und Data-Statement gesetzt werden welches zur Unterscheidung führt.

DuplicateLayer1.png

Beim Speichern eines Originallayers wird folgendes übernommen:

  • alle Einstellungen des Layers außer:
    • Layer_ID, duplicate_from_layer_id, duplicate_criterion, Gruppe, alias,
    • Name und alle anderssprachigen Namen
    • alle Einstellungen für die Default-Werte der Stellenzuweisung (template, queryable, transparency, drawingorder, legendorder, minscale, maxscale, symbolscale, offsite, requires, postlabelcache)
  • alle Attributeinstellungen
  • alle Rechteinstellungen

Nicht übernommen werden:

  • die Klassen und Styleeinstellungen
  • die Zuordnung der Layer zu den Stellen

DuplicateLayer4.png

Beispiel:

Es gibt 4 Layer mit folgenden Query-Statements

  • SELECT id, kampagne, gueltig FROM biotope WHERE true (alle Biotope) layer_id = 1
  • SELECT id, kampagne, gueltig FROM biotope WHERE kampagne = 1 (Biotope der Kampagne 1) layer_id = 2
  • SELECT id, kampagne, gueltig FROM biotope WHERE kampagne = 2 (Biotope der Kampagne 2) layer_id = 3
  • SELECT id, kampagne, gueltig FROM biotope WHERE gueltig = 1 (alle aktuell gültigen Biotope) layer_id = 4

Alle haben abgesehen von der WHERE-Klausel die gleichen Angaben, sowohl im Layer-, Attriubt- und Rechteformular. Will man jetzt ein weiteres Attribut hinzufügen, z.B. created_at oder eine Fläche, müsste man bei allen das Query-Statement ändern speichern sowie die Attribute und Rechte einstellen. Besser wäre es, wenn man das nur bei dem ersten macht und die Einstellungen sich automatisch auf die anderen übertragen. Mit der Funktion Duplikate Layers wird das wie folgt eingestellt:

  • Layer 1 ist der Originallayer der immer geändert werden soll. Der wird wie folgt geändert
    • $duplicate_from_layer_id = NULL
    • $duplicate_criterion = 'true'
    • SELECT id, kampagne, gueltig FROM biotope WHERE $duplicate_criterion
  • Layer 2 wird wie folgt geändert
    • $duplicate_from_layer_id = 1
    • $duplicate_criterion = 'kampagne = 1'
    • SELECT id, kampagne, gueltig FROM biotope WHERE $duplicate_criterion
  • Layer 3 wird wie folgt geändert
    • $duplicate_from_layer_id =1
    • $duplicate_criterion = 'kampagne = 2'
    • SELECT id, kampagne, gueltig FROM biotope WHERE $duplicate_criterion
  • Layer 3 wird wie folgt geändert
    • $duplicate_from_layer_id = 1
    • $duplicate_criterion = 'gueltig = 1'
    • SELECT id, kampagne, gueltig FROM biotope WHERE $duplicate_criterion

Wir sehen, das Query-Statement ist jetzt bei allen gleich. Das soll auch so sein, weil durch das duplizieren wird ja pfad und Data auf die anderen Layer übertragen. Speichert man Änderungen z.B. am Layer 2, der von Layer 1 dupliziert werden soll, gelten diese nur für diesen Layer 2, werden aber beim nächsten mal, wenn man Layer 1 wieder speichert überschrieben. Wenn man unterschiedliche Klassen hat, muss man dafür sorgen, dass der Originallayer die in der Klassendefinition benötigten Variablen im Data-Statement hat.

DuplikateLayer3.png

Ein weiteres Beispiel wird im Bildschirmvideo beschrieben.

Verhalten von Datenbanktriggern

DELETE Trigger

Nach dem fehlerfreien Löschen von Datensätzen im GLE, fragt kvwmap die Anzahl betroffener Zeilen ab. Ist der zurückgegebene Wert 0 wird davon ausgegangen, dass kein Datensatz gelöscht wurde und eine Fehlermeldung ausgegeben. Wurde ein DELETE-Trigger auf der Tabelle mit den zu löschenden Datensätze angelegt, kann es passieren, dass dieser Trigger NULL zurückliefert. Das kann z.B. der Fall sein, wenn man statt einem DELETE ein UPDATE machen will um Daten zu historisieren. Mit dem Rückgabewert NULL bricht man die Operation DELETE ab, so dass z.B. nur der BEFORE Trigger ausgeführt wird aber nicht die eigentliche Löschanweisung. Wird NULL von einem Trigger zurückgegeben ist die Anzahl der betroffenen Zeilen 0.

Um kvwmap trotzdem zu signalisieren, dass die Löschung, bzw. die Stellvertreter-Anweisung, z.B. eine Historisierung, erfolgreich ausgeführt wurde, muss man in der letzten Zeile des letzten ausgeführten Triggers vor dem RETURN NULL; eine Notiz mit einem JSON mit "success: true" einfügen.

 ...
 Trigger-Code
 ...
 RAISE NOTICE '{"success" : true}';
 RETURN NULL;
END;

Klasseneditor

Mit dem Klasseneditor lassen sich die Klassen von Layern editieren.

Der Editor (go=Klasseneditor) wird entweder aus dem Kontextmenü des Layers oder dem Formular zum Ändern von Layereigenschaften aufgerufen. Im Attributeditor können pro Klasse folgende Einstellungen vorgenommen werden:

  • ID: Die ID der Klasse wird beim Hinzufügen einer neuen Klasse über den Plus-Button automatisch erzeugt. Vor dem Zuordnen von Styles und Labels kann die ID noch geändert werden. Anschließend sollte sie nicht mehr geändert werden weil daran andere Objekte hängen können.
  • Klasse: Der Name der Klasse. Wenn nichts angegeben wird, erscheint die Klasse nicht in der Legende. Werden ein oder mehrere Leerzeichen angegeben, erscheint die Klasse mit dem Legendensymbol aber ohne Bezeichnung. Sind für die Anwendung im Konfigurationsparameter "Administration > supportedLanguages" mehr als nur eine Sprache ausgewählt, kann man auch für die anderen Sprachen die Bezeichnungen der Klassen angeben. Für jede unterstützte Sprache gibt es dann ein Namensfeld.
  • Expression: Hier wird die Definition angegeben, die entscheidet welche Datensätze zu der Klasse gehören. Siehe dazu Abschnitt Expressions und die MapServer Dokumentation.
  • Text: Hier kann man entweder einen Statischen Text eingeben, dieser wird verwendet um als Beschriftung für alle Datensätze in der Karte zu dienen, oder die Bezeichnung eines Attributes in eckigen Klammern, siehe auch Class-Definition der MapServer Doku. Wird nichts angegeben, wird das Attribut aus dem Layerattribut Labelitem, gesetzt im LayerEditor-Allgemeine Angaben, für die Beschriftung verwendet.
  • Klassifizierung: Über die Klassifizierung kann ein Gruppe von Klassen definiert werden. Alle Klassen mit der gleichen Bezeichnung der Klassifizierung gehören in eine Gruppe. Wird im Layerattribut, eingestellt im "Layereditor > allgemeine Einstellungen", ein Name für die Klassifizierung angegeben, werden nur die Klassen angezeigt, die diesen Namen in Klassifizierung stehen haben. Da das Attribut Klassifizierung variable sein kann, also ein LayerParameter, könnte man über das Umschalten eines Layerparameters die Klassifizierung eines Layers ändern. Wenn eine Klassifizierung angegeben wurde müssen alle einen Wert in Klassifizierung haben. Klassen ohne Namen werden sonst immer angezeigt.
  • Legendengrafik: Eine hier angegebene Datei wird, wenn angegeben, statt des von MapServer erzeugten Legendenbild verwendet. Die Datei muss im custom Ordner von graphics abgelegt sein. Zusätzlich kann man die Höhe und Breite der Legendengrafik angeben.
  • Reihenfolge: Die Reihenfolge in der Karte definiert wie die Klassen in der Karte gezeichnet werden. Das wirkt sich nur aus, wenn sich darzustellende Objekte auch überlagern. Die andere Angabe definiert die Reihenfolge der Darstellung der Klassen in der Legende.

Über den Mülleinmer-Button lassen sich Klassen löschen und mit dem Auto-Button automatische Klassifizierungen erzeugen. Siehe dazu auch automatische Klassifizierung.

Alle Änderungen werden über den Speichern-Button in der MySQL-Datenbank in der Tabelle classes gespeichert.

Klasseneditor

Style- und Labeleditor

Mit dem Style- und Labeleditor lassen sich die Styles der Geometrie und der Beschriftung der Klassen von Layern editieren, siehe auch API.

Der Editor (go=Style_Label_Editor) wird entweder aus dem Menü Layerverwaltung oder dem Formular zum Ändern von Layereigenschaften aufgerufen. Im Editor wählt man zunächst links oben den Layer aus. Nach Aufruf aus dem Layereditor ist der Layer schon voreingestellt. Anschließend wählt man die Klasse aus, für die man den Style anpassen will. Daraufhin erscheinen ein Feld mit den zugeordneten Styles und Labels. Ein Klick auf den Style oder das Label öffnet das dazugehörige Formular mit den entsprechenden Parametern des Mapserver-STYLE- bzw. LABEL-Objekts.

Im rechten Bereich befinden sich oben Hilfsmittel zur Auswahl von Farben und Fonts und unten eine Vorschau der Layer. Wenn der Style eines Layers geändert wird, sollte dieser auch eingeschaltet sein. Änderungen von Styles werder erst sichtbar, wenn man unter dem Formular auf Speichern geklickt hat und danach die Karte aktualisiert. Es können mehr als ein Style pro Klasse erzeugt werden oder wieder gelöscht werden. Style- und Labeleinstellungen gelten derzeit stellenübergreifend. Das heißt ein Layer sieht in allen Stellen gleich aus. Sollen Layer in verschiedenen Stellen unterschiedlich aussehen, kann man die Layer einfach kopieren und anpassen.

Es ist möglich, einen Style zu kopieren. Man trägt in einem neuen oder vorhandenen Style einfach die ID eines bereits existierenden Styles ein und speichert. Dabei ist zu beachten, dass nach jedem Tastendruck versucht wird, die Styleinformationen zu laden. Am besten kopiert man die gewünschte Style-ID deshalb aus der Zwischenablage in das Feld rein.

styleundlabeleditor.png

  • Die Felder size, minsize, maxsize, gap, initialgap und linejoinmaxsize haben einen Eingabebereich von 0 bis 200.
  • Die Felder width, minwidth und maxwidth haben einen Eingabebereich von 0 bis 100.

Import/Export-Funktionen

Daten-Export

Mit dem Daten-Export lassen sich PostGIS-Layer in andere Vektor-Formate exportieren. Der Daten-Export wird über die go-Variable "Daten_Export" aufgerufen oder indem man in aus einer Sachdatenanzeige heraus auf den Export-Button klickt. In einer Liste werden nun alle PostGIS-Layer angezeigt, die in der aktuellen Stelle abfragbar sind und für die das Recht zum Exportieren gesetzt ist. Wenn man den zu exportierenden Layer auswählt, erhält man weitere Optionen für den Export. Das Exportformat kann gewählt werden (bisher stehen Shape, GML, KML, GeoJSON, CSV, OVL und UKO zur Verfügung) und das Koordinatensystem, falls die Geometrie des Layers transformiert werden soll. Weiterhin können die Attribute ausgewählt werden, die exportiert werden sollen.

Unter Optionen kann ausgewählt werden ob die Metadatendatei des Layers, falls in der Layerdefinition unter Metadaten angegeben, mit exportiert werden soll.

Data-Export-Optionen.png

Darüber hinaus gibt es weitere Optionen, z.B. ob die Gruppennamen mit exportiert werden sollen. Diese Option ist nicht für alle Formate verfügbar.

Es ist außerdem möglich, nicht den gesamten Datenbestand des Layers zu exportieren, sondern durch räumliche Auswahl den Export auf bestimmte Datensätze zu beschränken. Dazu hat man die Möglichkeit ein Polygon zu zeichnen und so bestimmte Datensätze zu selektieren.

Nach Klick auf "Exportieren" wird der Daten-Export gestartet. Der Export liefert entweder ein zip-Archiv bei mehreren Dateien oder die einzelne Exportdatei. Damit das Zippen funktioniert, muss die Konstante "ZIP_PATH" richtig gesetzt sein. Sie verweist auf ein Zip-Programm, welches von der Kommandozeile gestartet werden kann. Bei Linux-Servern reicht in der Regel "zip". Bei Windows-Servern z.B. "c:/programme/Zip/bin/zip.exe".

Daten-Import

Daten können von den Nutzern in den Formaten Shape, GeoJSON, KML, DXF, OVL, GPX und GeoTIFF importiert werden. Über "go=Daten_Import" gelangt man ins Importformular. Hier zieht man einfach die gewünschten Dateien in den Kasten. Es können auch mehrere Dateien auf einmal hochgeladen werden und die Dateien können gezippt sein. Das Format wird automatisch erkannt. Bei Bedarf wird nach dem EPSG-Code gefragt.

Folgende Parameter sind zur Begrenzung der maximalen Datenmenge zu berücksichtigen:

MAXUPLOADSIZE(config.php) Dient der Begrenzung der maximalen Datenmenge (insgesamt pro Upload-Formular), die hochgeladen werden darf. Verhindert dass Nutzer nicht hunderte Dateien aus einem Ordner dort reinziehen können und dadurch Gigabytes an Daten hochladen.

post_max_size (php.ini) und upload_max_filesize (php.ini) Die beiden php.ini-Parameter begrenzen das Datenvolumen pro einzelnem Datei-Upload.


Durch den Import entstehen immer abfragbare Rollenlayer, die nur der jeweilige Nutzer sieht. Diese Rollenlayer und die zugehörige Tabelle existieren solange, bis der Nutzer sie selbst löscht.

daten import.PNG

Besonderheiten
Shape

Wenn eine prj-Datei vorhanden ist, wird versucht, das Koordinatenreferenzsystem aus ihr zu ermitteln. Ansonsten muss das Koordinatenreferenzsystem angegeben werden.

DXF

Das Koordinatenreferenzsystem muss angegeben werden. Hier entstehen 3 Rollenlayer für die Geometrietypen Polygon, Linie und Punkt.

GPX

Es entstehen zwei Rollenlayer für die Tracks und Waypoints.

Punktlisten-Import

Über go=Punktliste_Anzeigen können Textdateien importiert werden, die zeilenbasierte Koordinaten-Listen enthalten. Jede Zeile muss mindestens 2 Spalten für den Hoch- und den Rechts-Wert enthalten. Zusätzlich können weitere Spalten vorhanden sein. Als Trennzeichen der Spalten sind Komma, Semikolon, Tab und Leerzeichen erlaubt. Das Koordinatenreferenzsystem muss bekannt sein und es dürfen keine Leerzeilen in der Datei vorkommen. Nach dem Klick auf "Datei laden" muss noch festgelegt werden, welche Spalten als Hoch- und Rechts-Wert verwendet werden sollen. Die Auswahl einer Beschriftungsspalte ist optional.


importierte Daten mit Anderen teilen

Es gibt die Möglichkeit, den durch den Daten-Import entstandenen Rollenlayer zu einem "normalen" Layer zu machen, so dass er auch von anderen Nutzern gesehen werden kann. Dies kann der Nutzer, dem der Rollenlayer gehört über die Layeroptionen machen. Dort gibt es eine Option "Layer freigeben". Der Nutzer kann bei Bedarf noch den Namen des Layers anpassen und muss dann die Layergruppe auswählen, in der der Layer erstellt werden soll. Außerdem kann noch festgelegt werden, ob der Layer überall nur lesbar, in der gerade aktuellen Stelle editierbar oder in allen Stellen editierbar sein soll.

Share Layers.png

Damit diese Option in den Layeroptionen zur Verfügung steht, muss der Administrator vorher mehrere Sachen einstellen. Zunächst muss festgelegt werden, welche Layergruppen zur Verfügung stehen, um dort geteilte Layer zu erstellen. Diese Einstellung wird in der jeweiligen Layergruppe im Feld "Selectable_for_shared_layers" gemacht. Außerdem muss vom Administrator festgelegt werden, welchen Stellen geteilte Layer zugeordnet werden sollen. Dies wird im Stellenformular im Feld "Freigegebene Layer in dieser Stelle anzeigen" gemacht. Wenn ein Nutzer einen Rollenlayer freigibt, wird der Layer aber nicht allen Stellen zugeordnet, für das eben genannte Feld gesetzt ist, sondern nur den Stellen, denen der Nutzer auch zugeordnet ist. Dass ein bestimmter Nutzer Layer teilen darf, muss auch festgelegt werden. Dies erfolgt im Nutzerformular im Feld "Layer Teilen".

Durch die Freigabe des Rollenlayer entsteht ein neuer Layer, bei dem im Feld "Geteilt von Nutzer" die Nutzer-ID des Nutzers gespeichert ist, der den Layer freigegeben hat. Ansonsten ist es ein "normaler" Layer. Der Nutzer, der den Layer freigegeben hat, kann den Layer in den Layeroptionen auch wieder löschen.

Der geteilte Layer hat auch eine eigene Datenbank-Tabelle im Schema "shared", die von der Originaltabelle im Schema "custom_shapes" kopiert worden ist.

In einer Admin-Stelle hat man auch die Möglichkeit den Schemanamen und den Tabellennamen anzugeben, mit dem die Tabelle angelegt wird.

Kartenausschnitt speichern/laden

Unter dem Kartenfenster befinden sich die Links: Ausschnitt speichern | Ausschnitt laden. Sie dienen dem Speichern von Einstellungen des aktuellen Kartenfensters und dem Abrufen gespeicherter Einstellungen von Kartenfenstern.

Speichern:

  • Um einen bestimmen Kartenauschnitt zu speichern, passen sie das Kartenfenster und die entsprechenden Layern an.
  • Zum Speichern des aktuellen Kartenfenstern wählen Sie den Link "Ausschnitt speichern".
  • Sie gelangen auf die Oberfläche, in der der gewählte Kartenauschnitt gezeigt wird. Darüber befindet sich ein Eingabefeld, in dem es möglich ist ein Kommentar zum entsprechenden Kartenausschnitt hinzuzufügen. Der Kommentar ist in sofern wichtig, dass nach dem Zeitstempel nur so eine eindeutige Identifikation des gespeicherten Kartenausschnittes möglich ist.
  • Durch das betätigen des "Speichern"-Button werden die Einstellungen des Kartenausschnittes und der dazugehörige Kommmentar gespeichert.
  • Mit Hilfe des "Zurücksetzen"-Button können Sie die Eingabe im Kommentarfeld löschen. Es wird dabei nur das Kommentarfeld zurücksgesetzt, ohne den Kartenausschnitt zu speichern.
  • Mit betätigen des "Abbrechen"-Button beenden sie den Vorgang ohne den Kartenausschnitt zu speichern.

Wählen:

  • Wenn ein gespeicherter Kartenausschnitt geladen werden soll, betätigen Sie dazu den Link "Ausschnitt laden".
  • Es folgt eine Liste aller gespeicherten Kartenausschnitte des jeweiligen Nutzers.
  • Durch betätigen des entsprechenden Zeitstempels gelangen Sie auf die Oberfläche, mit angepassten Kartenfenster, zurück.

Drucken

Drucken eines frei wählbaren Kartenausschnittes unter Angabe des Maßstabes und der Drehung des Druckbereiches, siehe Drucken in PDF.

Benachrichtigungen

Der Administrator kann über den Menüpunkt mit dem Link index.php?go=notifications_anzeigen eine oder mehrere Benachrichtigungen für Anwender verwalten.

notifications anzeigen menue.png

Wenn der Menüpunkt angelegt ist, muss er nur der Stelle zugeordnet werden in dem die Benachrichtigungen verwaltet werden können sollen.

notifications anzeigen.png

Über den Plus-Button kann man eine neue Benachrichtigung anlegen und über den Stift gelangt man in die Editiermaske einer vorhandenen.

Notification Hint.png

In den Info-Feldern sind Hinweise zur Eingabe hinterlegt. Werden falsche Eingaben getätigt, erscheinen beim Speichern Fehlermeldungen.

notification validation result.png

Der Benachrichtigungstext und das Ablaufdatum müssen angegeben werden. Das Veröffentlichungsdatum muss vor dem Ablaufdatum liegen.

Im Feld Stellenfilter kann die Anzeige der Benachrichtigung auf bestimmte Stellen begrenzt werden.

Im Feld Nutzerfilter kann die Anzeige der Benachrichtigung auf bestimmte Nutzer begrenzt werden. Sind in beiden Feldern Filter angegeben wir beides gefiltert. Wird nichts angegeben, wird die Benachrichtigung bei allen angezeigt.

Die Benachrichtigungen werden in der MariaDB-Datenbank in der Tabelle notifications gespeichert und die Information welcher Nutzer seine Benachrichtigungen noch nicht gelöscht hat in der Tabelle user2notifications.

Wird eine neue Benachrichtigung vom Admin eingetragen, erhalten zunächst alle Nutzer eine Eintragung in der Tabelle user2notifications. Wählt ein Nutzer beim Ausblenden einer Benachrichtigung 'nicht mehr anzeigen', wird diese Zuordnung in der Tabelle user2notification gelöscht und für diesen Nutzer in keiner Stelle mehr angezeigt.

Wird eine Benachrichtigung geändert, werden die Zuordnungen für alle Nutzer noch mal neu eingetragen. So sehen die Nutzer auch geänderte Benachrichtigungen obwohl sie diese vielleicht schon mal mit 'nicht mehr anzeigen' abgewählt hatten.

Löscht der Admin eine Benachrichtigung wird vorher eine Warnung angezeigt.

notification delete warning.png

Beim Löschen einer Benachrichtigung werden auch alle Zuordnungen zu Nutzern gelöscht. Zwischen notifications und user2notifications besteht ein Fremdschlüssel mit ON DELETE CASCADE und ON UPDATE CASCADE. Wenn also in der Datenbank die ID einer Notification geändert wird, wird auch die notification_id in der Tabelle user2notifications geändert.


Die Anzahl der verfügbaren neuen Benachrichtigungen werden über das Glockensymbol im Kopf der Oberfläche angezeigt.

glocke.png

Wer eine eigene Header-Datei verwendet kann die Funktion zur Anzeige der Benachrichtiungen in seinen Kopf übernehmen in dem er das Div mit dem title="Benachrichtigungen" aus der Datei layouts/snippets/header.html übernimmt. Der Style der Benachtichtigungsfenster kann über den Klassennamen notification-box in der eigenen Style-Datei überschrieben werden.

notification box.png

Wie der Nutzer die Benachrichtigungen ausblenden und für sich löschen kann ist in der Nutzer-Dokumentation beschrieben. Nutzer-Dokumentation#Benachrichtigungen

Die Anzahl der Benachrichtigungen und die Benachrichtigungen selber, werden beim Laden der Seite neu aus der Datenbank abgefragt. Dabei wird der Nutzer- und Stellenfilter angewendet.u2m.user_id = " . $gui->user->id . " AND

 u2m.user_id = " . $gui->user->id . " AND
 CURRENT_DATE BETWEEN COALESCE(veroeffentlichungsdatum, CURRENT_DATE) AND COALESCE(ablaufdatum, CURRENT_DATE) AND
 (
   m.stellen_filter IS NULL OR
   m.stellen_filter =  OR
   concat(',', m.stellen_filter, ',') LIKE '%," . $gui->Stelle->id . ",%'
 )

Funktionen auf dem Server

  • Speicherung und Verwaltung der Karteneinstellungen
    In der MySQL-Datenbank werden die Informationen vorgehalten, die für eine Kartenausgabe erforderlich sind. Es handelt sich im Wesentlichen um die Daten, die sonst in der Map-Datei für den UMN-MapServer enthalten sind, nur dass sie in der Datenbank für verschiedene Karten nicht redundant abgespeichert werden.
  • Speicherung und Verwaltung von Benutzerdaten
    In der MySQL-Datenbank werden Daten zu den Benutzern, zu den Stellen und zu den Rollen, die die Benutzer in den Stellen einnehmen können gespeichert. Folgende Informationen können zu den Nutzern gespeichert werden.
    • login-Name, Passwort, Name, Tel., E-Mail, Funktion, letzte besuchte Stelle des Benutzers
    • Bezeichnung, Gültigkeitsdauer, maximale Kartenausdehnung, Referenzkarte, Wappen, Datenbankverbindung, OWS-Metadaten
    • aktuelle Kartenausdehnung, Fenstergröße, Zoomfaktor, Referenzsystem, letztes gewähltes Werkzeug, Layoutgestaltung der GUI (Skin) können für jeden Benutzer innerhalb der Stelle gespeichert werden.
  • Einlesen von ALB-Daten im WLDGE-Format in eine PostgreSQL-Datenbank
  • Freie Gestaltung von Menüpunkten und Zusammenfassung von Menüunterpunkten zu Obermenüs.

Fachschalen

Zu kvwmap gehört eine Reihe von Funktionen, die in Fachschalen zusammengefasst wurden. Eine Fachschale beinhaltet thematisch zusammengehörende Funktionen zur Erfüllung fachspezifischer Aufgaben. Die anderen Funktionen stehen parallel dazu immer zur Verfügung. Die benötigten Funktionen können über das frei konfigurierbare Menü thematisch zu einer Fachschale und über zugriffsrechtlich über die Rolle eines Benutzers in einer Stelle zugeordnet werden.


Änderung der Eigentümeranschriften

Die in der Sachdatenanzeige der Flurstücke angezeigten Eigentümeranschriften können von autorisierten Nutzern geändert werden. Die Änderungen werden in zwei separaten Tabellen ax_person_temp und ax_anschrift_temp gespeichert und können als NAS-Fortführungsauftrag exportiert werden, um damit den ALKIS-Bestand zu aktualisieren.

Um diese Funktionen nutzen zu können, müssen folgende Voraussetzungen erfüllt sein:

  • In der PostgreSQL-DB müssen die Tabellen ax_person_temp und ax_anschrift_temp vorhanden sein (siehe ALKIS-Schema).
  • In der MySQL-DB müssen die beiden folgenden Layer angelegt werden:
SET @group_id = 1;
SET @connection = 'user=xxxx password=xxxx dbname=kvwmapsp';

INSERT INTO layer (`Name`,`alias`,`Datentyp`,`Gruppe`,`pfad`,`maintable`,`Data`,`schema`,`document_path`,`tileindex`,`tileitem`,`labelangleitem`,`labelitem`,`labelmaxscale`,`labelminscale`,`labelrequires`,`connection`,`printconnection`,`connectiontype`,`classitem`,`filteritem`,`tolerance`,`toleranceunits`,`epsg_code`,`template`,`queryable`,`transparency`,`drawingorder`,`minscale`,`maxscale`,`offsite`,`ows_srs`,`wms_name`,`wms_server_version`,`wms_format`,`wms_connectiontimeout`,`wms_auth_username`,`wms_auth_password`,`wfs_geom`,`selectiontype`,`querymap`,`logconsume`,`processing`,`kurzbeschreibung`,`datenherr`,`metalink`,`privileg`) VALUES('Adressänderungen Anschrift','','5',@group_id,'SELECT gml_id, ort_post, postleitzahlpostzustellung, strasse, hausnummer, ortsteil, datum, user_id FROM ax_anschrift_temp WHERE 1=1','ax_anschrift_temp','','alkis','','','','','','50000','0','',@connection,'','6','lfd_nr','','3','pixels','2398','','1',NULL,NULL,'-1','-1','','EPSG:2398','','1.1.0','image/png','60','','','','','0','0','','','','','0');
SET @last_layer_id162=LAST_INSERT_ID();
INSERT INTO layer_attributes (`layer_id`,`name`,`real_name`,`tablename`,`table_alias_name`,`type`,`geometrytype`,`constraints`,`nullable`,`length`,`decimal_length`,`default`,`form_element_type`,`options`,`alias`,`alias_low-german`,`alias_english`,`alias_polish`,`alias_vietnamese`,`tooltip`,`group`,`raster_visibility`,`mandatory`,`order`,`privileg`,`query_tooltip`) VALUES(@last_layer_id162,'datum','datum','ax_anschrift_temp','ax_anschrift_temp','timestamp','','','1',NULL,NULL,'','Time','','Datum','','','','','','',NULL,NULL,'6','0','0');
INSERT INTO layer_attributes (`layer_id`,`name`,`real_name`,`tablename`,`table_alias_name`,`type`,`geometrytype`,`constraints`,`nullable`,`length`,`decimal_length`,`default`,`form_element_type`,`options`,`alias`,`alias_low-german`,`alias_english`,`alias_polish`,`alias_vietnamese`,`tooltip`,`group`,`raster_visibility`,`mandatory`,`order`,`privileg`,`query_tooltip`) VALUES(@last_layer_id162,'gml_id','gml_id','ax_anschrift_temp','ax_anschrift_temp','varchar','','PRIMARY KEY','0','16',NULL,'','Text','','','','','','','','',NULL,NULL,'0','0','0');
INSERT INTO layer_attributes (`layer_id`,`name`,`real_name`,`tablename`,`table_alias_name`,`type`,`geometrytype`,`constraints`,`nullable`,`length`,`decimal_length`,`default`,`form_element_type`,`options`,`alias`,`alias_low-german`,`alias_english`,`alias_polish`,`alias_vietnamese`,`tooltip`,`group`,`raster_visibility`,`mandatory`,`order`,`privileg`,`query_tooltip`) VALUES(@last_layer_id162,'hausnummer','hausnummer','ax_anschrift_temp','ax_anschrift_temp','varchar','','','1',NULL,NULL,'','Text','','Hausnummer','','','','','','',NULL,NULL,'4','0','0');
INSERT INTO layer_attributes (`layer_id`,`name`,`real_name`,`tablename`,`table_alias_name`,`type`,`geometrytype`,`constraints`,`nullable`,`length`,`decimal_length`,`default`,`form_element_type`,`options`,`alias`,`alias_low-german`,`alias_english`,`alias_polish`,`alias_vietnamese`,`tooltip`,`group`,`raster_visibility`,`mandatory`,`order`,`privileg`,`query_tooltip`) VALUES(@last_layer_id162,'ortsteil','ortsteil','ax_anschrift_temp','ax_anschrift_temp','varchar','','','1',NULL,NULL,'','Text','','','','','','','','',NULL,NULL,'5','0','0');
INSERT INTO layer_attributes (`layer_id`,`name`,`real_name`,`tablename`,`table_alias_name`,`type`,`geometrytype`,`constraints`,`nullable`,`length`,`decimal_length`,`default`,`form_element_type`,`options`,`alias`,`alias_low-german`,`alias_english`,`alias_polish`,`alias_vietnamese`,`tooltip`,`group`,`raster_visibility`,`mandatory`,`order`,`privileg`,`query_tooltip`) VALUES(@last_layer_id162,'ort_post','ort_post','ax_anschrift_temp','ax_anschrift_temp','varchar','','','1',NULL,NULL,'','Text','','Ort','','','','','','',NULL,NULL,'1','0','0');
INSERT INTO layer_attributes (`layer_id`,`name`,`real_name`,`tablename`,`table_alias_name`,`type`,`geometrytype`,`constraints`,`nullable`,`length`,`decimal_length`,`default`,`form_element_type`,`options`,`alias`,`alias_low-german`,`alias_english`,`alias_polish`,`alias_vietnamese`,`tooltip`,`group`,`raster_visibility`,`mandatory`,`order`,`privileg`,`query_tooltip`) VALUES(@last_layer_id162,'postleitzahlpostzustellung','postleitzahlpostzustellung','ax_anschrift_temp','ax_anschrift_temp','varchar','','','1',NULL,NULL,'','Text','','PLZ','','','','','','',NULL,NULL,'2','0','0');
INSERT INTO layer_attributes (`layer_id`,`name`,`real_name`,`tablename`,`table_alias_name`,`type`,`geometrytype`,`constraints`,`nullable`,`length`,`decimal_length`,`default`,`form_element_type`,`options`,`alias`,`alias_low-german`,`alias_english`,`alias_polish`,`alias_vietnamese`,`tooltip`,`group`,`raster_visibility`,`mandatory`,`order`,`privileg`,`query_tooltip`) VALUES(@last_layer_id162,'strasse','strasse','ax_anschrift_temp','ax_anschrift_temp','varchar','','','1',NULL,NULL,'','Text','','Strasse','','','','','','',NULL,NULL,'3','0','0');
INSERT INTO layer_attributes (`layer_id`,`name`,`real_name`,`tablename`,`table_alias_name`,`type`,`geometrytype`,`constraints`,`nullable`,`length`,`decimal_length`,`default`,`form_element_type`,`options`,`alias`,`alias_low-german`,`alias_english`,`alias_polish`,`alias_vietnamese`,`tooltip`,`group`,`raster_visibility`,`mandatory`,`order`,`privileg`,`query_tooltip`) VALUES(@last_layer_id162,'user_id','user_id','ax_anschrift_temp','ax_anschrift_temp','int4','','','1','32',NULL,'','UserID','','User-ID','','','','','','',NULL,NULL,'7','0','0');

INSERT INTO layer (`Name`,`alias`,`Datentyp`,`Gruppe`,`pfad`,`maintable`,`Data`,`schema`,`document_path`,`tileindex`,`tileitem`,`labelangleitem`,`labelitem`,`labelmaxscale`,`labelminscale`,`labelrequires`,`connection`,`printconnection`,`connectiontype`,`classitem`,`filteritem`,`tolerance`,`toleranceunits`,`epsg_code`,`template`,`queryable`,`transparency`,`drawingorder`,`minscale`,`maxscale`,`offsite`,`ows_srs`,`wms_name`,`wms_server_version`,`wms_format`,`wms_connectiontimeout`,`wms_auth_username`,`wms_auth_password`,`wfs_geom`,`selectiontype`,`querymap`,`logconsume`,`processing`,`kurzbeschreibung`,`datenherr`,`metalink`,`privileg`) VALUES('Adressänderungen Person','','5',@group_id,'SELECT * FROM ax_person_temp WHERE 1=1','ax_person_temp','','alkis','','','','','','50000','0','',@connection,'','6','lfd_nr','','3','pixels','2398','','1',NULL,NULL,'-1','-1','','EPSG:2398','','1.1.0','image/png','60','','','','','0','0','','','','','0');
SET @last_layer_id827=LAST_INSERT_ID();
INSERT INTO layer_attributes (`layer_id`,`name`,`real_name`,`tablename`,`table_alias_name`,`type`,`geometrytype`,`constraints`,`nullable`,`length`,`decimal_length`,`default`,`form_element_type`,`options`,`alias`,`alias_low-german`,`alias_english`,`alias_polish`,`alias_vietnamese`,`tooltip`,`group`,`raster_visibility`,`mandatory`,`order`,`privileg`,`query_tooltip`) VALUES(@last_layer_id827,'datum','datum','ax_person_temp','ax_person_temp','timestamp','','','1',NULL,NULL,'','Time','','Datum','','','','','','',NULL,NULL,'2','0','0');
INSERT INTO layer_attributes (`layer_id`,`name`,`real_name`,`tablename`,`table_alias_name`,`type`,`geometrytype`,`constraints`,`nullable`,`length`,`decimal_length`,`default`,`form_element_type`,`options`,`alias`,`alias_low-german`,`alias_english`,`alias_polish`,`alias_vietnamese`,`tooltip`,`group`,`raster_visibility`,`mandatory`,`order`,`privileg`,`query_tooltip`) VALUES(@last_layer_id827,'gml_id','gml_id','ax_person_temp','ax_person_temp','varchar','','PRIMARY KEY','0','16',NULL,'','Autovervollständigungsfeld','select array_to_string(array[vorname, nachnameoderfirma], \' \') as output, gml_id as value from alkis.ax_person where 1=1','Name','','','','','','',NULL,NULL,'0','0','0');
INSERT INTO layer_attributes (`layer_id`,`name`,`real_name`,`tablename`,`table_alias_name`,`type`,`geometrytype`,`constraints`,`nullable`,`length`,`decimal_length`,`default`,`form_element_type`,`options`,`alias`,`alias_low-german`,`alias_english`,`alias_polish`,`alias_vietnamese`,`tooltip`,`group`,`raster_visibility`,`mandatory`,`order`,`privileg`,`query_tooltip`) VALUES(@last_layer_id827,'hat','hat','ax_person_temp','ax_person_temp','_varchar','','','1',NULL,NULL,'','Autovervollständigungsfeld','select strasse||\' \'||hausnummer||\' \'||postleitzahlpostzustellung||\' \'||ort_post||\' \'||coalesce(ortsteil, \'\') as output, gml_id as value from alkis.ax_anschrift UNION select strasse||\' \'||hausnummer||\' \'||postleitzahlpostzustellung||\' \'||ort_post||\' \'||coalesce(ortsteil, \'\') as output, gml_id as value from alkis.ax_anschrift_temp where 1=1 order by output;layer_id=162 embedded','Anschrift','','','','','Geben Sie die ersten Buchstaben der neuen Anschrift ein und wählen die richtige Anschrift aus. Wenn die Anschrift bislang nicht existiert, legen Sie eine neue Anschrift an und wählen sie anschließend hier aus.','',NULL,NULL,'1','0','0');
INSERT INTO layer_attributes (`layer_id`,`name`,`real_name`,`tablename`,`table_alias_name`,`type`,`geometrytype`,`constraints`,`nullable`,`length`,`decimal_length`,`default`,`form_element_type`,`options`,`alias`,`alias_low-german`,`alias_english`,`alias_polish`,`alias_vietnamese`,`tooltip`,`group`,`raster_visibility`,`mandatory`,`order`,`privileg`,`query_tooltip`) VALUES(@last_layer_id827,'user_id','user_id','ax_person_temp','ax_person_temp','int4','','','1','32',NULL,'','UserID','','User-ID','','','','','','',NULL,NULL,'3','0','0');

UPDATE layer_attributes SET options = REPLACE(options, '162', @last_layer_id162) WHERE layer_id IN(@last_layer_id162, @last_layer_id827) AND form_element_type IN ('SubFormPK', 'SubFormFK', 'SubFormEmbeddedPK', 'Autovervollständigungsfeld', 'Auswahlfeld');
UPDATE layer_attributes SET options = REPLACE(options, '827', @last_layer_id827) WHERE layer_id IN(@last_layer_id162, @last_layer_id827) AND form_element_type IN ('SubFormPK', 'SubFormFK', 'SubFormEmbeddedPK', 'Autovervollständigungsfeld', 'Auswahlfeld');
  • In der config.php müssen die beiden Konstanen LAYER_ID_ADRESSAENDERUNGEN_PERSON und LAYER_ID_ADRESSAENDERUNGEN_ANSCHRIFT auf die IDs des beiden neuen Layer gesetzt werden.
  • Es muss die Funktion Adressaenderungen angelegt und den Stellen zugewiesen werden, die Anschriftenänderungen vornehmen dürfen.
  • Das Exportieren der Anschriftenänderungen erfolgt über die go-Variable Adressaenderungen_Export. Dieser Menüpunkt sollte nur der Stelle zugewiesen werden, die die gespeicherten Änderungen exportieren darf (im Normalfall der Administrator).
  • In der Rechteverwaltung muß den gewünschten Stellen für den Layer "Adressaenderungen Person" das Recht zum Erzeugen von Datensätzen gegeben werden. Die Attribute "gml_id", "datum" und "user_id" sollten nur lesbar sein und nur das Attribut "hat" editierbar. Für den Layer "Adressaenderungen Anschrift" muss ebenfalls das Recht zum Erzeugen von Datensätzen eingetragen werden. Auch hier sollten die Attribute "gml_id", "datum" und "user_id" wieder nur lesbar sein und die restlichen 5 Attribute editierbar.

Hat ein Nutzer in einer Stelle das Recht Adressänderungen vorzunehmen, so erscheint in der Sachdatenanzeige der Flurstücke neben jeder Eigentümeradresse ein Link Anschrift aktualisieren. Der Link öffnet ein eingebettetes Formular zur Auswahl der neuen Anschrift über ein Autovervollständigungsfeld. Hier ist die aktuelle Anschrift vorausgewählt und alle Anschriften aus ax_anschrift und ax_anschrift_temp sind auswählbar. Zusätzlich zur neuen Anschrift wird die User-ID, das Datum und als Schluessel die gml_id der Person gespeichert. Wenn es die neue Anschrift noch nicht im Datenbestand gibt, ist es über den Link "neu" möglich, eine neue Anschrift zu erstellen. Dazu öffnet sich ein weiteres Unterformular und die neue Anschrift kann hier eingegeben werden. Danach ist die neu erstellte Anschrift im o.g. Autovervollständigungsfeld auswählbar. Auch für neu erstellte Anschriften wird die User-ID und das Datum gespeichert. Wurde die Anschrift eines Eigentümers bereits geändert, erscheint bei Abfrage des entsprechenden Flurstücks unter der alten Anschrift die neue Anschrift mit Angabe des Datums und des Nutzers, welcher die Änderung vorgenommen hat. Daneben erscheint ein Link Aktualisierte Anschrift ändern, um die neue Anschrift zu bearbeiten.

Um die neuen Anschriften in einen NAS-Fortführungsauftrag zu exportieren, ruft man die go-Variable Adressaenderungen_Export auf. Hier kann man nun die Exportdatei erzeugen und sie anschließend herunterladen.

Vor jedem Export werden die beiden temp-Tabellen bereinigt, d.h. die bei der letzten Fortführung übernommenen Anschriften werden aus dem temp-Tabellen gelöscht.

Bauleitplanungsänderung

Bei der Veränderung von B-Pläne etc. soll den Gemeinden, als Träger der Bauleitplanung, die Möglichkeit gegeben werden, um die zu verändernden Stellen ein Polygon zu zeichnen und somit die betroffenen Stellen unkenntlich zu machen. Damit soll gewährleistet werden, dass die betroffenen Teile der Pläne als nicht aktuell gekennzeichnet werden und somit seitens der Kreisverwaltung keine Falschaussagen getroffen werden.

Um die Fachschale Bauleitplanungsänderung aufrufen zu können, muss es einen entsprechenden Menüpunkt mit der go-Variable 'bauleitplanung' geben (Tabelle: u_menues). Außderdem muss dieser Menüpunkt der Stelle (Tabelle: u_menue2stelle) und dem Nutzer dieser Stelle (Tabelle: u_menue2rolle) zugeordnet werden. In der Fachschale ist es möglich ein Polygon zu zeichnen, um so das betroffene Gebiet innerhalb eines B-Planes zu markieren. Desweiteren muss eine E-Mail-Adresse angegeben werden, an die eine Mail mit der Änderungsbenachrichtigung geschickt wird. Zu dieser Benachrichtung gehört die Nummer des bearbeiteten B-Planes und eine Bemerkung zur Änderung. Nach dem Absenden des Formulars wird das Polygon gespeichert, und die Mail wird automatisch versandt.

Damit die geänderten Bereiche in den B-Plänen nicht mehr zu sehen, bzw. markiert sind, muss es einen Layer geben, der über dem Layer der B-Pläne liegt. Dieser Layer könnte beispielsweise so aussehen:

INSERT INTO layer VALUES (106, 'Bauleitaenderungen', 2, 4, "", 'the_geom from (select the_geom,id
from bp_aenderungen where loeschdatum is null) as foo using unique id using
srid=2398', "", "", "", "", 50000, 0, "", 'user=kvwmap password=kvwmap dbname=kvwmapsp',
6, "", "", 3, 'pixels', 0, '2398', 'EPSG:2398', "", '1.1.0', 'image/png', 60, NULL);

Für die Darstellung des Layers wird dann natürlich noch eine entsprechende Klasse und ein Style benötigt. Damit gewährleistet ist, dass dieser Layer stets aktiv ist, wenn der Layer B-Pläne aktiv ist, wird in das Feld requires in der Tabelle used_layer folgende Bedingung eingetragen:

([B-Plaene]=1)

Dadurch ist der Layer Bauleitaenderungen vom Layer B-Pläne abhängig, immer aktiv wenn dieser aktiv ist und sein Name nicht in der Legende zu sehen. Gibt man der Klasse des Layers Bauleitaenderungen keinen Namen, so erscheint auch die Klasse des Layers nicht in der Legende.

Um den die gespeicherten Polygone der Bauleitänderung trotzdem abfragen zu können, wird ein zweiter Layer angelegt. Dieser sieht z.B. so aus:

INSERT INTO layer VALUES (112, 'B-Plan Änderungen', 2, 4, 'SELECT id,
username,hinweis,bemerkung,the_geom,datum FROM bp_aenderungen WHERE 1=1', 'the_geom from (select
the_geom,id from bp_aenderungen where loeschdatum is null) as foo using unique id using srid=2398', "",
"", "", "", 50000, 0, "", 'user=kvwmap password=kvwmap dbname=kvwmapsp', 6, "", "", 3, 'pixels', 0,
'2398', 'EPSG:2398', "", '1.1.0', 'image/png', 60, NULL);

Dieser Layer ist dann nach Zuweisung von Klasse und Style in der Legende zu sehen und kann auch ausgeschaltet werden.

Die Polygone, die man in der Fachschale erstellt hat, lassen sich auch wieder löschen, jedoch werden sie nicht wirklich gelöscht, sondern nur als gelöscht markiert. Um Polygone löschen zu können, muss es in u_funktionen eine Funktion "BplanAenderungLoeschen" geben und diese muss der gewünschten Stelle zugeordnet werden. Nach einer Sachdatenabfrage auf den Layer "B-Plan Änderungen" lassen sich nun die aufgeführten Polygone löschen.


Notizen

Mit der Funktion "Notizen" können Textnotizen an jede beliebige Position innerhalb des Kartenbereichs einer Stelle gesetzt werden. Es kann entweder ein Polygon oder ein Punkt erfasst werden, um den Geltungsbereich der Notiz zu markieren. Eine Notiz gehört immer zu einer bestimmten Kategorie. Die Kategorien lassen sich vom Administrator frei definieren und den entsprechenden Stellen zuordnen.

Voraussetzungen:

  • Über "go=Notizenformular_KatVerwaltung" müssen Kategorien angelegt werden und den entsprechenden Stellen zugeordnet werden.
  • Den Stellen, die Notizen erfassen können sollen, muss das Menü "go=Notizenformular" zugewiesen werden.
  • Es müssen 2 Layer "Notizen" und "Notizen_poly" angelegt und den entsprechenden Stellen zugeordnet werden:
SET @group_id = 1;
SET @connection_id = 1;
SET @connection = 'host=pgsql dbname=kvwmapsp user=kvwmap password=*****';

INSERT INTO layer (`Name`, `alias`, `Datentyp`, `Gruppe`, `pfad`, `maintable`, `Data`, `schema`, `document_path`, `tileindex`, `tileitem`, `labelangleitem`, `labelitem`, `labelmaxscale`, `labelminscale`, `labelrequires`, `connection_id`, `connection`, `printconnection`, `connectiontype`, `classitem`, `tolerance`, `toleranceunits`, `epsg_code`, `template`, `queryable`, `transparency`, `drawingorder`, `minscale`, `maxscale`, `offsite`, `ows_srs`, `wms_name`, `wms_server_version`, `wms_format`, `wms_connectiontimeout`, `wms_auth_username`, `wms_auth_password`, `wfs_geom`, `selectiontype`, `querymap`, `logconsume`, `processing`, `kurzbeschreibung`, `metalink`, `privileg`, `trigger_function`, `sync`) VALUES ('Notizen', '', '0', @group_id, 'SELECT q_notiz_kategorien.id,notiz,q_notiz_kategorien.kategorie,person,datum, the_geom FROM q_notizen, q_notiz_kategorien WHERE q_notiz_kategorien.id = q_notizen.kategorie_id::integer', 'q_notizen', 'the_geom from (select GeometryType(the_geom) as geomtype,oid,notiz AS label,person,kategorie_id,datum,st_Pointonsurface(the_geom) AS the_geom from q_notizen) as foo using unique oid using srid=2398', '', '', '', '', '', 'label', '50000', '0', '', @connection_id, @connection, '', '6', 'geomtype', '3', 'pixels', '2398', '', '0', NULL, '10000', NULL, NULL, '', 'EPSG:2398', '', '1.1.0', 'image/png', '60', '', '', '', '', '0', '0', '', '', '', '0', '', '0');
SET @last_layer_id53=LAST_INSERT_ID();
INSERT INTO layer_attributes (`layer_id`, `name`, `real_name`, `tablename`, `table_alias_name`, `type`, `geometrytype`, `constraints`, `nullable`, `length`, `decimal_length`, `default`, `form_element_type`, `options`, `alias`, `alias_low-german`, `alias_english`, `alias_polish`, `alias_vietnamese`, `tooltip`, `group`, `raster_visibility`, `mandatory`, `order`, `privileg`, `query_tooltip`) VALUES (@last_layer_id53, 'datum', 'datum', 'q_notizen', 'q_notizen', 'date', '', '', '1', NULL, NULL, '', 'Text', '', '', '', '', '', '', '', '', NULL, NULL, '4', '0', '0');
INSERT INTO layer_attributes (`layer_id`, `name`, `real_name`, `tablename`, `table_alias_name`, `type`, `geometrytype`, `constraints`, `nullable`, `length`, `decimal_length`, `default`, `form_element_type`, `options`, `alias`, `alias_low-german`, `alias_english`, `alias_polish`, `alias_vietnamese`, `tooltip`, `group`, `raster_visibility`, `mandatory`, `order`, `privileg`, `query_tooltip`) VALUES (@last_layer_id53, 'id', 'id', 'q_notiz_kategorien', 'q_notiz_kategorien', 'int4', '', '', '1', '32', '0', '', 'Text', '', '', '', '', '', '', '', '', NULL, NULL, '0', '0', '0');
INSERT INTO layer_attributes (`layer_id`, `name`, `real_name`, `tablename`, `table_alias_name`, `type`, `geometrytype`, `constraints`, `nullable`, `length`, `decimal_length`, `default`, `form_element_type`, `options`, `alias`, `alias_low-german`, `alias_english`, `alias_polish`, `alias_vietnamese`, `tooltip`, `group`, `raster_visibility`, `mandatory`, `order`, `privileg`, `query_tooltip`) VALUES (@last_layer_id53, 'kategorie', 'kategorie', 'q_notiz_kategorien', 'q_notiz_kategorien', 'text', '', '', '1', NULL, NULL, '', 'Text', '', '', '', '', '', '', '', '', NULL, NULL, '2', '0', '0');
INSERT INTO layer_attributes (`layer_id`, `name`, `real_name`, `tablename`, `table_alias_name`, `type`, `geometrytype`, `constraints`, `nullable`, `length`, `decimal_length`, `default`, `form_element_type`, `options`, `alias`, `alias_low-german`, `alias_english`, `alias_polish`, `alias_vietnamese`, `tooltip`, `group`, `raster_visibility`, `mandatory`, `order`, `privileg`, `query_tooltip`) VALUES (@last_layer_id53, 'notiz', 'notiz', 'q_notizen', 'q_notizen', 'text', '', '', '1', NULL, NULL, '', 'Text', '', '', '', '', '', '', '', '', NULL, NULL, '1', '0', '0');
INSERT INTO layer_attributes (`layer_id`, `name`, `real_name`, `tablename`, `table_alias_name`, `type`, `geometrytype`, `constraints`, `nullable`, `length`, `decimal_length`, `default`, `form_element_type`, `options`, `alias`, `alias_low-german`, `alias_english`, `alias_polish`, `alias_vietnamese`, `tooltip`, `group`, `raster_visibility`, `mandatory`, `order`, `privileg`, `query_tooltip`) VALUES (@last_layer_id53, 'person', 'person', 'q_notizen', 'q_notizen', 'varchar', '', '', '1', '100', NULL, '', 'Text', '', '', '', '', '', '', '', '', NULL, NULL, '3', '0', '0');
INSERT INTO layer_attributes (`layer_id`, `name`, `real_name`, `tablename`, `table_alias_name`, `type`, `geometrytype`, `constraints`, `nullable`, `length`, `decimal_length`, `default`, `form_element_type`, `options`, `alias`, `alias_low-german`, `alias_english`, `alias_polish`, `alias_vietnamese`, `tooltip`, `group`, `raster_visibility`, `mandatory`, `order`, `privileg`, `query_tooltip`) VALUES (@last_layer_id53, 'the_geom', 'the_geom', 'q_notizen', 'q_notizen', 'geometry', 'GEOMETRY', '', '1', NULL, NULL, '', 'Text', '', '', '', '', '', '', '', '', NULL, NULL, '5', '0', '0');
INSERT INTO classes (`Name`, `Layer_ID`, `Expression`, `drawingorder`, `text`) VALUES ('Punktnotizen', @last_layer_id53, '(\'[geomtype]\' eq \'POINT\')', '0', '');
SET @last_class_id=LAST_INSERT_ID();
INSERT INTO styles (`symbol`, `symbolname`, `size`, `color`, `backgroundcolor`, `outlinecolor`, `minsize`, `maxsize`, `angle`, `angleitem`, `width`, `minwidth`, `maxwidth`) VALUES (NULL, 'zugehoerigkeitspfeil', '30', '255 255 150', '', '100 100 100', '20', '40', '0', '', NULL, NULL, NULL);
SET @last_style_id=LAST_INSERT_ID();
INSERT INTO u_styles2classes (style_id, class_id, drawingorder) VALUES (@last_style_id, @last_class_id, 0);
INSERT INTO labels (`font`, `type`, `color`, `outlinecolor`, `shadowcolor`, `shadowsizex`, `shadowsizey`, `backgroundcolor`, `backgroundshadowcolor`, `backgroundshadowsizex`, `backgroundshadowsizey`, `size`, `minsize`, `maxsize`, `position`, `offsetx`, `offsety`, `angle`, `autoangle`, `buffer`, `antialias`, `minfeaturesize`, `maxfeaturesize`, `partials`, `wrap`, `the_force`) VALUES ('verdana', NULL, '0 0 0', '255 255 150', '', NULL, NULL, '255 255 150', '100 100 100', '2', '2', '8', '7', '10', '1', '-1', '-1', NULL, NULL, '4', NULL, NULL, NULL, NULL, '59', '1');
SET @last_label_id=LAST_INSERT_ID();
INSERT INTO u_labels2classes (label_id, class_id) VALUES (@last_label_id, @last_class_id);
INSERT INTO classes (`Name`, `Layer_ID`, `Expression`, `drawingorder`, `text`) VALUES ('Flächennotizen', @last_layer_id53, '(\'[geomtype]\' ne \'POINT\')', '0', '');
SET @last_class_id=LAST_INSERT_ID();
INSERT INTO styles (`symbol`, `symbolname`, `size`, `color`, `backgroundcolor`, `outlinecolor`, `minsize`, `maxsize`, `angle`, `angleitem`, `antialias`, `width`, `minwidth`, `maxwidth`, `sizeitem`) VALUES (NULL, 'zugehoerigkeitspfeil', '30', '126 177 221', '', '100 100 100', '20', '40', '', '', NULL, NULL, NULL, NULL, '');
SET @last_style_id=LAST_INSERT_ID();
INSERT INTO u_styles2classes (style_id, class_id, drawingorder) VALUES (@last_style_id, @last_class_id, 0);
INSERT INTO labels (`font`, `type`, `color`, `outlinecolor`, `shadowcolor`, `shadowsizex`, `shadowsizey`, `backgroundcolor`, `backgroundshadowcolor`, `backgroundshadowsizex`, `backgroundshadowsizey`, `size`, `minsize`, `maxsize`, `position`, `offsetx`, `offsety`, `angle`, `autoangle`, `buffer`, `antialias`, `minfeaturesize`, `maxfeaturesize`, `partials`, `wrap`, `the_force`) VALUES ('verdana', NULL, '0 0 0', '', '', NULL, NULL, '126 177 221', '100 100 100', '2', '2', '8', '7', '10', '1', '-2', '-2', '360', NULL, '4', '1', NULL, NULL, '1', '59', '1');
SET @last_label_id=LAST_INSERT_ID();
INSERT INTO u_labels2classes (label_id, class_id) VALUES (@last_label_id, @last_class_id);
INSERT INTO layer (`Name`, `alias`, `Datentyp`, `Gruppe`, `pfad`, `maintable`, `Data`, `schema`, `document_path`, `tileindex`, `tileitem`, `labelangleitem`, `labelitem`, `labelmaxscale`, `labelminscale`, `labelrequires`, `connection`, `printconnection`, `connectiontype`, `classitem`, `filteritem`, `tolerance`, `toleranceunits`, `epsg_code`, `template`, `queryable`, `transparency`, `drawingorder`, `minscale`, `maxscale`, `offsite`, `ows_srs`, `wms_name`, `wms_server_version`, `wms_format`, `wms_connectiontimeout`, `wms_auth_username`, `wms_auth_password`, `wfs_geom`, `selectiontype`, `querymap`, `logconsume`, `processing`, `kurzbeschreibung`, `datenherr`, `metalink`, `privileg`, `trigger_function`, `sync`) VALUES ('Notizen_poly', '', '2', @group_id, 'SELECT q_notiz_kategorien.id,notiz,q_notiz_kategorien.kategorie,person,datum, the_geom FROM q_notizen, q_notiz_kategorien WHERE q_notiz_kategorien.id = q_notizen.kategorie_id', 'q_notizen', 'the_geom from (select oid, kategorie_id,person,datum,the_geom from q_notizen) as foo using unique oid using srid=2398', '', '', '', '', '', '', '50000', NULL, '', @connection, '', '6', 'kategorie_id', 'kategorie_id', '3', 'pixels', '2398', '', '0', NULL, '10000', NULL, NULL, '', 'EPSG:2398', '', '1.1.0', 'image/png', '60', '', '', '', '', '0', '0', '', '', '', '', '0', '', '');
SET @last_layer_id102=LAST_INSERT_ID();
INSERT INTO layer_attributes (`layer_id`, `name`, `real_name`, `tablename`, `table_alias_name`, `type`, `geometrytype`, `constraints`, `nullable`, `length`, `decimal_length`, `default`, `form_element_type`, `options`, `alias`, `alias_low-german`, `alias_english`, `alias_polish`, `alias_vietnamese`, `tooltip`, `group`, `raster_visibility`, `mandatory`, `order`, `privileg`, `query_tooltip`) VALUES (@last_layer_id102, 'datum', 'datum', 'q_notizen', 'q_notizen', 'date', '', '', '1', NULL, NULL, '', 'Text', '', '', '', '', '', '', '', '', NULL, NULL, '4', '0', '0');
INSERT INTO layer_attributes (`layer_id`, `name`, `real_name`, `tablename`, `table_alias_name`, `type`, `geometrytype`, `constraints`, `nullable`, `length`, `decimal_length`, `default`, `form_element_type`, `options`, `alias`, `alias_low-german`, `alias_english`, `alias_polish`, `alias_vietnamese`, `tooltip`, `group`, `raster_visibility`, `mandatory`, `order`, `privileg`, `query_tooltip`) VALUES (@last_layer_id102, 'id', 'id', 'q_notiz_kategorien', 'q_notiz_kategorien', 'int4', '', '', '1', '32', '0', '', 'Text', '', '', '', '', '', '', '', '', NULL, NULL, '0', '0', '0');
INSERT INTO layer_attributes (`layer_id`, `name`, `real_name`, `tablename`, `table_alias_name`, `type`, `geometrytype`, `constraints`, `nullable`, `length`, `decimal_length`, `default`, `form_element_type`, `options`, `alias`, `alias_low-german`, `alias_english`, `alias_polish`, `alias_vietnamese`, `tooltip`, `group`, `raster_visibility`, `mandatory`, `order`, `privileg`, `query_tooltip`) VALUES (@last_layer_id102, 'kategorie', 'kategorie', 'q_notiz_kategorien', 'q_notiz_kategorien', 'text', '', '', '1', NULL, NULL, '', 'Text', '', '', '', '', '', '', '', '', NULL, NULL, '2', '0', '0');
INSERT INTO layer_attributes (`layer_id`, `name`, `real_name`, `tablename`, `table_alias_name`, `type`, `geometrytype`, `constraints`, `nullable`, `length`, `decimal_length`, `default`, `form_element_type`, `options`, `alias`, `alias_low-german`, `alias_english`, `alias_polish`, `alias_vietnamese`, `tooltip`, `group`, `raster_visibility`, `mandatory`, `order`, `privileg`, `query_tooltip`) VALUES (@last_layer_id102, 'notiz', 'notiz', 'q_notizen', 'q_notizen', 'text', '', '', '1', NULL, NULL, '', 'Text', '', '', '', '', '', '', '', '', NULL, NULL, '1', '0', '0');
INSERT INTO layer_attributes (`layer_id`, `name`, `real_name`, `tablename`, `table_alias_name`, `type`, `geometrytype`, `constraints`, `nullable`, `length`, `decimal_length`, `default`, `form_element_type`, `options`, `alias`, `alias_low-german`, `alias_english`, `alias_polish`, `alias_vietnamese`, `tooltip`, `group`, `raster_visibility`, `mandatory`, `order`, `privileg`, `query_tooltip`) VALUES (@last_layer_id102, 'person', 'person', 'q_notizen', 'q_notizen', 'varchar', '', '', '1', '100', NULL, '', 'Text', '', '', '', '', '', '', '', '', NULL, NULL, '3', '0', '0');
INSERT INTO layer_attributes (`layer_id`, `name`, `real_name`, `tablename`, `table_alias_name`, `type`, `geometrytype`, `constraints`, `nullable`, `length`, `decimal_length`, `default`, `form_element_type`, `options`, `alias`, `alias_low-german`, `alias_english`, `alias_polish`, `alias_vietnamese`, `tooltip`, `group`, `raster_visibility`, `mandatory`, `order`, `privileg`, `query_tooltip`) VALUES (@last_layer_id102, 'the_geom', 'the_geom', 'q_notizen', 'q_notizen', 'geometry', 'GEOMETRY', '', '1', NULL, NULL, '', 'Text', '', '', '', '', '', '', '', '', NULL, NULL, '5', '0', '0');
INSERT INTO classes (`Name`, `Layer_ID`, `Expression`, `drawingorder`, `text`) VALUES ('', @last_layer_id102, '', '1', '');
SET @last_class_id=LAST_INSERT_ID();
INSERT INTO styles (`symbol`, `symbolname`, `size`, `color`, `backgroundcolor`, `outlinecolor`, `minsize`, `maxsize`, `angle`, `angleitem`, `antialias`, `width`, `minwidth`, `maxwidth`, `sizeitem`) VALUES (NULL, '', '1', '255 255 150', '', '000 000 000', NULL, NULL, '0', '', NULL, NULL, NULL, NULL, '');
SET @last_style_id=LAST_INSERT_ID();
INSERT INTO u_styles2classes (style_id, class_id, drawingorder) VALUES (@last_style_id, @last_class_id, 0);

Klicken Sie auf Notizen und legen eine neue Notiz an. Diese erscheint nach dem Absenden und dem aktiv schalten im Kartenfenster. Die zu definierende Textposition zeigt auf die Spitze des Bezugspfeils.

Image004.jpg

Wenn man Text in mehreren Zeilen haben möchte, muss man im Textfeld mit der Enter-Taste feste Zeilenumbrüche eingeben.

Image006.jpg

Wenn man eine Notiz ändern möchte macht man die Abfrageoption des Layers Notizen aktiv, wählt den Infoknopf und selektiert in der Karte die Notiz, die man ändern möchte. Dort kann man dann auf ändern klicken und kommt wieder in das Formular, welches zum anlegen neuer Notizen dient.

Image008.jpg

Kataster

Darstellung der ALKIS-Daten. Neben der Darstellung der Verwaltungseinheiten, Flurstücke, Gebäude und Nutzungsartenflächen werden zahlreiche weitere Themen aus ALKIS in Karten und Tabellenform angezeigt. Eine detaillierte Beschreibung welche Layer es gibt und wie diese definiert sind findet sich hier: Gruppen_und_Themen_für_ALKIS

Abgesehen davon, dass man jeden Layer über die Suchfunktion des GLE suchen kann, gibt es für die Suche nach Adressen, Flurstücken, Grundbuchblättern, Eigentümern und historischen Flurstücken spezielle Suchformulare in denen eine hierarchische Suche mit Auswahllisten unterstützt wird.

Die Fortführung des ALKIS-Datenbestandes erfolgt über die NAS Schnittstelle mit ogr2ogr in Anlehnung an die PostNAS Suite.

Für die Datenaufbereitung werden nutzerspezifische Skripte verwendet, die bei der Fortführung automatisch ausgeführt werden.

Flächenversiegelung

Erfassung und Darstellung von Versiegelungsflächen auf der Grundlage von Luftbildern

Aufbau des PHP-Skript

Die Anwendung ist so programmiert, dass alle Aufrufe über die Datei index.php erfolgen. Die Seiten, die der Benutzer im Browser angezeigt bekommt, werden zur Laufzeit durch den Server zusammengesetzt.

index.php

Die Datei index.php startet mit dem Einbinden einer Konfigurationsdatei config.php und einer Startdatei start.php, unterscheidet und verzweigt in Anwendungsfälle mit einer switch-Anweisung und endet mit einer Enddatei end.php. Zur Unterscheidung der Anwendungsfälle nutzt das Skript den Parameter $go und $go_plus. Wenn $go_plus einen Wert enthält, wird dieser an $go angehängt. Wenn $go leer ist, wird ein Standardfall ausgeführt. In den jeweiligen Anwendungsfällen (cases), werden die entsprechenden Funktionen der Benutzeroberfläche als Methoden der Klasse GUI der Klassenbibliothek kvwmap.php aufgerufen.

config.php

Die Konfigurationsdatei enthält verschiedene Voreinstellungen zur Konfiguration der Anwendung, die in den PHP-Dateien verwendet werden. Die Voreinstellungen werden über das Setzen von Konstanten realisiert. Die Konstanten sind thematisch in Gruppen zusammengefasst und umfassen z.B. Einstellungen zu Dateipfaden, Layout und WMS-Capabilities Metadaten. Des Weiteren wird in der Konfigurationsdatei eingestellt, welche Klassenbibliotheken geladen werden sollen und diese eingebunden. Dazu gehört auch die Bibliothek php_mapscript.so bzw. dll. Außerdem wird ein Debugdatei-Objekt $debug aus der Klasse debugfile der Klassenbibliothek kvwmap.php mit einem vorgegebenen Debuglevel eingestellt, und Datenbankobjekte für den Zugriff auf die Benutzer-, Karten- und Geometriedaten initialisiert.

start.php

In der Startdatei wird zunächst das Objekt für die Benutzeroberfläche initialisiert. Die Klasse GUI für die Benutzeroberfläche ist in der Klassenbibliothek kvwmap.php enthalten. Anschließend werden alle an das Skript übergebenen Variablen aus der PHP-Systemvariable $_REQUEST an das Objekt $GUI in das Array $formvars übergeben. Wird die PHP-Anwendung über CLI aufgerufen, werden die Argumente aus der Kommandozeile an $formvars übergeben. In start.php kann eingestellt werden, das wievielte Argument an welches Element von $formvars übergeben werden soll. In weiteren Schritten werden die Datenbankobjekte an $GUI übergeben und geöffnet. Zur Identifizierung des zugreifenden Benutzers wird die vom Web-Server bereitgestellte PHP-Konstante REDIRECT_REMOTE_USER verwendet. An Hand von $login_name werden aus der Benutzerdatenbank alle Benutzerdaten ausgelesen und dem Objekt $user aus der Klassenbibliothek user.php zugewiesen, incl. der von ihm zuletzt genutzten Stelle. Soll beim aktuellen Aufruf keine neue Stelle eingestellt werden, wird diese Stelle für den Benutzer verwendet, ansonsten neu gesetzt. Vor dem Erzeugen des Stellenobjektes wird geprüft, ob der Nutzer auf die Stelle zugreifen darf. Abschließend wird für den Benutzer die Stelle als Rolle gesetzt, ein Menü-Objekt in $GUI->Menue initiiert und das Menü für die Stelle geladen. Je nach Einstellungen erfolgen zwischendurch Ausgaben in die Debug-Datei.

end.php

In der Datei end.php werden die offenen Datenbankverbindungen und die Debug-Datei geschlossen.

kvwmap.php

In der Klasse GUI sollten alle Funktionen enthalten sein, die die Interaktion des Benutzers mit dem Programm betreffen. Einige allgemeine Funktionen, wie das Lesen der Karteninformationen aus der Datenbank übernimmt die Klasse GUI, andere fachspezifische Aufgaben werden durch separate Objekte übernommen. Das gilt vor allem für die Funktionen der Fachschalen.

kvmobile

Zur Erfassung, Verarbeitung und Präsentation von Geodaten aus kvwmap auf mobilen Endgeräten gibt es zwei Möglichkeiten.

Wenn auf dem mobilen Endgerät eine ständige mobile Internet-Verbindung oder WLAN-Verbindung verfügbar ist, kann kvwmap ganz normal im Browser verwendet werden. Das Layout ist jedoch nicht für kleinere Bildschirme optimiert. Gut Nutzbar wäre kvwmap im Browser nur auf Tabletts oder Laptops.

Um auch auf kleineren Endgeräten wie Handy's und auch ohne ständige Internet-Verbindung die Daten von kvwmap nutzen zu können bietet sich die APP kvmobile an.

Die APP wird als HTML-CSS-JavaScript Anwendung entwickelt. Der Source Code ist auf github verfügbar. Die APP und wird über Cordova für das Android Betriebssystem gebaut und als APK-Datei zum Download angeboten.

Serverseitig ist das kvwmap Plugin mobile erforderlich. Das Plugin ermöglicht das Arbeiten im Offline-Modus in kvmobile sowie die Synchronisierung von Geodaten und Fotos zwischen dem Server und dem mobilen Endgerät. An die Layer, die in kvmobile bearbeitet werden sollen, werden besondere Anforderungen gestellt, die in der Dokumentation zum Plugin beschrieben sind.

Die APP kvmobile verbindet sich über Benutzername und Passwort mit einer Stelle in einem kvwmap und stellt dem Nutzer die in der Stelle verfügbaren Layer mobile zur Verfügung. Ohne kvwmap funktioniert die APP also derzeit nicht. kvmobile muss sich erst mindestens ein mal mit dem Server verbunden haben um die dortigen Layer auf das Endgerät zu holen. Anschließend kann der Nutzer offline arbeiten. Erst wenn wieder Internet vorhanden ist können die Daten mit dem Server synchronisiert werden.

Für die Synchronisierung wird ein Versionierungskonzept mit uuid's und Deltas verwendet. Alle Daten haben eine eindeutige uuid und eine Versionsnummer pro Layer. Wenn kvmobile sich die Daten erstmalig holt, werden diese so wie sie sind in der sqlite Datenbank in kvmobile gespeichert. Werden Änderungen durchgeführt, egal ob auf Server oder Client werden die dazugehörigen SQL-Requests als sogenannte Deltas mit hochgezählter Versionsnummer gespeichert. Bei der Synchronisierung schickt kvmobile seine Deltas zum Server, die dort ausgeführt werden, und holt sich die Deltas vom Server die vom Zeitpunkt der letzten Synchronisierung bis jetzt angelegt wurden und führt diese auf dem Client aus. In der APP kvmobile wird die neue Version gesetzt, damit sie weiß bis zu welcher Änderungen die Deltas schon ausgeführt wurden.

Werden die selben Objekte von verschiedenen kvmobil APP's gleichzeitig bearbeitet, überschreibt immer die letzte Synchronisierung vorherige. Wenn die Abstände zwischen den Synchronisierungen größer sind, z.B. weil schlechtes Internet verfügbar ist, ist es also ratsam die Daten die bearbeitet werden sollen vorher in Bereiche für verschiedene Mitarbeiter aufzuteilen.

Installation

Es gibt verschiedene Wege für die Installation von kvwmap. Das hängt von der zur Verfügung stehenden Umgebung ab. Der Standardweg auf einem Root-Server ist die Installation von Docker Containern in denen die zugehörigen Komponenten voreingerichtet sind.

Die Installation der Container läuft über eine Script in wenigen Arbeitsschritten ab.

wget -O inithost.sh https://gdi-service.de/public/kvwmap_resources/inithost && \
chmod a+x inithost.sh && \
./inithost.sh

Die Voraussetzung ist ein Server mit Zugang zum Internet, Debian Betriebssystem und ein Root-Zugang. Die Hardwareausstattung richtet sich nach der Menge der Daten die verarbeitet werden sollen und den erforderlichen Datenverarbeitungsprozessen. Für ein normales Portal z.B. Schutzgebietskataster, Liegenschaftsauskunftssystem oder Flächenmanagementkataster reicht ein Server mit folgender Ausstattung:

  • AMD Ryzen 8700 oder Intel® Core i5-13500
  • Okta-Core CPU
  • 64 GB RAM
  • 2 x 512 GB Festplatte im RAID 1

Weitere teils aber schon veraltete Informationen zu Möglichkeiten die Umgebung zu installieren:

Da sich kvwmap frei in bestehende Systeme integrieren lässt gibt es auch keinen vorgegebenen Weg wie man die Anwendung installiert. Es kann sein, dass die Datenbanken schon existieren, dass es schon Datenbanknutzer gibt, dass schon ein Apache läuft oder auch vielleicht schon ein MapServer und die Postgis-Erweiterung. In solchen Fällen reicht es kvwmap als Web-Site zum Apache hinzuzufügen. Soll kvwmap erstmalig auf einem neuen Server eingesetzt werden, wird die Installation in einem Docker Container empfohlen. Das ist die einfachste und schnellste Variante und wird als Referenzinstallation gepflegt. Wer kvwmap in einem Docker Container laufen lässt kann sich über git nicht nur die jeweils neue Version von kvwmap holen, sondern auch die für kvwmap benötigten Softwarekomponenten vom dockerhub. Das kvwmap Image setzt auf Debian auf und nutzt die Images mdillon/postgis und mysql. Unterstützt der verwendete Server kein docker wird die Einrichtung unter einem Linux wie Debian oder Ubuntu empfohlen, weil hier viele Komponenten schon in den Repositories der Betriebssysteme bereitgestellt werden. Dennoch ist es etwas aufwendiger die einzelnen Komponenten zu installieren, zu konfigurieren und kvwmap so anzupassen, das es mit den Komponenten zusammenarbeiten kann. Da MapServer, Apache, MySQL und PostgreSQL auch unter Windows laufen kann auch kvwmap auf solchen einem Server betrieben werden. Nützlich zur Einrichtung der Komponenten sind hier Installer wie ms4w oder OSGeo4W. Ein einfacher WebServer und PostgreSQL reichen nicht aus. Es muss immer auch eine Unterstützung für phpMapScript und PostGIS vorhanden sein.

Eine Reihe zum Teil veralteter und nicht mehr gepflegter Installationsanweisungen findet man hier.

Voraussetzungen

In diesem Abschnitt wird eine Übersicht darüber gegeben, was alles für kvwmap installiert werden sollte bzw. aus welchen Komponenten die Anwendung besteht.

Folgende Komponenten werden für die Nutzung dieses Internet-GIS vorausgesetzt:

Serverseite

  • Apache - Es ist eine Version >= 2.0.48 eingesetzt worden, damit die Umgebungsvariable REDIRECT_REMOTE_USER genutzt werden kann. Diese wird zur Identifizierung des Nutzers verwendet. (siehe auch Apache bug-report)
  • Folgende Apache-Module werden von kvwmap verwendet und müssen daher vorhanden sein
    • authz_groupfile
    • cgi
    • headers
    • rewrite
    • ssl
    • proxy
    • proxy_http
    • proxy_html
    • xml2enc
  • PHP - Die Entwicklung von kvwmap läuft derzeit auf der Version 7
  • Folgende Module werden für kvwmap installiert und müssen daher vorhanden sein
    • php-cli
    • php-curl
    • php-dev
    • php-gd
    • php-mbstring
    • php-mysql
    • php-pgsql
    • php-soap
    • php-sqlite3
    • php-xsl
    • php-zip
  • Ob PHP richtig kompiliert wurde erkennen Sie durch die Ausgabe eines phpinfo() Befehls. Erzeugen Sie dazu eine Datei mit folgendem Inhalt in einem Verzeichnis unterhalb von wwwroot. oder fügen Sie dieses Programmschnipselchen in eine andere php Datei ein.
     <?php
       phpinfo();
     ?>

Die Funktion phpinfo zeigt dann an welche Module geladen sind.

PHP Version 4.3.10

System

Linux berg 2.6.5-7.97-smp #1 SMP Fri Jul 2 14:21:59 UTC 2004 x86_64

Build Date

Jul 20 2005 18:31:02

Configure Command

'./configure' '--enable-force-cgi-redirect' '--with-regex=system' '--enable-dbase' '--with-pgsql=/usr/local/pgsql' '--with-gd=/usr/local/gd'

Server API

CGI


In Configure Command sollte --with-pgsql=… stehen und weiter unten:

GD Support

enabled

GD Version

2.0 or higher

GIF Read Support

enabled

GIF Create Support

enabled

JPG Support

enabled

PNG Support

enabled

WBMP Support

enabled

mysql

MySQL Support

enabled

Active Persistent Links

0

Active Links

0

Client API version

3.23.49

MYSQL_MODULE_TYPE

builtin

MYSQL_SOCKET

/tmp/mysql.sock

MYSQL_INCLUDE

no value

MYSQL_LIBS

no value

pgsql

PostgreSQL Support

enabled

PostgreSQL(libpq) Version

8.0.1

Multibyte character support

enabled

SSL support

enabled

Active Persistent Links

0

Active Links

0

Directive

Local Value

Master Value

pgsql.allow_persistent

On

On

pgsql.auto_reset_persistent

Off

Off

pgsql.ignore_notice

Off

Off

pgsql.log_notice

Off

Off

pgsql.max_links

Unlimited

Unlimited

pgsql.max_persistent

Unlimited

Unlimited

Darin erkennt man ob MySQL, GD und PostgreSQL wirklich unterstützt werden und z.B. welche PostgresSQL-Version unterstützt wird.

Informationen zu Einstellungen von php findet man sonst auch in der php.ini Datei. Nach dem Kompilieren von PHP gegebenenfalls php.ini anpassen:

short_open_tag = On            - erlaubt den verkürzten Tag für php 
session.gc_maxlifetime = xxxx  - Länge der php-Session in Sekunden
  • gd - wenn die Druckrotation funktionieren soll, gd nicht selbst kompilieren, sondern PHP kompilieren mit --with-gd
  • MapServer - Version ab 7.x wird empfohlen
  • Folgende Einstellungen werden für die Kompilierung von MapServer verwendet:
    • -DWITH_PROTOBUFC=0
    • -DWITH_RSVG=1
    • -DWITH_CAIRO=1
    • -DWITH_SVGCAIRO=0
    • -DWITH_PHP=1
    • -DWITH_CLIENT_WMS=1
    • -DWITH_CLIENT_WFS=1
  • Folgende Funktionen muss MapServer dann erfüllen:
    • OUTPUT=PNG OUTPUT=JPEG SUPPORTS=PROJ SUPPORTS=AGG SUPPORTS=FREETYPE SUPPORTS=CAIRO SUPPORTS=SVG_SYMBOLS SUPPORTS=RSVG SUPPORTS=ICONV SUPPORTS=FRIBIDI SUPPORTS=WMS_SERVER SUPPORTS=WMS_CLIENT SUPPORTS=WFS_SERVER SUPPORTS=WFS_CLIENT SUPPORTS=WCS_SERVER SUPPORTS=FASTCGI SUPPORTS=GEOS SUPPORTS=POINT_Z_M INPUT=JPEG INPUT=POSTGIS INPUT=OGR INPUT=GDAL INPUT=SHAPEFILE
  • phpMapScript wird durch -DWITH_PHP mit MapServer installiert.
  • PDFClass ist Bestandteil von kvwmap
    Quelle: http://www.ros.co.nz/pdf/
  • Imagemagick und Ghostscript - zur Druckvorschau und Bildkonvertierung, siehe Installation von ImageMagick mit JPEG-, PNG- und TIF-Unterstützung ist im WebContainer enthalten und mit --with-rsvg=yes kompiliert.
  • MySQL – Unterstützung von InnoDB erforderlich.
  • phpMyAdmin
    Zur Administration der MySQL Datenbank kann phpMyAdmin installiert werden. Jedes andere DB-Frontend mit ODBC-Treiber für MySQL ist natürlich auch möglich. Ich benutze z.B. auch MS-Access mit MySQL-ODBC.
  • PostgreSQL - Version ab 9.0
    Zur Verwaltung von PostgreSQL setzten wir bei GDI-Service pgAdmin 4 ein. Es ginge aber auch phpPgAdmin wobei pgAdmin 4 schon etwas mächtiger ist. Voraussetzung hierfür ist eine Verbindung über TCP/IP über Port 5432 und die Freischaltung von Postgres für externe Zugriffe in postgres.conf und eventuell das Eintragen der eigenen IP in pg_hba.conf.
  • PostGIS - Version ab 1.5
    Die Verwaltung von Geometrie geht recht gut mit dem Desktop GIS QuantumGIS. Darin kann man direkt Tabellen mit PostGIS Geometrie als Layer einbinden um schnell mal was anzeigen zu lassen oder räumlich zu bearbeiten.

Clientseite

  • pgAdmin III
    Zur Administration von PostgreSQL würde ich pgAdminIII empfehlen, aber es geht natürlich auch pgMyAdmin oder andere DB-Frontends mit ODBC für MySQL, z.B. MS-Access
    Quelle: http://www.pgadmin.org
  • ODBC-Treiber für PostgreSQL
    Für den Zugang zum Server von einem lokalen Recher aus, muss der ODBC-Treiber für PostgreSQL installiert werden.
    Quelle: http://www.postgresql.org/ftp/odbc/versions
  • PostGIS – aktuellste Version mit der modifizierten shp2pgsql aus dem Ordner kvwmap/tools
  • EDBS2WKT
    Konverter zum Einlesen von ALK-Daten in die postgresql Datenbank.
    Quelle: http://62.153.231.87/alk/edbs2wkt
    Vor dem Einlesen von ALK-Daten in die PostGIS-Datenbank sollte eben PostgreSQL mit PostGIS unterstützung installiert sein.

UMN-MapServer

Hinweise zur Installation des UMN-MapServers finden Sie unter: http://mapserver.gis.umn.edu/docs

Siehe auch: http://wiki.osgeo.org/index.php/Installation_von_MapServer%2C_Apache_und_PostgreSQL/PostGIS_auf_Debian_4.0 http://en.giswiki.org/wiki/UMN_MapServer_Installationsanleitung_von_Kai_Behncke

UMN MapServer für Linux ist im Packet FGS und für Windows im Packet ms4w enthalten. Siehe dazu unter: http://www.maptools.org/fgs bzw. http://www.maptools.org/ms4w/

PostgreSQL mit PostGIS Erweiterung

PostgreSQL

Laden Sie sich PostgreSQL von http://www.postgresql.org

Zur Installation von PostgreSQL lesen Sie die INSTALL-Anweisung im Installationsverzeichnis von postgresql. Führen Sie aber zur Nutzung von Geos den configure Befehl folgendermaßen durch:

> LDFLAGS=-lstdc++ ./configure

an Stelle von einfach nur

> ./configure

Danach

> make

> make install

Zum Einrichten der Datenbank für kvwmap

> adduser postgres

Oft ist schon ein postgres user im system vorhanden, dann lassen.

Datenverzeichnis anlegen

> mkdir /usr/local/pgsql/data

Verzeichnis dem user postgres zuweisen

> chown postgres /usr/local/pgsql/data

Wechseln zum user postgres (als postgres anmelden)

> su – postgres

Datenbank initialisieren

> /usr/local/pgsql/bin/initdb -D /usr/local/pgsql/data

Postmaster starten. (Diese Zeile in Startskript von Rechner aufnehmen, sonst immer nach Neustart von Server neu starten)

> /usr/local/pgsql/bin/postmaster -D /usr/local/pgsql/data >logfile 2>&1 &

Kvwmap Datenbank anlegen.

> /usr/local/pgsql/bin/createdb <Datenbankname>

Als Datenbankname geben Sie den Namen an, den Sie in der config.php im kvwmap-Verzeichnis an die Variable $pgdbname übergeben haben. Z.B. kvwmapsp1-4-2

Zum Testen in Datenbank einloggen.

> /usr/local/pgsql/bin/psql kvwmapsp1-4-2

Alle Programme für postgres befinden sich in /usr/local/pgsql/bin.

Am besten den Pfad anpassen.

> export PATH=$PATH:/usr/local/pgsql/bin


Konfiguration:

Der Datenbankserver von PostgreSQL wird über die Datei postgres.conf konfiguriert. Diese Datei befindet sich im mit „initdb –D Verzeichnis“ angelegten data-Verzeichnis, z.B. in /usr/local/pgsql/data. Wenn was nicht funktioniert, kann man mal dort nachschauen, ob alles korrekt eingestellt ist. z.B. wenn der Zugang zur pgsql Datenbank von einem entfernten Rechner aus mit pgAminIII nicht funktioniert liegt das entweder daran, dass die Firewall den Port 5432 nicht frei gibt, oder die Verbindungen nur vom localhost erlaubt sind. Das kann man mit dem Parameter listen_addresses einstellen in der postgres.conf. Für den Zugriff von entfernten Rechner muss für Postgres der Port 5432 offen sein (entsprechend /etc/services). In /etc/hosts sollte der Rechner eingetragen sein, der zugreifen will. In /etc/hosts.allowed können auch Zugangsbeschränkungen eingetragen werden.


Projektdatenbank: Zur Einbindung von ALK-Daten in eine PostGIS-Datenbank sollte mit EDBS2WKT zunächst eine Datenbank neu erstellt werden, die die Tabellen für die ALK-Objekte enthält. Damit man diese Postgres-Datenbank dann mit kvwmap zusammen nutzen kann, muss man das Skript postgis_install.sql aus dem Verzeichnis /layouts/sql_dump von kvwmap in postgres ausführen. Danach sollten alle relevanten Tabellen in der Datenbank enthalten sein.

PROJ

Wenn Sie PROJ noch nicht für UMN-MapServer installiert haben, laden Sie sich PROJ von http://www.remotesensing.org:16080/proj

Entpacken von proj-version.tar.gz nach /usr/local

Erzeugen eines symbolischen Links:

  1. ln –s proj-version proj

Installieren mit:

  1. ./configure
  1. make
  1. make install

GEOS

Laden Sie sich GEOS von http://geos.refractions.net

Entpachen von geos-version.tar.gz nach /usr/local

Erzeugen eines symbolischen Links:

  1. ln –s geos-version geos

Installieren mit

  1. ./configure
  1. make
  1. make install

PostGIS

Man muss den PostgreSQL Source haben und PostgreSQL installiert haben.

Laden Sie sich PostGIS von http://postgis.refractions.net

Folgen Sie der Installationsanleitung in README.postgis

Zur Aktivierung der PROJ und GEOS Unterstützung in Makefile.config USE_PROJ und USE_GEOS auf 1 setzen und als Pfade /usr/local angeben.

Installieren mit: make -> make install

Zur Einrichtung der PostGIS Erweiterung für die kvwmap Datenbank:

  1. createlang plpgsql <Datenbankname>
  1. psql -f lwpostgis.sql -d <Datenbankname>

Als Datenbankname geben Sie den Namen an, den Sie in der config.php im kvwmap-Verzeichnis an die Variable $pgdbname übergeben haben. Z.B. kvwmapsp1-4-2

Anlegen der Tabellen für die Koordinatensysteme

  1. pgsql –f spatial_ref_sys.sql

Es muss auch ein Benutzer angelegt sein, mit dem Sie von kvwmap aus auf die Datenbank zugreifen. Nutzer hinzufügen:

  1. createuser –P <Benutzername>

<Benutzername> ist der Name unter dem Sie auf die Datenbank von kvwmap aus zugreifen, z.B. kvwmap Anschließend werden Sie nach einem Passwort <Passwort> für den Nutzer gefragt. Der hier angegebene Name bzw. Passwort wird dann in der config.php im kvwmap Verzeichnis auf die Variable $PostGISdb->user=’<Benutzername’ bzw. $PostGISdb->passwd='<Passwort>' gesetzt. 2.3.5 Datenbank Sichern und Wiederherstellen

Eine PostGIS Datenbank lässt sich mit dem pg_dump Befehl sichern. Dabei wird eine sql-Datei erzeugt, die später zur Wiederherstellung eines alten Standes verwendet werden kann. Um die Sicherung ausführen zu können melden Sie sich am Besten auf Ihrer Konsole als postgres an.

  1. su postgres

Anschließend wechseln Sie in ein Verzeichnis, in dem postges Schreibrechte hat, z.B.

  1. cd /usr/local/pgsql/data

Dort führen sie den dump Befehl aus.

  1. ../bin/pg_dump -f <dateinamedersicherung.sql> <datenbankname>

Zum wiederherstellen müssen Sie die alte Datenbank löschen.

  1. dropdb <datenbankname>

Anschließend legt man die Datenbank wieder an, fügt den PostGIS Support und die Referenzsystem hinzu und läd dann die Sicherung ein.

  1. createdb <datenbankname>
  1. createlang plpgsql <datenbankname>
  1. psql -f postgis.sql -d <datenbankname>
  1. psql –f spatial_ref_sys.sql –d <datenbankname>
  1. psql -f <dateinamedersicherung.sql> -d <datenbankname>
  1. vacuumdb -z <datenbankname>

Die Dateien postgis.sql und spatial_ref_sys.sql befinden sich in dem share Verzeichnis des pgsql Verzeichnisses. Die letzte Zeile dient dem Auffrischen der Tabellen und der Neuorganisation der Indizee und des Speicherplatzes.

MySQL

Installieren Sie auf Ihrem System einen MySQL Server. Folgen Sie den Installationsanleitungen unter: http://dev.mysql.com/doc/index.html Führen Sie zum einrichten der der kvwmap-Tabellen die Datei mysql_install.sql aus dem Verzeichnis /layouts/sql_dump

Schritte zur Installation von kvwmap

Um kvwmap nutzen zu können müssen die oben beschriebenen Komponenten installiert sein.

Nachfolgend werden die Schritte beschrieben, die absolviert werden sollten, damit man im Client eine Karte sehen kann. Dazu gehören einige Einstellung die den Server betreffen. Diese werden in der Datei config.php vorgenommen. Die meißten Einstellungen werden über Konstanten vorgenommen. Wenn noch Einstellungen vorgenommen werden müssen, die irgentwo anders im Quellcode fest verankert sind lassen Sie es mich wissen, dann baue ich das auch als Konstane in die config.php ein.

Und es sind eine Reihe von Eintragungen in der MySQL-Datenbank vorzunehmen, z.B. das Anlegen einer Steller, Benutzer, Layer, Menüpunkte etc.

Verzeichnisse

  • Entpachen sie das Packet kvwmap_Version in das www-root
  • In www-root (z.B. /usr/local/httpd/htdocs) sollten folgende zusätzlichen Verzeichnisse angelegt werden:
  • /tmp – für die dynamisch generierten Bilder vom MapServer. Dies ist der Pfad der in der MapDatei für IMAGEPATH steht.
  • Auf der gleichen Ebene wie www-root (z.B. /usr/local/httpd) sollten folgende Verzeichnisse angelegt werden.
  • /logs – Log- und Debugdateien lässt sich in config.php ändern
  • /var – Datenverzeichnis, lässt sich auch in config.php anpassen.
  • Unter dem Verzeichniss var legen sie standardmäßig /data an und darunter die Verzeichnisse für Ihre Daten

config.php

Die Datei config.php wird jedes Mal beim Speichern der Administrationseinstellungen (go=Administratorfunktionen) an Hand der dort eingestellten und in der MySQL-Tabelle config gespeicherten Daten übergeschrieben!

Konstanten.png

Die Konstanten sind in Gruppen aufgeteilt und für ausgewählte Plugins getrennt aufgeführt. Die Bedeutung der Konstanten ist in den meisten Fällen hinter der "i"-Schaltfläche hinterlegt.

Datenbankeinträge für die Anzeige im Client

Um in der Benutzeroberfläche des kvwmap-Clients überhaupt etwas sehen zu können, müssen mindestens eine Stelle und ein Benutzer eingetragen werden und ein Layer angelegt sein. Eine Beschreibung zur Verwaltung von Benutzerdaten und Karteninformationen finden Sie unter Abschnitt 5.

Installation mit ms4w

Hier wird die Installation von kvwmap unter MapServer for Windows (MS4W) beschrieben.

Die nachfolgende Beschreibung bezieht sich auf die Installation unter Windows 7 auf einem Feldrechner (Panasonic Toughpad)
um kvwmap lokal und ohne Internetanbindung im Außendienst nutzen zu können.


Folgendes wird benötigt:


Die MS4W-Pakete ab Version 3.1.0-beta4 und neuer können nicht benutzt werden, da sie den MapServer 7 verwenden, mit dem die verwendete Version von kvwmap nicht kompatibel ist.
Außerdem gilt die PHP-Extension ext/mysql seit Version 5.5 als veraltet und ist dann auch im MS4W-Paket nicht mehr enthalten. Version 7.0 wird ext/mysql dann garnicht mehr unterstützen. Als Ersatz dient ext/mysqli oder ext/pdo_mysql, um die zu nutzen müsste man allerdings die class/mysql.php umschreiben.
MapServer for Windows 3.0.6 ist die letzte Version von MS4W, die keine Beta ist, sowie den Mapserver 6 und PHP 5.4 verwendet.


Installation von MS4W (3.0.6)

  • Zipdatei an einem beliebigen Ort entpacken
  • apache-install.bat ausführen (möglichst mit Adminrechten, bei Problemen die Befehlszeilen aus der .bat per Hand in cmd eingeben)
  • unter C:/Windows/system32/drivers/etc die hosts-Datei öffnen und folgendes eintragen (wenn noch nicht vorhanden):
    • 127.0.0.1 localhost (meistens ist der Eintrag schon vorhanden und man muss nur das # vorne entfehrnen)
  • den Browser öffnen und in der Adresszeile localhost eingeben
    • wenn der Apache korrekt läuft, sollte die Informationsseite von MS4W jetzt angezeigt werden


Installation MySQL, phpMyAdmin, PostgreSQL und PostGIS

MySQL

  • bei der Installation MySQL muss InnoDB als Storage Engine ausgewählt werden
  • ansonsten typische Installation / Standartkonfiguration
  • Pfad des bin-Verzeichnisses in der PATH-Umgebungsvariable eintragen lassen
  • nach der Installation kann man mit cmd testen ob MySQL läuft:
    • mysql -u root -h localhost -p
    • Passwort eingeben
    • use mysql
    • show tables

phpMyAdmin

  • phpMyAdmin wird unter ms4w/apps/phpMyAdmin installiert
  • danach wird unter ms4w/http.d eine Datei httpd_phpMyAdmin.conf erstellt, mit folgendem Inhalt:
 Alias /phpMyAdmin/ "/ms4w/apps/phpMyAdmin"
 <Directory "/ms4w/apps/phpMyAdmin">
   AllowOverride None
   Options Indexes FollowSymLinks Multiviews
   Order allow,deny
   Allow from all
 </Directory >
  • den Apache mit der apache-restart.bat neu starten
  • im Brower localhost/phpMyAdmin/index.php öffnen und die Verbindung zur MySQL-Datenbank prüfen

PostgreSQL, PostGIS

  • bei der Installation ODBC und pgAdmin mit anwählen
  • nach Abschluss der Installation von PostgreSQL öffnet sich der PostreSQL StackBuilder, mit dem man PostGIS und andere Erweiterungen installieren kann
  • in PgAdmin einen neuen Benutzer anlegen mit dem Namen kvwmap und dem Passwort kvwmap als Superuser
  • postgis template anlegen


Installation von kvwmap


Vorbereitungen

  • kvwmap in das Verzeichnis ms4w/apps entpacken bzw. clonen
  • das Verzeichnis in kvwmap umbenennen, falls es nicht schon so heisst
  • im Verzeichnis ms4w/http.d zwei neue conf-Dateien anlegen
    • httpd_kvwmap.conf
 Alias /kvwmap/ "/ms4w/apps/kvwmap"
 <Directory "/ms4w/apps/kvwmap">
   AllowOverride None
   Options Indexes FollowSymLinks Multiviews
   Order allow,deny
   Allow from all
 </Directory >  
    • httpd_mapserver.conf
 Alias /tmp/ "/ms4w/tmp"
 <Directory "/ms4w/tmp">
   AllowOverride None
   Options Indexes FollowSymLinks Multiviews
   Order allow,deny
   Allow from all
 </Directory >
  • im Verzeichns ms4w die Verzeichnisse data, logs und tmp anlegen
  • in ms4w/data ein Verzeichnis mapfiles anlegen und dort eine neue Datei defaultmapfile.map mit folgendem Inhalt anlegen
 MAP
  OUTPUTFORMAT
    NAME jpeg
    MIMETYPE image/jpeg
    DRIVER AGG/JPEG
    EXTENSION jpg
    IMAGEMODE RGB
    TRANSPARENT FALSE
    FORMATOPTION "QUALITY=80"
  END
  OUTPUTFORMAT
    NAME png
    MIMETYPE image/png
    DRIVER AGG/PNG
    EXTENSION png
    IMAGEMODE RGB
    FORMATOPTION "INTERLACE=OFF"
  END
  OUTPUTFORMAT
    NAME png
    MIMETYPE image/png
    DRIVER AGG/PNG
    EXTENSION png
    IMAGEMODE PC256
    TRANSPARENT ON
  END
  OUTPUTFORMAT
    NAME PNG24
    DRIVER "AGG/PNG"
    MIMETYPE "image/png"
    EXTENSION PNG
    IMAGEMODE RGBA
    TRANSPARENT ON
  END
  OUTPUTFORMAT
    NAME jpeg_print
    MIMETYPE image/jpeg
    DRIVER AGG/JPEG
    EXTENSION jpg
    IMAGEMODE RGB
    TRANSPARENT FALSE
    FORMATOPTION "QUALITY=100"
  END
END
  • danach den Apache mit der apache-restart.bat neu starten

config-default.php bearbeiten

  • folgt

install.php bearbeiten

  • folgt

refrencemap zuweisen

  • folgt

Installation mit fgs

Hier wird die Installation von kvwmap in der Free OpenSource GIS Suite (fgs) beschrieben.

Voraussetzung ist das aktuelle Packet von fgs, download unter: http://dl.maptools.org/dl/fgs/releases/1.0/1.0.0/self-installers/

--Markus Hentschel 16:53, 25. Jul 2007 (CEST)
Vorteil FGS: sehr leichte Installation, leichte Nachinstallation von weiteren Komponenten.
Nachteil FGS: einige Funktionalitäten gehen nicht, weil alle Komponenten vorkompiliert sind und nicht geändert werden können. Beispiel: Druck rotieren geht nicht. Bei Mapserver < 5.0: Mapserver ist mit den Standardeinstellungen der map.h und mapsymbol.h kompiliert, z.B. MS_MAXIMAGESIZE_DEFAULT=2048 oder MS_MAXSYMBOLS=64 (In der neuesten FGS-Version 1.0 nicht mehr nötig).
--Pkorduan 14:09, 28. Okt 2007 (CET)
Weiterer Nachteil bei Version 0.2: Das Modul postgis-lib:1.0.6 ist ohne proj Unterstützung kompiliert. Selbst von das proj-lib Modul für fgs installiert ist, kann postgis trotzdem keine transformationen rechnen. Der SQL Befehl transform() funktioniert nicht und somit auch keine Koordinatentransformationen mit PostGIS on-the-fly. (Hat nichts mit MapServer zu tun. Der transformiert fleißig mit Proj) Wenn man kvwmap mit Layern in unterschiedlichen EPSG-Codes verwenden möchte, dann muss PostGIS transformieren können. Der Parameter USE_PROJ=1 muss für postgis gesetzt sein. Man muss also in dem Fall postgis für fgs neu kompilieren (In der neuesten FGS-Version 1.0 nicht mehr nötig).

Zum Installieren von FGS bzw. von Modulen innerhalb der FGS-Umgebung siehe auch drei HowTo's:



Docker Network

In diesem Abschnitt wird beschrieben wie das Netzwerk der von kvwmap genutzten Docker-Containern aufgebaut ist, wie man die darin befindlichen Container verwalten kann und wo die zugehörigen Daten zur Verwendung im GIS und für die Administration der Anwendung liegen. siehe Präsentation docker-network.pdf

Netzwerkarchitektur

Netzwerk-Architektur

Administration

Die Administrationsoberfläche

Die Administrationsoberfläche kann über "go=Administratorfunktionen" aufgerufen werden. Hier findet man verschiedene Funktionen, die die Administration von kvwmap vereinfachen.

Administratorfunktionen

Aktualisierung des Quellcodes per git

Bei der Entwicklung von kvwmap wird die Versionsverwaltungssoftware git verwendet. Auf https://github.com/srahn/kvwmap wird die Entwicklung gehostet. Auch wenn man nicht selber an der Entwicklung teilnimmt, kann man git nutzen, um damit den Quellcode des eigenen kvwmap auf Knopfdruck zu aktualisieren.

Es ist empfehlenswert, sich vor der Einrichtung dieser Funktionalität zu entscheiden, ob man kvwmap in der stabilen Releaseversion (branch: kvwmap) oder in der Entwicklungsversion (branch: develop) betreiben möchte. Bei der Verwendung der Releaseversion umfasst die Aktualisierung des Quellcodes nur das Einspielen der Bugfixes. Bei der Entwicklungsversion werden Bugfixes und neue Funktionalitäten eingespielt.

Voraussetzungen:

  • git muss auf dem eigenen Server installiert sein
  • der kvwmap-Ordner muss ein git-Repository sein:
Ein solches Repository wird folgendermaßen erstellt: In dem Verzeichnis, in dem der kvwmap-Ordner liegen soll, führt man diesen Befehl aus:
git clone -b <branch> https://github.com/srahn/kvwmap <kvwmap-Ordner>
<branch> muss dabei durch "kvwmap" oder "develop" ersetzt werden und <kvwmap-Ordner> durch den gewünschten Ordnernamen von kvwmap.
Die aktuelle Version von kvwmap wird nun von github heruntergeladen und unter dem ausgewählten Ordner abgelegt.
Jetzt muss man dieses kvwmap noch lauffähig machen, indem man seine config.php und den custom-Ordner erstellt oder von einem bestehenden kvwmap hineinkopiert. Die credentials.php muss gegebenenfalls angepasst werden.
  • der Apache-Nutzer muss das Recht haben, git auszuführen und zwar als der Nutzer, der das Repository angelegt hat
Dazu muss die Datei /etc/sudoers editiert werden und zwar als root mit dem Befehl "visudo". Hier fügt man dann z.B. eine Zeile in folgender Form hinzu:
www-data        ALL=(fgs) NOPASSWD: /usr/bin/git
In diesem Beispiel heißt der Apache-Nutzer "www-data", der Nutzer, der das Repository angelegt hat, heißt "fgs" und der Pfad zum git lautet "/usr/bin/git".
  • in der config.php muss die Konstante "GIT_USER" auf den Nutzer gesetzt sein, der das Repository angelegt hat

Wenn alle Voraussetzungen erfüllt sind, erscheint in der Administrationsoberfläche ein Modul "Aktualisierung des Quellcodes". Hier wird der Status des eigenen Quellcodes angezeigt, indem mit dem Stand auf github verglichen wird. Falls der Status nicht aktuell ist, wird die Anzahl der neuen commits auf github angezeigt und man kann auf "aktualisieren" klicken um die Änderungen einzuspielen.

update code.PNG

Konfigurationsparameter

In diesem Modul können alle Einstellungen zur Konfiguration der Anwendung eingestellt werden. Die Werte werden in diesem Formular geändert und beim Speichern sowohl in die MySQL-Datenbanktabelle config gespeichert als auch in der Datei config.php. Wenn die Parameter gespeichert werden, wirken sie sich erst beim nächsten Aufruf der Anwendung aus, weil die Parameter von der Anwendung nicht zur Laufzeit aus der Datenbank gelesen werden sondern aus Performancegründen aus der Datei config.php. Die config.php ist sozusagen nur ein Cache der Parameter aus der Tabelle config. Wenn Einstellungen in der config.php geändert werden, gelten diese nur solange bis die Konfigurationsparameter das nächste mal gespeichert und damit die config.php überschrieben wird. Die Parameter sind in die folgenden Punkte untergliedert:

  • Administration
  • Datenbanken
  • E-Mail Einstellungen
  • Layer-IDs
  • Layout
  • Logging
  • OWS-METADATEN
  • Pfadeinstellungen
  • z CSW-Metadatensystem

Hinweise zu den einzelnen Parametern können durch Überfahren des i-Buttons mit der Maus angezeigt werden.

Konfigurationsparameter > Administration

Admin-Stellen

Die Möglichkeiten zur Verwaltung von Stellen, Menüs, Funktionen, Layergruppen, Layern und Nutzern stehen in Stellen zur Verfügung, wenn die entsprechenden Menüpunkte in der entsprechenden Stelle zugeordnet sind und die Stelle in dem Konfigurationsparameter admin_stellen als Administratorstelle registriert ist.

Parameter admin_stellen

Sind die Menüpunkte zu Stellen zugeordnet, die nicht als Administratorstellen eingetragen sind, können nur Stellen, Menüs, Funktionen, Layergruppen, Layern und Nutzer verwaltet werden, die der aktuell angemeldete Nutzer sehen kann. Also alle Objekte, die in den Stellen zugeordnet sind in denen der aktuelle Nutzer Zugang hat.

Unteradmin-Stellen

Die Zuordnung von Stellen zu Admin-Stellen kann dazu genutzt werden Unteradministratoren einzurichten. Jeder Nutzer, der in einer Stelle angemeldet ist, die nicht Admin-Stelle ist, aber Menüpunkte mit Verwaltungsfunktionen, wie Nutzerverwaltung, Stellenverwaltung etc. hat, kann die Objekte verwalten, die in seinen Stellen enthalten sind.

Soll ein Unter-Admin U z.B. nur 2 Stellen (S1 und S2), verwalten, legt man als Ober-Admin in einer Admin-Stelle die beiden Stellen S1 und S2 an und ordnet alles hinzu was man für nötig hält, z.B. Layer L1 und L2 und Menüs M1 und M2 (keine Adminmenüs). Zusätzlich richtet man eine Stelle SA ein und ordnet den Unter-Admin U zu S1, S2 und SA zu sowie die Stellen und Nutzerverwaltung als Verwaltungsmenüpunkte in SA. Meldet sich U nun in SA an, kann er die Stellen SA, S1 und S2 sehen und darin z.B. S1 den Menüpunkt M1 wegnehmen.

Auf folgende wichtige Dinge sei hingewiesen:

  • Wird in der Unteradmin-Stelle ein Objekt aus allen Stellen entfernt, die die Unteradminstelle sehen kann, kann dieses Objekt nur wieder durch einen Oberadmin in einer Oberadminstelle der Unteradminstelle zugeordnet werden in dem das Objekt einer Stelle zugeordnet wird, die der Unteradmin sehen kann.
  • Die Unteradminstellen sollen keine Menüpunkte zum Anlegen von Objekten zugeordnet bekommen und auch keine benutzen, weil neu angelegte Objekte, z.b. neue Layer nach dem Speichern noch keiner Stelle gehören. Der Unteradmin könnte also nach dem Anlegen von Objekten die neuen Objekte nicht sehen. Diese Funktion kommt in einer nächsten Version von kvwmap.
  • Es sind noch nicht alle Anwendungsfälle bezüglich des Filters abgedeckt. Ist einem Unteradmin z.B. ein Menüpunkt zugeordnet zum Ändern der Menüpunkte, kann er durch Ändern von selected_menue_id auch Menüs ändern, die nicht zu seinen Stellen gehören. Es ist also ratsam bisher nur die Menüpunkte Stellen_Anzeigen und Nutzer_Anzeigen solchen Unteradminstellen zuzuordnen. Bisher werden nur folgende Anwendungsfälle geschützt.
    • als_nutzer_anmelden
    • Stelleneditor
    • Stelle_Löschen
    • Benutzerdaten_Formular
    • Benutzer_Löschen
  • Eine Ausnahme gibt es. Der Unteradmin kann in der Unteradminstelle neue Nutzer einladen und den Stellen, die der Unteradmin sieht zuordnen und auch anschließend verwalten. Damit ist zumindest die Nutzerverwaltung in Gruppenzuständigkeit möglich, was auch der Anlass für die Filterung der Verwaltungsfunktionen war.

Stelle

Stelle anlegen

Zum Anlegen einer neuen Stelle kann der Menüpunkt „Stelle Anlegen“ aus der Menügruppe „Stellenverwaltung“ verwendet werden.

Das Formular ist in folgende Gruppen unterteilt:

  • Stammdaten
  • Zuordnungen
  • Metadaten
  • Sonstiges

Die Gruppe Metadaten ist defaultmäßig zugeklappt.

Gruppen im Stelleneditor

In der Gruppe Stammdaten können folgende Einstellungen für die Stelle vorgenommen werden: Bezeichnung, Referenzkarte, maximale Ausdehnung, EPSG-Code (der zur maximalen Ausdehnung passt), eine Datenbankverbindung, eine Wappendatei und ein Wappen-Link Für Referenzkarten wird eine Auswahlliste angeboten. Soll eine Referenzkarte für die Stelle verwendet werden, die noch nicht in der Auswahl erscheint, ist zuvor eine neue Referenzkarte in der MariaDB-Tabelle referenzkarten zu registrieren. Die Datei mit der Referenzkarte ist in dem Verzeichis zu hinterlegen, welches in der Konstante REFERENCEMAPPATH angegeben ist.

Die maximale Ausdehnung ist in dem EPSG-Code anzugeben, der bei EPSG-Code eingetragen ist. x ist der Rechtswert und y der Hochwert. Damit werden die Koordinaten in der Reihenfolge West, Süd, Ost, Nord angegeben.

Stelleneditor Stammdaten

In der Gruppe Zuordnungen können der Stelle folgende Dinge zugeordnet werden:

  • Menüpunkte
  • Funktionen
  • Kartendruck-Layouts
  • Datendruck-Layouts
  • Layer
  • Benutzer
  • Übergeordnete Stellen
  • Untergeordnete Stellen

Die Zuordnung erfolgt jeweils durch Selektion ein oder mehrerer Werte in der rechten Box (verfügbare) und klicken auf den Doppelpfeil der nach links zeigt. Die Boxen für verfügbare Menüpunkte und Layer sind zweigeteilt. Im obigen Teil kann eine ganze Gruppe ausgewählt werden. Sind in der Gruppe einzelne Menüpunkte bzw. Layer enthalten, können im unteren Teil der Box einzelne für die Übernahme ausgewählt werden.

Eine Zuordnung kann aufgehoben werden durch Selektion ein oder mehrerer Werte in der linken Box (zugeordnete) und klicken auf den Doppelpfeil der nach rechts zeigt.

Die Zuordnungen sowie auch alle anderen Änderungen im Formular werden erst wirksam wenn das Formular gespeichert wird.

Eine Funktion muss nur zugeordnet werden, wenn die Funktion nicht schon in zugeordneten Menüpunkten aufgerufen wird.

Die Zuordnung von über- zu untergeordneten Stellen muss zueinander passen.

Zuordnungen Teil 1

Zuordnungen Teil 2

Zuordnungen Teil 3

In der Gruppe Metadaten können Beschreibungen angeben werden, die für die Veröffentlichung von Diensten (Capabilities) und in Datensatz-Metadaten Verwendung finden. Die Daten können auch für die interne Beschreibung von Stellen in kvwmap verwendet werden.

Die zur Stelle gehörenden Metadaten lassen sich in jeder Stelle gesondert bearbeiten, wenn es in der Stelle einen Menüpunkt mit dem Anwendungsfall Dienstmetadaten (index.php?go=Dienstmetadaten) gibt. Damit können Nutzer einer Stelle die Metadaten der Stelle selber pflegen. Das Formular ist aufgeteilt in allgemeine Metadaten wie Titel, Kurzbeschreibung, Zugangsbeschränkung, Kosten und Referenzsystem den Angaben über die Stelle, die für die Metadaten verantwortlich sowie die Stellen, die verantwortlich sind für die Inhalte und die Veröffentlichung. Die Metadatenelemente, die in INSPIRE- und ISO-konformen Metadatendokumenten Pflicht sind, sind mit * gekennzeichnet.

Allgemeine Metadaten und Verantwortlicher für die Metadaten

Kontakt zum Verantwortlichen über den Inhalt der Geodaten

Kontakt zum Verantwortlichen für den Vertrieb der Daten

In der Gruppe Sonstiges können die folgenden Parameter eingestellt werden:

  • Wird ein Standardnutzer für die Stelle ausgewählt, werden dessen Rolleneinstellungen für alle Nutzer initial übernommen, wenn die Nutzer dieser Stelle neu zugewiesen werden, es sei den es handelt sich bei der Zuweisung um den Standardnutzer selbst, denn sonst könnte man dem Standardnutzer niemals andere Einstellungen zuordnen als die, die er schon hat.
  • ob durch andere freigegebene Layer in dieser Stelle angezeigt werden können sollen.
  • IP-Adresse des Nutzers überprüfen. Wenn das eingestellt ist, können Nutzer nur auf die Stelle zugreifen, wenn die IP-Adresse von der der Nutzer aus zugreift beim Nutzer eingetragen ist. Siehe Nutzerverwaltung
  • Alter von Passwörtern in dieser Stelle prüfen.
  • Erlaubtes Alter von Passwörtern, wenn es geprüft wird (in Monaten)
  • Layer-Aliasnamen verwenden
  • historische Zeitstempel zulassen
  • Kommentar welcher für Hinweise gedacht ist, die ein oder mehrere Administratoren verwalten.

Stelleneditor, sonstige Angaben

Stellen anzeigen

Über den Menüpunkt Stellen anzeigen der Menügruppe Stellenverwaltung können Stellen gelistet und sortiert werden. Zu jeder Stelle gibt es Links zum Stelleneditor (siehe Stelle anlegen), den zur Stelle zugeordneten Layern (siehe stellenbezogene Layereigenschaften und zum Löschen der Stelle.

Button in der Stellenanzeige.

Stellen ändern

Zur Änderung von Stellen siehe Stelle anlegen.

Maximale Ausdehnung des Kartenfensters für eine Stelle ändern

Die Koordinaten für die maximale Ausdehnung des Kartenfensters einer Stelle läßt sich über die Angaben zu minxmax, minymax, maxxmax, maxymax in der

Tabelle stelle in der Zeile der entsprechenden Stelle ändern.

Neben der maximalen Ausdehnung kann über das Setzen von Filtern (siehe Tabelle 'used_layer' -> Filter) der Inhalt von Layern, dessen Objekte in der

PostgreSQL-Datenbank gehalten werden, stellenbezogen weiter eingeschränkt werden.

Einschränkung der Stellen bezüglich Inhalt des Kartenfensters und entsprechender räumlicher Anfragen, die mittels Raumbezug (Polygon) zuvor festgelegt

werden können, befindet sich z.Z. in der Entwicklung und wird in der nächsten Version zur Verfügung stehen!

Filterverwaltung

Die Filterverwaltung ermöglicht nicht nur das stellenbezogene räumliche bzw. inhaltliche Einzuschränken von Layern, sondern auch deren Sachdaten. Dazu wählt man den Menüpunkt „Filterverwaltung“ (go-Variable: "Filterverwaltung").

Es werden nur Layer berücksichtigt, die einen Data-Eintrag haben. Damit auch ein reiner MS-Query-Layer filterbar ist, bekommt er im DATA eine Pseudo-Geometrie:

geom from (select oid, *, st_geometryfromtext('POINT(0 0)', 25833) as geom
from public.antraege) as foo ...

Hier wird als nächsten Schritt die entsprechende Stelle und dann der betroffene Layer mit Hilfe der Auswahllisten gewählt. Damit wird eine Liste von Attributen geladen, über die der Layer eingeschränkt werden kann. Wichtig: Jedes Attribut, das in der Filterverwaltung geladen werden soll, muss im DATA-Statement des Layers eingetragen sein. Filterverwaltung.jpg

Zu jedem Attribut kann jetzt ein Wert festgelegt werden, um den der Layer eingeschränkt werden soll. Mit den Operatoren lassen sich die Einschränkungen noch flexibler gestallten, wie in den folgenden Beispielen gezeigt wird:

Filter1.jpg

1. In diesem Beispiel werden nur Informationen vom Layer ausgegeben, die den Wert „132100“ im Attribut „gemkgschl“ aufweisen.

Filter2.jpg

2. Wie in diesem Beispiel können den Werten auch Platzhalter hinzugefügt werden. Hier werden all Layerinformationen ausgegeben, die im Attribut „gemkgschl“ mit dem Wert „1321“ beginnen. Platzhalter lässt sich beliebig verschieben.

Ist einem Layer eine Geometrie zugeordnet, wird in der Liste der Attribute „the_geom“ geladen. In dem Fall ist es möglich die Einschränkung zum Layer räumlich durch ein Polygon festzulegen (Das gilt natürlich nicht für die o.a. MS_Query-Layer mit Dummy-Geometrie). Dazu setzt man das Häkchen bei „Polygon“ und legt im Anschluss das Polygon im Kartenfenster fest. Als Operator kann man zwischen „Intersects“ oder „Within“ wählen. „Intersects“ schränkt die Objekte des Layers räumlich so ein, dass alle Objekte die vom Polygon geschnitten oder innerhalb des Polygons liegen abfragbar sind und dargestellt werden. Der „Within“-Operator stellt dabei nur die Objekte dar, die zu 100% innerhalb des Polygons liegen.

Als letzter Schritt müssen die Einstellungen noch mit dem „Speichern“-Button gesendet bzw. gespeichert werden.

Um die Einschränkungen eines Layer zu ändern, löscht man die entsprechenden Werte zu den Attributen oder ersetzt diese durch neue Werte. Im Falle einer räumlichen Einschränkung durch ein Polygon reicht es, wenn der Wert „Polygon“ zum Attribut „the_geom“ deaktiviert und die Änderung gespeichert wird. Um ein Polygon neu zu übernehmen, aktiviert man den Wert „Polygon“, löscht das geladene Polygon und legt ein neues Polygon fest, dass dann wieder gespeichert wird.

  • Stellenbezogene Filterung: Besitzt der Layer ein Attribut vom Formularelementtyp StelleID, dann kann hier in diesem Attribut eine konkrete Stelle (in der Regel wahrscheinlich die Stelle, die gerade gefiltert wird) eingetragen werden. Der Nutzer sieht in der Stelle nur die Datensätze, die im Feld Stelle-ID den entsprechenden Eintrag haben. Vorsicht bei Nutzern, die mehreren Stellen zugeordnet sind!
  • Nutzerbezogene Filterung: Besitzt der Layer ein Attribut vom Formularelementtyp UserID, dann kann statt einem festen Wert hier in diesem Attribut auch die Varibale $userid eingetragen werden, welche durch kvwmap bei Anwendung des Filters durch die jeweilige Nutzer-ID ersetzt wird. So wird es möglich, einen Filter zu definieren, durch den jeder Nutzer nur seine eigenen Datensätze sehen, abfragen und bearbeiten darf.

Stellen ohne Authentifizierung

In kvwmap können mehrere Stellen eingerichtet werden, die jeder Benutzer ohne vorherige Authentifizierung aufrufen kann. Diese werden im Folgenden Gast-Stellen genannt. Zur Einrichtung sind folgende Einstellungen notwendig:

  • In der Konfigurationsdatei config.php ist für die Konstante $gast_stellen ein Array mit ID's einzutragen, die als Gast-Stellen fungieren sollen. z.B. für die Stellen mit der id 1 und 35:
$gast_stellen = array(1, 35);
  • In der stellenbezogenen Layereinstellung kann festgelegt werden welche Layer eingeschaltet sein sollen, wenn sich ein Nutzer die Stelle als Gast aufruft. Dazu "Stellen anzeigen" dann "Layer" der entsprechenden Stelle auswählen und auf "Ändern" in der Spalte "Eigenschaften stellenbezogen" klicken. Für aktiv bei Gast kann dann ja oder nein ausgewählt werden, siehe Abbildung.
aktiv bei Gast
  • Man kann sich aus einer Gast-Stelle wieder ausloggen über den passenden im Menü befindlichen Menüpunkt oder über den Parameter go=logout. Nach dem ausloggen landet der Nutzer auf der Anmeldeseite von kvwmap.

Ist ein Gast-Stelle eingerichtet, kann diese wie folgt genutzt werden:

  • Aufruf der URL von kvwmap mit dem zusätzlichen Parameter gast. Als Wert für den Parameter gibt man die ID der Stelle an, die man als Gast benutzen möchte. z.B.: http://www.gdi-service.de/kvwmap/index.php?gast=35
  • Der Kartenausschnitt der aufgerufenen Stelle stellt sich beim Aufrufen der Seite auf die maximale Ausdehnung der Stelle ein.
  • Es sind alle Layer aktiv, die in den stellenbezogenen Layereigenschaften der Gaststelle unter "aktiv bei Gast" auf "ja" gesetzt wurden.
  • Es sind alle Layergruppen geöffnet, in denen sich aktive Layer befinden.
  • Ruft ein neuer Gastnutzer kvwmap auf, wird für diesen in der Tabelle user ein neuer Nutzer mit dem Attribut Funktion="gast" angelegt. Dieser Nutzer wird solange genutzt, wie die Session im Browser gilt. Meldet sich der Nutzer aktiv ab oder schaltet den Browser aus, wird beim nächsten Aufruf der Gaststelle wieder ein neuer Gastnutzer angelegt.
  • Da die Anzahl der Gastnutzer schnell ansteigen kann, sollten die Tabellen in denen Einstellungen der Gastnutzer stehen, möglicherweise auch durch ein Cron-Job bereinigt werden. Dazu kann dieses Script verwendet werden.
  • Seit der Einführung von Foreign-Keys auf Nutzertabellen werden alle mit Nutzern zusammenhängenden Daten in anderen Tabellen automatisch mit gelöscht. Daher kann zur Automatisierung der Löschung von Gastnutzern das einfachere Script tools/deleteGastUser.sh in einem Cron-Job verwendet werden. Die Zugangsdaten zur MySQL-Datenbank werden dabei aus der config.php ausgelesen. Es löscht alle Gastnutzer, die älter als 1 Tag sind.
  • Die Löschung der Log-Files von Gastnutzern obliegt weiterhin dem Administratoren.

Nutzerverwaltung

Die Nutzerverwaltung erreicht man über den Menüpunkt Nutzerverwaltung. In der Nutzerverwaltung kann man die existierenden Nutzer anzeigen, Neu anlegen oder in einer Übersicht zugeordnet zu Stellen auflisten lassen.

Nutzerverwaltung.png

Authentifizierung über PHP

Seit der Version 1.6.5 erfolgt die Authentifizierung über PHP und die für die Nutzereinstellungen verwendete MySQL Datenbank. Das PHP Skript prüft ob ein Benutzer sich bereits authentifiziert hat, wenn nicht, erscheint ein Dialog zur Eingabe von Benutzername und Passwort. Nach absenden diese Formulares wird in der MySQL Datenbank von kvwmap nachgesehen ob der Benutzername zum Passwort passt.

Anmeldefenster

Wenn ja, wird der Benutzername in einer Sessionvariable gespeichert und für die Session immer mitgeführt. Damit die Sessionfunktion für PHP auch funktioniert, muss in der php.ini die Variable session.auto_start=1; gesetzt sein. Danach erfolgen die weiteren Prüfungen, die aber dann genauso wie die Prüfung der Authentifizierung immer wieder ausgeführt werden. Erst wenn man sich eine bestimmte Zeit nicht beim Server gemeldet hat, wird die Session gelöscht und man muss sich wieder neu anmelden. Die Dauer der Gültigkeit der Session ist standardmäßig bei 24 Minuten (1440 Sekunden). Möchte man das ändern, kann man das über den Parameter session.gc_maxlifetime in der php.ini Datei. Nach der Änderung Apache neu starten oder graceful. Die Authentifizierung erfolgt in der Datei login.php in snippets. Dort kann man auch das Layout des Anmeldefensters anpassen. Wenn man seine eigene Datei bei update schützen möchte, lege man diese in snippets/custum ab und ändere den Pfad auf die Datei login.php in index.php in der Zeile:

  include(LAYOUTPATH.'snippets/login.php');

PHP Authentifizierung bedeutet also für alle, die kvwmap von vorherigen Versionen kennen, dass die Authentifizierung über den Web-Server wegfallen kann. Die in der Apache Konfiguration vorgenommenen Einschränkungen bezüglich der Authentifizierung können also herausgenommen werden, jedoch sollte man überlegen die Restriktionen der IP´s oder IP Bereiche weiterhin aufrecht zu erhalten. Also z.B.

 Order deny,allow
 Deny from all
 Allow from 139.30.110.0/255.255.255.0 # Ein ganzes Netz freigeben
 Allow from 62.159.207.22 # Einen Einzelnen Rechner freigeben

Dies ist unabhängig von der Persönlichen Authentifizierung.

Authentifizierung über den Web-Server

Nutzer von kvwmap müssen sich authentifizieren, damit die Anwendung weiß wen sie vor sich hat. Alle benutzerseitigen Einstellungen werden über den Benutzernamen gesteuert, die der Web-Server liefert, wenn die Authentifizierung anerkannt wurde.

Es gibt mehrere Möglichkeiten der Authentifizierung mit Apache siehe Dokumentation: http://httpd.apache.org/docs/2.0/howto/auth.html

Neben der Authentifizierung über das Standardmodul mod_auth kann auch mod_auth_mysql verwendet werden. Wir der Name schon sagt erfolgt dabei die Authentifizierung über eine MySQL-Datenbank und ist das sinnvollerweise die kvwmap-Datenbank, wenn man nicht schon eine andere Datenbank mit den Benutzern hat.

Authentifizierung mit Apache und MySQL

mod_auth_mysql.so sollte im Ordner modules vom apache Verzeichnis zu finden sein. Wenn nicht downloaden und compilieren nach Installanweisungen.

--HolgerR 10:54, 9. Aug 2006 (CEST)
Unter SuSE Version > 9 müssen apache2-devel und mysql-devel installiert sein, damit einerseits apxs2 auf dem System vorhanden ist und andererseits die Bibliotheken von mysql zur Verfügung stehen

Man muss zunächst in der httpd.conf das Modul mod_auth_mysql einbinden

Also das Komentarzeichen von folgender Zeile wegnehmen:

LoadModule mysql_auth_module modules/mod_auth_mysql.so

Dadurch wird in der Zeile:

<IfModule mod_auth_mysql.c>
   Include conf/mod_auth_mysql.conf
</IfModule>

Ebendieses Konfigurationsdatei geladen. Der entscheidende Teil für kvwmap sieht folgendermassen aus und muss für die eigene Version, das eigene Verzeichnis angepasst werden. Hier ist kvwmap_1.5.7 das zu schützende Verzeichnis


<Location /kvwmap-1.5.7>
 AuthName "MySQL Secured Place"
 AuthType Basic
 require valid-user
 AuthMySQLHost localhost
 # Der Name der Datenbank wo die Nutzer drin stehen.
 AuthMySQLDB kvwmap
 # Der Name des Nutzers, der sich da anmelden soll bei der Datenbank zum   nachsehen.
 AuthMySQLUser apachedemon
 AuthMySQLPassword # Das Passwort von apachedemon wenn es eins hat.
 AuthMySQLUserTable user # Die Tabelle wo die Nutzer drin stehen.
 AuthMySQLNameField login_name # Die Spalte wo die loginnamen drin stehen.
 AuthMySQLPasswordField passwort # Die Spalte wo die Passwörter drin stehen.
 # Setzen von Bedingungen, z.B. Einschraenkung des Zugriffs auf die Funktion --HolgerR 18:02, 3. Aug 2006 (CEST)
 AuthMySQLUserCondition "Funktion = 'user'" # Mehrere Bedingungen in Klammern setzen; Verknüpfungen mit 'and' 'or' moeglich
 ## AuthMySQLGroupTable user_grp (here do not modify this for the simple test!)
 ## AuthMySQLGroupField group (here do not modify this for the simple test!)
 AuthMySQLPwEncryption none # Hier kann man einschalten, das verschlüsselte
 #Passwörter erkannt werden. (z.B. md5 oder crypt)
</Location>

Infos unter http://modauthmysql.sourceforge.net/CONFIGURE

Nutzer anlegen

Nutzerdatenformular neu.png

Zum Anlegen eines neuen Nutzers wählt man den Menüpunkt „Nutzer anlegen“ im Obermenü Nutzerverwaltung. Es erscheint der Benuterdaten Editor wie in Abbildung dargestellt. Man trägt mindestens die Werte mit * ein und sendet das Formular mit „Als neuen Nutzer eintragen“ ab. Der eingetragene Nutzer hat anschließend sofort zugriff auf die Stellen, die im Feld „Berechtigte Stellen“ zugewiesen wurden.

Nur beim erstmaligen anlegen muss man das Password festlegen. Die Rechte des Nutzers werden über die Zuordnung der Rechte zu den Stellen definiert.

Bei einem Klick auf den Link "Mehr anzeigen" erscheinen zusätzlich Eingabefelder für Organisation und Position.

Nutzerdatenformular mehr.png

Ein Klick auf "Weniger anzeigen" blendet die zusätzlichen Eingabefelder wieder aus.

Nutzer ändern

Um Nutzerdaten zu ändern wählen Sie erst Nutzerverwaltung > Nuter anzeigen. Damit werden alle Nutzer, die nicht archiviert sind angezeigt.

Nutzer Anzeigen

Durch anklicken des Nutzernamen gelangt man in das Formular zur Bearbeitung der Nutzerdaten.

Nutzerdatenformular

Die Zustimmung zu den Nutzungsbedingungen kann durch den Administrator zurückgenommen werden. Dadurch wird der Nutzer gezwungen den Nutzungsbedingungen erneut zuzustimmen, z.b. wenn diese geändert wurden. agreement accepted.png


Soll das Passwort geändert werden auf den Link "Passwort ändern" klicken.

Passwort aendern.png

Nutzerübersicht

Die Nutzerübersicht zeigt die aktiven Nutzer gruppiert nach den Stellen in denen sie zugeordnet sind.

Nutzerübersicht

Über die Nutzerübersicht gelangt man auch zu den Nutzerdatenformularen und kann Nutzer löschen bzw. archivieren.

Nutzer archivieren

Wenn die Konstante Administration > NUTZER_ARCHIVIEREN auf true gesetzt ist, werden Nutzer beim Löschen in der Tabelle user nicht gelöscht, sondern der Flag archived auf das aktuelle Datum gesetzt.

Archivierte Nutzer erscheinen nicht mehr in der Liste der Nutzer in der Nutzerverwaltung und können sich auch nicht mehr am System anmelden. Um archivierte Nutzer wieder zu aktivieren ist der Flag archived in der Tabelle user auf NULL zu setzen.

Layer-Definition

Layer in kvwmap setzen üblicherweise auf einer PostGIS-Tabelle oder einem PostGIS-View auf (Connectiontype: MS_POSTGIS) oder binden einen Dienst (Connectiontype: MS_WMS oder MS_WFS) als Datenquelle ein. Beim Datentyp werden Punkte, Linien und Flächen (MS_LAYER_POINT, MS_LAYER_LINE, MS_LAYER_POLYGON) unterstützt. Außerdem sind Rasterlayer (MS_LAYER RASTER) und reine Abfrage-Layer ohne Geometrie (Type MS_LAYER_QUERY) möglich.


PostGIS-Tabelle anlegen und füllen

Prinzipiell gibt esw zwei verschiedene Möglichkeiten, PostGIS-Tabellen anzulegen und Daten in diese Tabellen zu spielen.

  • Wenn eine Shape-Datei vorliegt, kann diese mitsamt Geometrie, Index und Inhalt über das in PostGIS mitgelieferte Skript shp2pgsql als Datenbanktabelle angelegt werden (Beschreibung siehe z.B. die Beschreibung auf der offiziellen PostGIS-Seite). Prinzipiell:
shp2pgsql <options> <shapedateiname> <schema>.<tabellenname> | psql -d <datenbankname>
  • Soll die Tabelle zunächst ohne Inhalte definiert werden (z.B. weil noch gar keine Daten vorliegen), kann die Tabellendefinition über einen SQL-Datenbank Client (z.B. pgAdmin) und den entsprechenden CREATE TABLE Befehl erfolgen. Hier ein Beispiel für das Anlegen einer Tabelle zur Aufnahme von Jagdbezirken.Das SQL legt zu der Tabelle noch das Geometrie-Attribut an und indiziert dieses:
CREATE TABLE jagdkataster.jagdbezirke
(
 id serial NOT NULL,
 art character varying(15) NOT NULL,
 flaeche numeric,
 name character varying(50),
 zuordnung character varying(10),
 status boolean,
 verzicht boolean NOT NULL DEFAULT false
)
WITH (
 OIDS=TRUE
);
SELECT AddGeometryColumn('jagdkataster', 'jagdbezirke','the_geom',25833,'MULTIPOLYGON', 2);
CREATE INDEX gist_jagdbezirke
 ON jagdkataster.jagdbezirke
 USING gist
 (the_geom);

Die Tabelle muss die Systemspalte oid besitzen um von MapServer gelesen werden zu können.

Eine saubere Definition der Datenbanktabelle ist Voraussetzung einer sauberen Datenerfassung durch den Nutzer. kvwmap wertet die Tabellendefinition aus (Feldtypen, NOT NULL, Constraints etc.) und führt unter anderem damit eine Validierung der Nutzereingaben durch.

In der Postgres-Datenbank können auch Sichten (sog. "Views") angelegt werden. Das sind gespeicherte SQL-Abfragen, die im Prinzip wieder genau wie eine Tabelle abgefragt werden können. Mögliche Indizes in den Tabellen, die der View abfragt, gehen verloren, was die Sicht als Grundlage für einen Layer unter Umständen deutlich verlangsamen kann. Sind in kvwmap Editierrechte für den Layer gesetzt, müssen der Sicht Regeln (Rules) für den Insert-, Update- bzw. Deletefall hinzugefügt werden.

Neuen Layer anlegen

kvwmap bietet eine Admin-Oberfläche zum Erstellen und Bearbeiten von Layern: Den Layereditor (go=Layereditor). Layer sollten immer über den Layereditor angelegt werden, da kvwmap aus den Eintragungen der Layerdefintion (insbesondere dem Query-Feld) etliche Ableitungen erstellt, z.B. zur Definition der Attribute des Layers. Ein händisches Eintragen eines Layers in der MySQL-Datenbank ist auch möglich, aber sehr aufwändig und fehleranfällig, da in diversen Tabellen zwingend Eintragungen gemacht werden müssen, damit der Layer funktioniert. Wenn ein neuer Layer angelegt wird (ohne Layer-ID) ist das Formular leer, enthält aber ein Auswahlfeld für die Connection.

Bildschirmfoto 2024-02-05 um 14.40.28.png

Wird hier eine Connection ausgewählt werden alle Tabellen in eine weitere Auswahlliste geladen. Wenn hier eine Tabelle ausgewählt wird, befüllt sich das Formular mit den Angaben zur Tabelle. Wird dieses Formular so gespeichert entsteht ein Layer, der den Inhalt dieser Tabelle darstellt. Hat die Geometrie eine Tabelle wird auch der Geometrietyp eingetragen sonst ist es ein einfacher Abfragelayer.

Bildschirmfoto 2024-02-05 um 14.47.20.png

Die folgenden Felder werden automatisch ausgefüllt: Name, Alias, Datentyp, Connection-Typ, Connection, EPSG-Code, Query, Data, Haupttabelle, ID-Spalte, Schema, Tolleranzunits=pixels. Vor dem Speichern können natürlich auch noch Änderungen vorgenommen werden. Die Gruppe muss immer manuell ausgewählt werden, weil sie eine Pflichtangabe ist und nicht automatisch ausgewählt werden kann.

Wird ein Layer ausgewählt oder das Formular mit einer Layer-ID im Parameter selected_layer_id aufgerufen erscheint das Formular mit allen bisherigen Einträgen zum Layer und kann bearbeitet werden.

LayerEditor2.png

LayerEditor Sachdaten.png

Layereditor3.png

plugin layer attributes.png

Layereditor4.png

Die wichtigsten Einstellungen zum Layer sind die Basisparameter. Hier wird u.a. der Name, die Connection, das Query- und Data-SQL sowie das Koordinatensystem des Layers definiert. Bis auf den Aliasnamen müssen alle diese Felder befüllt sein, damit der Layer funktioniert.

Darüberhinaus gibt es weitere Felder, die für die Kartendarstellung des Layers verwendet werden. Die meisten dieser Felder sind Mapserver-Einstellungen. Eine ausführliche Beschreibung dieser Mapserver-Layer-Parameter findet sich in der MapServer Doku.

Über die Stift-Icons neben der Gruppe gelangt man in den Gruppeneditor und neben der Connection zum Editor der Connections.

Im Abschnitt Sachdaten können Einstellungen vorgenommen werden, die die Sachdatenausgabe des Layers betreffen. Hier kann z.B. eingestellt werden, wieviele Datensätze auf einmal bei einer Sachdatenabfrage angezeigt werden sollen, wie die Dateien für diesen Layer abgelegt werden sollen oder welche Toleranz bei der Kartenabfrage berücksichtigt werden soll. Über das Feld "DDL Default Attribut" kann festgelegt werden, welches Sachdatendrucklayout standardmäßig vorausgewählt sein soll.

Unter OWS-Parameter befinden sich Felder, die für die Verwendung von WMS- und WFS-Diensten verwendet werden.

Wenn die Option "Schreibe Mapserver Templates" gesetzt ist, wird für den Layer jeweils beim Speichern eine zum Data-Statement oder der Haupttabelle passende MapServer Header und Template Datei in das Verzeichnis " . WMS_MAPFILE_PATH . "templates/ geschreiben. Der generische Ansatz der auf der Haupttabelle basiert, erzeugt zu Codelisten und Enumerations, wie sie für XPlanung und im AAA-Modell verwendet werden, jeweils Attribute mit Textausgabe in der auch die Beschreibungen und ggf. der Codespace enthalten sind. Der Pfad zum templates Ordner kann in der Konstante WMS_MAPFILE_PATH angepasst werden. Ist das Verzeichnis noch nicht vorhanden wird es angelegt. Der Dateiname setzt sich zusammen aus dem Layernamen sowie dem Zusatz _head.html bzw. _body.html. Ist die Datei schon vorhanden, wird sie überschrieben. Als Layername wird der Name der beim Speichern eingestellten Sprache genommen.


Unter Metadaten kann eine Kurzbeschreibung, Quellenangabe, der Ansprechpartner (Datenherr), dessen Telefonnummer und E-Mail-Adresse sowie Angaben zur Aktualität, Aktualisierungsrate und ein Metadatenlink für ausführlichere Informationen zum Layer hinterlegt werden.

Wenn Plugins geladen sind, kann es sein dass zusätzliche Layerparameter angezeigt werden. Im Beispiel sind die Attribute cluster_option aus dem Plugin portal sowie die Attribute sync und vector_tile_url aus dem Plugin mobile dargestellt.

Eine umfassende Erläuterung aller Layer-Einstellungen findet sich in der Referenz zur MySQL-Datenbank von kvwmap.



Vektorlayer

PostGIS-Vektorlayer

PostGIS-Vektorlayer werden mit Datentyp MS_LAYER_POLYGON, MS_LAYER_LINE, MS_LAYER_POINT definiert. Bei Flächen und Linien können die Objekte der entsprechenden PostGIS-Tabelle aber auch durchaus Multipolygone und Multilinien sein.

Neben dem Namen (evtl. auch in verschiedenen Sprachen) und dem Datentyp sind die Zugehörigkeit zu einer Layergruppe, die Verbindung zur Datenbank (CONNECTION und CONNECTIONTYPE) und das datenbankseitig verwendete Koordinatenreferenzsystem (EPSG-Code) zwingend nötig. Gruppen, zu denen man den Layer zuordnen möchte müssen bereits existieren. Neue können über den Menüpunkt Layergruppen anzeigen angelegt werden.

Vektorlayer benötigen zur Darstellung in der Karte Klassen-Definitionen (mindestens eine). Zur Beschreibung des Aussehens der Objekte und deren Beschriftung bietet kvwmap den Style- und Labeleditor an (go=Style_Label_Editor). Wird mehr als eine Klasse definiert, müssen die Klassen durch die sog. Expression definiert werden.

Der Eintrag in der Query ist dann notwendig, wenn der Layer abfragbar sein soll - über die Karte oder über die Sachdatensuche. Beim Speichern der Layerdefinition wird die Query von kvwmap auf Fehler in der SQL-Syntax geprüft. Gleichzeitig entwickelt kvwmap aus der Query die Reihenfolge und die grundlegende Definition der Attribute, also der Sachinformationen zum Thema.

WFS-Layer

Ein WFS-Layer wird genauso wie ein PostGIS-Vektorlayer auch mit den Datentypen MS_LAYER_POLYGON, MS_LAYER_LINE oder MS_LAYER_POINT definiert. Das Feld Connectiontype wird hier auf MS_WFS gesetzt und im Feld Connection die URL des WFS-Dienstes eingetragen. Die URL muss keine WFS-Parameter enthalten. Sie werden in separaten Feldern definiert bzw. automatisch vom Mapserver gesetzt. Der EPSG-Code muss hier auch angegeben werden. Wichtig beim WFS-Layer sind noch die Felder im Abschnitt "OWS-Paramater". Im Feld "WMS-Name/Typename" muss der Name des Featuretypes eingetragen werden und im Feld "OWS-Serverversion" die WFS-Version des Dienstes.

WFS-Layer benötigen zur Darstellung in der Karte ebenfalls Klassen-Definitionen (mindestens eine). Zur Beschreibung des Aussehens der Objekte und deren Beschriftung bietet kvwmap den Style- und Labeleditor an (go=Style_Label_Editor). Wird mehr als eine Klasse definiert, müssen die Klassen durch die sog. Expression definiert werden.



Raster-Layer

Unter Raster-Layer werden Layer verstanden, die in der Karte den Inhalt von georeferenzierten Bildern (üblicherweise TIFs) darstellen. Rasterlayer werden mit Datentyp MS_LAYER_RASTER definiert und können über das direkte Ansprechen von entweder einzelnen Rasterbildern oder einem Set von Rasterbildkacheln durch den Mapserver realisiert werden oder über das Einbinden von WMS-Diensten.

Einzelne Rasterdateien

Bei einzelnen Tiff-Dateien wird in der Layerdefinition folgendes angegeben:

  • Datentype: MS_LAYER_RASTER
  • Connectiontype: MS_OGR
  • Data: der Pfad zur Datei relativ zu SHAPEPATH

Rasterlayer.png]

Layer mit Rasterkacheln

Statt einem DATA-Statement und einer CONNECTION enthält ein Rasterlayer einen TILEINDEX (Pfad zur Shape-Indexdatei der Rasterkacheln) und einem TILEITEM (Bezeichnung der Spalte in der Indexdatei, die die Dateinamen der einzelnen Kacheln enthält). Rasterlayer haben keine Klassen.

Hinweise zum Anlegen eines TILEINDEX für Rasterdaten:

Liegen Bildkacheln vor, erfolgt das Anlegen eines TILEINDEX praktischerweise mit gdaltindex.

  • Voraussetzung:
    Es liegen georeferenzierte Rasterdaten z.B. Luftbildkacheln vor. Die Georeferenzierung erfolgt bei TIFF-Daten über tfw-Dateien und bei JPEG-Daten über jgw-Dateien.
    Der Inhalt der tfw- und jgw-Dateien ist identisch. Tiff-Daten lassen sich somit in JPEG umwandeln, was Speicherplatz spart und kürzere Ladezeiten ermöglicht. Die tfw- und tif-Dateien bzw. die jpg- und die jgw-Dateien sind sinnvollerweise in einem Verzeichnis unterhalb des Datenpfades z.B. /opt/lampp/var/data abzulegen.
  • Erzeugung des Index:
    Infos über die Befehlssyntax von „gdaltindex“ erhält man durch Eingabe des Kommandos „gdaltindex“ ohne Parameter auf der Linux-Konsole.
    Der Tileindex lässt sich einfach im Datenverzeichnis z.B. mit dem Kommando: „gdaltindex luftbilder luftbilder/*.jpg“ erzeugen. Hierbei ist der Verzeichnisname mit den Daten „luftbilder“ und das erzeugte shape-file mit dem Index heißt „luftbilder“. Es werden 3 Dateien erzeugt. In diesem Beispiel luftbilder.shp, luftbilder.shx und luftbilder.dbf.
  • Erzeugen des Index im Docker-Container:
    Läuft kvwmap im Docker-Container, steht gdal nicht auf dem Hostrechner und auch nicht im web Container zur Verfügung. Dazu benutzt man dann den gdal Container. Zunächst kann man sich mit dem Befehl
dcm status gdal
darüber informieren ob der Container gdal läuft. Wenn nicht, muss dieser erst gestartet werden mit
dcm run gdal
Der Befehl zum Ausführen von gdaltindex im laufenden gdal Container sieht dann wie folgt aus:.
gdaltindex /var/www/data/shapeverzeichnis/index_datei.shp /var/www/data/rasterverzeichnis/*.tif

Außerhalb des Containers lautet der Befehl

docker exec gdal gdaltindex /var/www/data/shapeverzeichnis/index_datei.shp /var/www/data/rasterverzeichnis/*.tif
Der gdal Container, der auf dem Image pkorduan/gdal-sshd basiert bindet das Volume -v $USER_DIR/www:/var/www mit ein, welches in der Regel das Verzeichnis /home/gisadmin/www auf das interne Verzeichnis /var/www mapped. Das bedeutet, dass das Verzeichnis im gdal Container zur Verfügung steht. Die Pfadangaben des gdaltindex Befehls beziehen sich auf die Verzeichnisstruktur im gdal Container. Der Speicherort für die Shape-Dateien wird hier auch mit vollem und absolutem Pfad angegeben, da das Verzeichnis beim Einstieg in den Container defaultmäßig /data ist. Also im Hostsystem vorher in das Verzeichnis zu gehen wo sich die Rasterdaten befinden oder die Shape-Files hin sollen bringt nichts. Man könnte höchstens den gdal Container interaktiv starten mit:
docker run -it --name gdaltindex --volumnes-from wwwdata pkorduan/gdal-sshd /bin/bash
und den gdal Befehl darin manuell ausführen. Im Beispiel wurde dieser interaktive Container gdaltindex genannt, damit man ihn nach dem Aussteigen aus dem Container mit exit leichter wieder löschen kann.
docker rm gdaltindex
Möchte man nicht den vorhandenen gdal Container nutzen, sondern einen eigenen verwenden, der nach dem Ausführen sofort wieder gelöscht wird, übergibt man den Befehl mit dem Parameter -c
docker run --rm --volumes-from wwwdata pkorduan/gdal-sshd /bin/bash -c "gdaltindex /var/www/data/shapeverzeichnis/index_datei.shp /var/www/data/rasterverzeichnis/*.tif"
  • Einbindung als Raster-Layer:
    Es ist ein Rasterlayer in der Tabelle layer MySQL-Datenbank anzulegen. Der Tileindex muss jetzt lediglich in der Spalte „tileindex“ der Tabelle eingetragen werden. In diesem Beispiel ist der Eintrag „luftbilder.shp“ vorzunehmen.
  • Mögliche Probleme:
    Wenns nicht gleich funktioniert sind zunächst die Rechte der Daten zu überprüfen und ggfs. mit „chmod“ z.B. auf 755 zu setzen.
    Die Erzeugung eines Index über grössere Datenbestände kann schon mal etwas dauern. Das Kommando sollte dann aber ohne Fehlermeldungen durchlaufen.



WMS-Layer

Ein WMS kann vom Nutzer temporär in seine Karte eingefügt werden, er kann aber auch dauerhaft als Layer definiert werden.


Zum Anlegen eines WMS-Layers muss man mindestens den getCapabilities Request des WMS kennen. Beispiel für einen WMS: Schulstandorte (GeoPortal MV, Fachthemen, Bildung und Soziales, Umbrüche nur für die bessere Lesbarkeit):

https://www.geodaten-mv.de/dienste/schulstandorte_wms?REQUEST=GetCapabilities&SERVICE=WMS

Das Capabilities-Dokument sollte mindestens auf folgende Elemente untersucht werden:

  • OnlineResource
  • Format des getMap
  • Version (kvwmap kann momentan maximal Version 1.1.1)
  • Format des GetFeatureInfo
  • Liste der CRS (kompatibel zu den angebotenenen Referenzsystemen in den kvwmap-Optionen?)
  • Layer Namen
  • Layer abfragbar (queryable)
  • Layer transparent (opaque)
  • Layer Style
  • Layer Style LegendURL

Zum Testen kann man sich einen GetMap Request zusammen basteln:

 
 https://www.geodaten-mv.de/dienste/schulstandorte_wms? //
 SERVICE=WMS&REQUEST=GetMap&VERSION=1.3.0& //
 LAYERS=schultyp_grund,schultyp_regional,schultyp_gymnasium,schultyp_gesamt,schultyp_waldorf,schultyp_foerder,schultyp_abendgym,schultyp_berufs& //
 WIDTH=600&HEIGHT=600&BBOX=317000,5963908,386068,6032975& //
 CRS=EPSG:25833&FORMAT=image/png&STYLE=default
 


Im kvwmap-WMS-Layer bleiben die Felder Query und Data leer. Im Feld Connection wird nur ein Teil des GetMap-Requests eingetragen, nämlich die Serveradresse und nur die 3 Parameter: VERSION, LAYERS und FORMAT. Weitere optionale Parameter wie z.B. TRANSPARENT sind möglich. Im Beispiel also:

 http://www.geodaten-mv.de/dienste/schulstandorte_wms?language=ger& //
 VERSION=1.1.1 //
 LAYERS=schultyp_grund,schultyp_regional,schultyp_gymnasium,schultyp_gesamt,schultyp_waldorf,schultyp_foerder,schultyp_abendgym,schultyp_berufs& //
 FORMAT=image/png& //
 TRANSPARENT=true
 

Falls ein WMS-Proxy dazwischen geschaltet werden muss, wird der Connection ein "http://meinkvwmap.de/wms_proxy.php?url=" vorangestellt. In der eigentlichen URL muss das Fragezeichen gegen ein kaufmännisches "&" ausgetauscht werden. Im Beispiel also:

 http://geoport.lk-xy.de/wms_proxy.php?url=
 http://www.geodaten-mv.de/dienste/schulstandorte_wms&language=ger& //
 VERSION=1.1.1& //
 LAYERS=schultyp_grund,schultyp_regional,schultyp_gymnasium,schultyp_gesamt,schultyp_waldorf,schultyp_foerder,schultyp_abendgym,schultyp_berufs& //
 FORMAT=image/png //
 TRANSPARENT=true
 

Der ConnectionType ist "MS_WMS" und als Datentyp wird "MS_Layer_Raster" gewählt. Alle anderen Einstellungen erfolgen wie bei einem normalen Rasterlayer. Wenn der WMS abfragbar ist ("<Layer queryable = '1' ... >"), kann Queryable auf "ja" gestellt werden, wenn eine Sachdatenabfrage auf den Dienst sinnvoll erscheint.

Wenn in der kvwmap-Legende der WMS-Layer mit Legende erscheinen soll, ist im Layer eine Klasse mit einem beliebigen Klassennamen anzulegen. Ein Style muss nicht angelegt werden.

Wenn der WMS Transparenz unterstützt ("<Layer opaque = '0' ... >"), kann in der Connection "TRANSPARENT=true" eingetragen werden. In den stellenabhängigen Eigenschaften ist dann keine Transparenz anzugeben. Die Drawingorder muss berücksichtigt werden.

Shape-Layer

Üblicherweise werden Shapes im kvwmap-Umfeld nicht verwendet, da die Arbeit mit einer Datenbank enorme Vorteile bietet.

Shape-Layer werden je nachdem mit Datentyp MS_LAYER_POLYGON, MS_LAYER_LINE, MS_LAYER_POINT definiert. Der wesentliche Unterschied zum PostGIS-Vektorlayer ist, dass in der CONNECTION der Pfad zur *.shp-Datei angegeben wird und der CONNECTIONTYPE "MS_Shapefile" lautet.

Die Verwendung von Umlauten, Leerzeichen, Schrägstrichen oder sonstigen Sonderzeichen in Verzeichnissen und Dateinamen sollte vermieden werden.

Layer-Metadaten

Die Metadaten zum Layer dienen der Beschreibung des Layers. Sie werden an folgenden Stellen zur Dokumentation der Layer verwendet.

  • Die Kurzbeschreibung wird als Abstract für die Veröffentlichungen des Layers im Dienst (go=OWS) oder für den Export von Map-Dateien, z.B. beim WMS-Export und beim Erzeugen von Dienstdateien (go=create_geoweb_service) im Plugin xplankonverter verwendet.
  • Die Kurzbeschreibung und der Metadatenlink werden in der Themenübersicht (go=Layer_Uebersicht) verwendet.
  • Alle Metadaten außer Metadatenlink, Version und Kommentar werden beim Layerdef-Export zur Darstellung der Layer-Info in kvmportal verwendet.
  • Die Quellenangaben werden beim Klick auf den © Button links unter der Karte in kvmwap und auch in kvportal als Urheberrechte angezeigt.

Quellenangaben

Es können eine oder mehrere Quellenangaben pro Layer aus einer definierten Liste ausgewählt werden.

Urheberrechte.png

Zum Hinzufügen einer Quelle wird der Plus-Button.png Button verwendet. Daraufhin erscheint eine Auswahlliste.

Datasource-Auswahlliste.png

Wird eine Datasource angeklickt, erscheint diese als ausgewählte Datasource des Layers. Es können mehrere ausgewählt werden.

2Datasources.png

Über den Stift-Button.png Button gelangt man in die Liste der eingetragenen Datenquellen. Dort können neuer hinzugefügt und vorhandene geändert und gelöscht werden.

Quellenangaben Formular.png

Der Name wird als Copy-Right-Info in kvportal verwendet.

Der Text der Beschreibung wird für den Layer angezeigt wenn man unter der Karte auf den Copy-Right-Button klickt. Wenn am Ende des Textes getrennt durch ein ; ein Link beginnend mit http steht, wird der Text davor als Link dargestellt der auf die angegebene URL zeigt.

Layer-Klassifizierung

automatische Klassifizierung

Es gibt die Möglichkeit, die Klassen an Hand der Daten des Layers automatisch generieren zu lassen. Durch Klick auf den Link "Klassen automatisch hinzufügen" öffnet sich ein Formular für die automatische Klassengenerierung. Es stehen mehrere Methoden zur Verfügung, wie die Klassen erstellt werden sollen:

  1. für jeden Wert eine Klasse: Hier wird für jeden vorkommenden Wert eine Klasse angelegt (zur Sicherheit maximal 50). Diese Methode eignet sich vor allem für Attribute mit wenigen unterschiedlichen Werten. Jede Klasse bekommt eine zufällige Farbe aus der Tabelle "colors".
  2. gleiche Klassengrösse: Diese Methode bildet den gesamten Wertebereich auf die definierte Anzahl an Klassen ab, wobei das von-bis-Intervall innerhalb jeder Klasse gleich groß ist. Es wird ein Farbverlauf erzeugt.
  3. gleiche Anzahl Klassenmitglieder: Diese Methode bildet den gesamten Wertebereich auf die definierte Anzahl an Klassen ab, wobei die Anzahl an Objekten innerhalb jeder Klasse gleich groß ist. Es wird ein Farbverlauf erzeugt.
  4. Jenks-Caspall-Algorithmus: Diese Methode bildet den gesamten Wertebereich auf die definierte Anzahl an Klassen ab, wobei versucht wird, die Unterschiede innerhalb einer Klasse zu minimieren und die Unterschiede zwischen den Klassen zu maximieren. Es wird ein Farbverlauf erzeugt.

Außerdem muss das Attribut angegeben werden, nach dem klassifiziert werden soll.

Bei den Klassifizierungsmethoden 2 - 4 muss außerdem die Anzahl an gewünschten Klassen und eine Farbe für den Farbverlauf angegeben werden. Der Farbverlauf geht von hell nach dunkel und die angegebene Farbe entspricht der Farbe der letzten Klasse. Sie sollte deshalb ausreichend dunkel gewählt werden.

Optional kann noch ein Klassifizierungsname angegeben werden, welcher in das Klassen-Feld "Klassifizierung" übernommen wird.

Wenn man nach Attributen klassifizieren möchte, egal ob von Hand oder automatisch, muss man diese Attribute und die Geometriespalte in einer Unterabfrage im Feld Data abfragen. Außerdem muss dieses Attribut als classitem eingetragen werden oder in der Expression verwendet werden.

Expressions

Bei mehreren Klassen wird in der Spalte Expression der logische Ausdruck eingegeben, der die Klasse definiert. Soll ein Layer z.B. hinsichtlich einer "Objektart" klassifiziert dargestellt werden, werden mit "([Objektart] = 1000)" nur die Features angezeigt, deren Wert in deisem Attribut genau 1000 entspricht.

  • Beispiele Schreibweise für textliche Vergleiche:
('[textattribut]' = 'text')
('[textattribut]' eq 'text')
('[textattribut]' != 'text')
('[textattribut]' != '') 
  • Beispiele Schreibweise für numerische Vergleiche:
([numerisches attribut] = 1234)
([numerisches attribut] eq 1234)
([numerisches attribut] > 1234)
([numerisches attribut] gt 1234)
([numerisches attribut] >= 1234)
([numerisches attribut] ge 1234)
([numerisches attribut] > 1234 and [numerisches attribut] < 2345) 
  • Schreibweise für boolsche Vergleiche:
('[boolean attribut]' eq 't')
('[boolean attribut]' eq 'f')

Für boolsche Attribute am besten im Data-Statement das Attribut in ein numerisches umwandeln und dieses dann zur Klassifizierung nutzen:

CASE WHEN bool_att THEN 1 ELSE 0 END AS class_att

Im Klasseneditor kann dann anhand class_att nach 1 und 0 klassifiziert werden.

Mehr Informationen zu den Möglichkeiten der EXPRESSION siehe mapserver.org.

Clusterbildung bei Punkt-Layern

Als Clusterbildung wird das Zusammenziehen von eigentlich separaten Punktobjekten zu einem Punktobjekt in der Karte verstanden, wenn sich - bedingt durch den Kartenmaßstab - die einzelnen Punktsymbole überlagern.

  • Die Angabe von Cluster:Maxdistance ist erforderlich,
  • Es muss eine weitere Klasse definiert werden, die für die Darstellung des Cluster-Objekts verwendet wird,
  • Die neue Klasse erhält die EXPRESSION "('[Cluster_FeatureCount]'!='1')", während die vorhandenen Klassen den Eintrag "('[Cluster_FeatureCount]'='1')" benötigen (bis MapServer 6.4 "[Cluster:FeatureCount]"),
  • Soll das Cluster-Objekt eine Beschriftung in Form der Anzahl der zusammengezogenen Einzelobjekte erhalten, muss als LABELITEM "Cluster_FeatureCount" eingetragen werden,
  • Style und gegebenfalls Label der neuen Klasse müssen definiert werden.



Diagramme in der Sachdatenanzeige

Zu Vektorlayern aus der PostGIS-Datenbank können ein oder mehrere Diagramme definiert werden. Die definierten Diagramme des Layers werden im Layereditor am Ende vom Abschnitt Sachdaten angezeigt.

Liste-in-Layerformular.png

Mit Betätigung des Stift-Button können die vorhandenen Diagramme gelistet, geändert, gelöscht und neue hinzugefügt werden. Es gibt keine gesonderten Menüpunkte zum Editieren von Diagrammen. Man kann nur über den Layereditor oder über die Sachdatenanzeige zu den Diagrammenlisten und -formularen gelangen.

Ein Menü-Link zur Diagrammliste eines Layers mit der ID 9 benötigt die Parameter go=layer_charts_Anzeigen und layer_id=9.

Liste Diagramme.png

Das Anlegen und Ändern von Diagrammen erfolgt im Formular layout/snippets/layer_chart_formular.php.

Formular Diagramm.png

Die Diagramme werden in der Tabelle layer_charts gespeichert welche folgende Attribute enthält:

  • layer_id integer not null: Id des Layers zu dem das Diagramm gehört. Wird im Editor nicht angezeigt. Der Titel des Layers ist aber im Formular zu sehen.
  • Diagramm ID, id integer not null autoincrement: Fortlaufende id zur identifizierung des Diagramms.
  • Diagrammtitel, title varchar(255): Bezeichnung des und Überschrift über dem Diagramms.
  • Diagrammtyp, type enum('bar','pie','doughnut') not null default 'bar': Diagrammtyp.der Berechnung des Hochwertes im Diagramm.
  • Beschriftung Balken, value_attribute_label varchar(100):
  • Aggregationsfunktion, aggregate_function enum('sum', 'average', 'min', 'max'): Art
  • Werteattribut (Hochwert), value_attribute_name varchar(65): Name des Attributes dessen Werte für die Berechnung des Hochwertes verwendet werden.
  • Beschriftungsattribut (Rechtswert):, label_attribute_name varchar(65): Name des Attributes nach dem klassifiziert wird und dessen Werte als Beschriftung an der Rechtsachse verwendet werden.
  • Beschreibung, beschreibung: Ein Freitextfeld zur Beschreibung des Inhaltes des Diagramms
  • Breite, breite: Die Breite in der das Diagram maximal angezeigt werden soll. In Pixel (px) oder Prozent (%). Die Angabe ist Pflicht.

Die Diagramme werden am Ende einer Sachdatenanzeige in einer separaten Gruppe, die aufgeklappt werden muss angezeigt.

Diagramme Gruppe Sachdatenanzeige.png

Als Diagrammtyp können über die Auswahlliste die Typen Balken, Torten und Doughnut gewählt werden. Das Diagramm passt sich jeweils automatisch an.

Flächenanteile Säulendiagram.png Flächenanteile donat.png

Fährt man mit der Maus über ein Segment des Diagramms wird der konkrete Wert, z.B. die Flächensumme für die Kategorie angezeigt.

Flächenanteile Bebauung.png

Interessiert man sich nur für das Verhältnis von innerhalb und außerhalb, kann man Sonstiges durch anklicken ausblenden, die Beschriftung wird durchgestrichen und das Diagramm zeigt nur noch innerhalb und außerhalb an.

Verhältnis-innerhalb-außerhalb.png

Mit dem Bearbeiten-Button kommt man zum Änderungsformular. Der Button wird nur angezeigt wenn in der Stelle der Menüpunkt mit dem Anwendungsfall "Layereditor" zur Verfügung steht oder die Funktion "Layereditor" zugeordnet ist die Funktion user->is_case_allowed für den angemeldeten Nutzer true liefert. Also wenn der Nutzer den Layer auch bearbeiten darf. (In der Regel nur Administratoren)

Voraussetzung für die Funktion: Für die Erzeugung der Diagramme wird die Bibliothek Chart.js eingesetzt. Die Datei chart.js muss im THIRDPARTY_PATH unter dem Verzeichnis Chart abgelegt sein. Der View für die Darstellung der Diagramme befindet sich in kvwmap unter layouts/snippets/layer_charts.php, die Funktionen im gleichen Verzeichnis in layer_chart_functions.php.

Chart Layer

Man kann auch Kreis oder Balkendiagramme in der Karte darstellen wie hier in diesem Beispiel für Energieverbrauchsklassen.

Energieverbrauchsklassen.png

Dazu muss der Datentyp auf MS_LAYER_CHART gesetzt sein und es geht nur bei Connectiontype MS_POSTGIS.

Datentyp CHART.png

Unter Processing wird mit CHART_TYPE die Diagramart und getrennt durch Semikolon mit CHART_SIZE die Größe in Pixel eingestellt.

Processing CHART.png

Bei den Klassen werden dann keine Angaben unter Expression angegeben. Es werden nur so viele Klassen erstellt wie es Teile im Diagramm geben soll. Nach welchem Attribut klassifiziert wird, wird im Style unter size eingetragen. In der Legende werden die Name der Klassen und die im Style eingestellten Farben dargestellt.

Style CHART Einstellung.png

Dokumente Ordner

Sollen in dem Layer auch Dokumente hochgeladen werden können, kann man im Attribut "Dokumente Ordner" einen individuellen Speicherpfad angeben, z.B.

/var/www/data/mein_layer

Wird kein Ordner angegeben werden alle Dokumente in dem Ordner gespeichert, der in der config-Konstante CUSTOM_IMAGE_PATH festgelegt ist. Default ist hier

/var/www/data/bilder

Der Ordner kann auch noch im Attribut-Editor für jedes einzelne Dokument-Attribut überschrieben werden, siehe Admin-Dokumentation#Dokument.

Dokumente URL

Sollen die Dokumente auch online zur Verfügung stehen, kann man dafür hier eine URL angeben. Diese URL sollte dann auch auf den Ordner in dem die hochgeladenen Dateien liegen verweisen. Das wird mit einem entsprechenden Eintrag in der Apache-Config realisiert.

Wenn wir z.B. einen Dokumente Ordner

/var/www/data/mein_layer

haben und die URL soll heißen

https://mein-server.de/dokumente

Dann muss die Apache-Config lauten:

Alias /dokumente "/var/www/data/mein_layer/"
<Directory /var/www/data/mein_layer/>
  AllowOverride None
  ...
</Directory>

Layer zu einer Stelle hinzufügen

Der Layer kann direkt im Layereditor einer oder mehreren Stellen zugeordnet werden. Über den Stelleneditor (go=Stellen_Anzeigen) kann die Zuordnung von Layern zu einer Stelle ebenfalls erfolgen. Die Defaults aus der Layerdefinition (zur Zeichenreihenfolge, zum Maßstabsbereich usw.) werden in der Zuordnung verwendet und müssen gegebenenfalls stellenabhängig im Nachgang angepasst werden. Sind in der Layer-Rechteverwaltung (go=Layerattribut-Rechteverwaltung) bereits Default-Rechte für den Layer vergeben, so werden diese bei der Zuordnung eines Layers zu einer Stelle gesetzt.

Stellenbezogene Layereigenschaften

Über den Menüpunkt Stellenverwaltung > Stellen anzeigen gelangt man zur Übersicht der Layer, die zu der jeweiligen Stelle gehören. Button zur Übersicht der stellenbezogenen Layereigenschaften

Darin können die Zeichen- und Legendenreihenfolge der Layer in der Stelle am Stück angepasst sowie zu den stellenbezogenen und Layereinstellungen gewechselt werden.

Übersicht der stellenbezogene Layereinstellungen

Für die Änderung allgemeiner Layereieigenschaften wird in den Layereditor gewechselt, siehe auch GLE. Die stellenbezogenen Layereigenschaften werden in einem gesonderten Formular bearbeitet.

StellenbezogeneLayereigenschaften.png

Die in diesem Editor vorgenommen Einstellungen wirken sich auf den Layer nur in der gewählten Stelle aus. Werden hier keine Angaben geändert gelten die Default-Werte des Layers, die im Layereditor gesetzt sind. Wird im Layereditor im Tab "Stellen-Zuweisung" der Link "Default-Werte an Stellen übertragen" angeklickt werden die stellenbezogenen Eigenschaften des Layers in allen Stellen auf Default gesetzt zu denen der Layer gerade zugeordent ist.

  • Unter Layergruppen kann man eine Layergruppe auswählen zu der der Layer nur in dieser Stelle gehören soll.
  • Layer können in der Karte nur abgefragt werden wenn in abfragbar ja ausgewählt wird. Geometrie übernehmbar bezieht sich auf die Übernahme von Geometrien im Geometrieeditor. Layer bei denen hier nein steht erscheinen nicht in der Auswahl der Layer von denen Geometrien übernommen werden können.
  • Unter Offsite kann eine Farbe angegeben werden die Transparent dargestellt werden soll, mit den 3 RGB Werten: "0 0 0", RGB hexadecimal: "#rrggbb" oder RGBA (translucence): "#rrggbbaa". Die Eigenschaft wirken sich nur auf Rasterlayer aus.
  • Transparency wird in % angegeben. Höhere Werte sind mehr durchscheinend.
  • Wenn Post label cache eingeschaltet ist, werden die Texte des Layers erst ganz zum Schluss über allen anderen Layern gezeichnet.
  • Der Filter grenzt die in der Karte und Sachdatenanzeige dargestellten Feature des Layers ein. Es wird ein WHERE Ausdruck erwartet. Mehrere können mit logischen Operatoren AND, OR usw. verknüpft werden.
  • Template, Header und Footer werden nur verwendet wenn der Layer in einem WMS ausgegeben werden soll. Die Vorlagen werden dann für die HTML-Ausgabe von GetFeatureInfo-Anfragen verwendet.
  • Symbol scale gibt an in welchem Maßstab die Styles die angegebene normale Größe haben sollen. Wird der Maßstab größer werden auch die Symbole größer wenn z.B. Max-Width größere Werte hat als Width und umgekehrt kleiner wenn der Maßstab kleiner wird. (Für die Maßstabszahl gilt das Reziproke)
  • Unter Requires kann ausgewählt werden zu welchem anderen Layer dieser Layer gehören soll. Wird hier ein andere ausgewählt, erscheint der Layer aus diesem Formular nicht mehr in der Legende, nur seine Klassen falls er welche hat. Wird der bei Requires ausgewählte Layer in der Legende der Karte eingeschaltet erscheinen auch die Features der Layer die diesen als Requires eingestellt haben. Abfragen in der Karte fragen gleichzeitig auch die mit Requires zugeordneten Layer ab. So kann man mehrere Layer wie einen Layer aussehen lassen.
  • Layer bei denen "aktiv bei Gast" ausgewählt ist sind in Gast-Stellen nach dem Anmelden immer aktiv gestellt.
  • Aktivitäten von Layern für die "wird geloggt" eingeschaltet ist, können vom Admin geloggt werden.

Layergruppenverwaltung

Die Layergruppen können über den Menüpunkt Layergruppen anzeigen verwaltet werden. Der Link zu der Anzeige ist: index.php?go=Layergruppen_Anzeigen.

Layergruppen anzeigen

Layergruppen anzeigen.png

In der Anzeige der Layergruppen kann in die Formulare zum Ändern der Eintragungen gewechselt werden, Layergruppen gelöscht und neue angelegt werden. Sollen Layer Gruppen zugeordnet werden, müssen die Gruppen vorher angelegt worden sein.

Layergruppen ändern

Layergruppe Aendern.png

Im Formular zum Ändern von Layergruppen werden folgende Informationen eingetragen:

  • Gruppenname ... Name der Gruppe (Pflichtangabe)
  • Gruppenname[_sprache] ... Name der Gruppe in anderen Sprachen (optional)
  • obergruppe ... Id der Obergruppe in der die Gruppe eingeordnet werden soll. Wird hier nichts angegeben, ist die Gruppe auf der obersten Stufe und keiner anderen untergeordnet.
  • order ... Reihenfolge der Layergruppe in der Legende.

Wenn der Gruppeneditor mit dem Parameter selected_layer_id aufgerufen wurde und dieser eine positive Zahl hat, wird ein Link zum Sprung auf den Layer mit dieser ID angezeigt.

Menüverwaltung

Die auf der linken Seite angezeigten Menüpunkte sind immer einer Stelle zugewiesen. Welche Menüpunkte zu welchen Stellen gehören, kann in der Stellenverwaltung eingestellt werden. Menüs sind in Ober- und Untermenüs aufteilbar. Die Bearbeitung der Menüpunkte erfolgt entweder in der Oberfläche in der Menüverwaltung oder direkt in der MySQL-Datenbank in der Tabelle u_menues.

Menüverwaltung

Die Menüverwaltung wird mit dem Anwendungsfall Menues_Anzeigen gestartet.

Liste der Menüpunkte

Mit dem Link "Ändern" kommt man zum Editor für die einzelnen Punkte.

Menüeditor

Wenn in Links javascript:void(0) angegeben ist, wird statt dessen der Link im Feld Onclick verwendet.

Mit dem Button rechts neben dem Eingabefeld kann der angegebene Link getestet werden.

Am Ende stehen die folgenden Optionen zur Verfügung:

  • "zurück": Springt in die Liste der Menüpunkte zurück
  • "Ändern": Speichert die eingestellten Änderungen für den aktuellen Menüpunkt
  • "Zurücksetzen": Setzt die Werte im Formular auf die ursprünglichen Werte des Menüpunktes zurück
  • "Als neuen Menüpunkt Eintragen": Legt einen neuen Menüpunkt an mit den aktuellen Werten aus dem Formular


Über den Button "Neues Menü" kann man einen neuen Menüpunkt anlegen. Dieser Button erscheint aber nur, wenn die Eigenschaft display im Style #neuer_datensatz_button auf block gesetzt ist. Am besten man erstellt sich einen Style in seiner custom/custom.css.

#neuer_datensatz_button {
  display: block;
}

Neuen Menüpunkt anlegen

Wenn der Obermenüpunkt schon existiert, muss nur noch der Unterpunkt angelegt werden, ansonsten beide, jedoch erst der Obermenüpunkt. Für das Anlegen eines neuen Menüpunktes sind die nachfolgend beschriebenen Arbeiten auszuführen.

  • Eintragen des Menüpunktes in die Tabelle u_menues.
    • id ist eine fortlaufende Nummer
    • name (Pflicht) die Angabe in der Spalte name ist der Text, der als Menüpunkt in der GUI erscheint. Hier können auch deutsche Umlaute enkodiert werden, z.B. &auml für ä
    • links (Pflicht) enthält die Angabe des Anwendungsfalles, der aufgerufen werden soll. Wenn es ein Obermenüpunkt sein soll, ist hier index.php?go=changemenue einzutragen.
    • onclick Der JavaScript-Code, der hier eingetragen ist, wird beim Klick auf den Menüpunkt ausgeführt. Soll der Link in links nicht ausgeführt werden, muss am Ende return false; stehen.
    • bei obermenue ist die ID des Obermenüpunktes anzugeben, in dem das Menü enthalten sein soll. Ist es selbst ein Obermenü, kommt hier eine 0 rein
    • In menueebene (Pflicht) kommt eine 1, wenn es ein Obermenü ist sonst eine 2 für Untermenü
    • In target kann optional gewählt werden, ob die Seite hinter dem Menüpunkt in einem neuen Fenster aufgehen soll oder im aktuellen, in dem das Menü ist. _blank öffent den Menüpunkt in einem neuen Fenster. Das reservierte Wort confirm sorgt dafür, dass die Ausführung des Punkte noch einmal vorab bestätigt werden muss und ggf. abgebrochen werden kann.
    • Order gibt an in welcher Reihenfolge der Menüpunkt in der Stelle eingeordnet werden soll. Wird diese Eigenschaft geändert, muss der Menüpunkt neu zur Stelle zugeordnet werden, damit sich die Reihenfolge auswirkt.
    • title bietet die Möglichkeit einen Hilfetext anzugeben. Dieser wird beim Überstreichen des Menüpunktes mit der Maus als Tooltip angezeigt.
    • button_class Hier kann man angeben mit welchem Style der Menüpunkt als Button gezeichnet werden soll. Wenn hier eine Klasse angegeben ist und in Optionen die Option "Menüs als Schaltfläche" ausgewählt ist, wird der Menüpunkt als Button am oberen Rand der Menüs angezeigt.
  • Beispiel: Eintragen des Übermenüpunktes in u_menues
INSERT INTO `u_menues` ( `id` , `name` , `links` , `obermenue` , `menueebene` , `target` )
VALUES (NULL , 'Drucken', 'index.php?go=changemenue', '0', '1', NULL);

Fragen Sie anschließend die dabei erzeugte id in der Tabelle u_menues ab. z.B. 51

  • Beispiel: Eintragen des Untermenüpunktes zur Druckvorschau
INSERT INTO `u_menues` ( `id` , `name` , `links` , `obermenue` , `menueebene` , `target` )
VALUES (NULL , 'Druckvorschau', 'index.php?go=Druckausschnittswahl', '<id für Obermenü>', '2', NULL);

Wenn beim Speichern eine Validierung fehlschlägt, wird am entsprechenden Attribut eine Meldung angezeigt.

Validationmsg.png

Parametrisierter Menüpunkt-Link

Der Anwendungsfall ist immer in der Form "go=<anwendungsfall>" anzugeben. Außerdem können dahinter noch weitere Parameter angehängt werden, die den Anwendungsfall präzisieren bzw. Vorgaben machen (siehe beispielsweise auch Menüs,_Funktionen_u.a.):

  • "go_next": Springt in einen weiteren Anwendungsfall, wenn der Nutzer den zuerst genannten durchlaufen hat. Beispiel:
index.php?go=ALK-Flurstueck_Auswaehlen&go_next=Nachweisrechercheformular
  • "title": Übergibt dem Anwendungsfall einen anzuzeigenden Titel. Beispiel:
index.php?go=Layer-Suche&title=Fachdatensuche
  • "selected_layer_id": Übergibt dem Anwendungsfall eine Layer-ID, um diesen Layer aufzurufen. Beispiel:
index.php?go=neuer_Layer_Datensatz&selected_layer_id=50303974
index.php?go=Layer-Suche&selected_layer_id=50303997
  • "attributenames" + "values": Übergibt dem Anwendungsfall "go=neuer_Layer_Datensatz" einen Attributnamen, der bereits mit einem Wert vorausgefüllt sein soll. Weil mehrere Attribute und Werte übergeben werden können, sind sie mit eckigen Klammern und einer laufenden Nummer zu versehen. Beispiel:
index.php?go=neuer_Layer_Datensatz&selected_layer_id=50303787&attributenames[0]=gemeindeverband&values[0]=5351&attributenames[1]=status&values[1]=planung
  • "value": Übergibt dem Anwendungsfall "go=Layer-Suche" einen Wert für ein bestimmtes Attribut, der in der Maske bereits voreingetragen sein soll. Der Attributname wird in der Form "value_<attributname>" an den Parameter gehängt. Der Layer muss benannt sein. Beispiel:
index.php?go=Layer-Suche&selected_layer_id=50303452&value_jahr=2019
  • "operator": Übergibt dem Anwendungsfall "go=Layer-Suche" einen Operator für ein bestimmtes Attribut, wenn der Operator vom Standard-Operator abweichen soll. Der Attributname wird in der Form "operator_<attributname>" an den Parameter gehängt. Der Layer muss benannt sein. Beispiele:
index.php?go=Layer-Suche&titel=Fachdatensuche&selected_layer_id=50303999&operator_gemarkungsname=LIKE
index.php?go=Layer-Suche&selected_layer_id=50303787&value_gemeindeverband=5362&operator_gemeindeverband==
  • "anzahl": Übergibt dem Anwendungsfall "go=Layer-Suche" die anzuzeigende Trefferanzahl. Beispiel:
index.php?go=Layer-Suche&selected_layer_id=50303997&anzahl=100
  • "go_plus=Suchen": Führt die definierte Suche direkt aus, ohne dass der Nutzer das "go=Layer-Suche" durchläuft. Beispiel:
index.php?go=Layer-Suche&go_plus=Suchen&anzahl=20&selected_layer_id=50303645
  • Im Text des Menülinks können auch Layerparameter vorkommen. Diese werden wie gewohnt mit dem Präfix $ eingetragen. Das ist hilfreich z.B. zur Vorbelegung von Werten beim Anlegen neuer Datensätze. Verwendet werden können auch die Parameter $stelle_id, $user_id, $language und $hist_timestamp z.B:
index.php?go=neuer_Layer_Datensatz&selected_layer_id=105&attributenames[0]=kartiergebiet_id&values[0]=$kartiergebietfilter

Die Übersetzung dieser Parameter erfolgt vor der Ausgabe im Menü. In den Links sind also bereits die ersetzten Werte der Parameter zu sehen.

  • "overwrite_layer_name": Wird im Link eine Layersuche mit go=Layer-Suche_Suchen und selected_layer_id aufgerufen, kann der Parameter overwrite_layer_name angegeben werden um den Namen des Layers zu ändern. Das ist hilfreich, wenn Filterausdrücke angegen sind und sich dies in der Überschrift des Suchergebnisses ausdrücken soll. Das Beispiel gibt den Titel "Nur aktuelle Kartierungen" aus:
index.php?go=Layer-Suche_Suchen&selected_layer_id=105&overwrite_layer_name=Nur aktuelle Kartierungen&value_aktuell=1&operator_aktuell==

Zuordnen des Menüs zur Stelle

Die Zuordnung eines Menüpunktes zur Stelle erfolgt in der Stellenverwaltung:

 Stellenverwaltung > Stellen anzeigen > Stelle Ändern

Im Stellenformular zum Abschnitt Menüpunkte scrollen und dort auf der linken Seite erst die Menügruppe auswählen und darunter die Menüpunkte. Durch einen Klick auf den Button mit Doppel nach links, werden die ausgewählten Menüpunkte für die Stelle übernommen. Die Änderung muss noch mit dem Button Speichern (ganz unten im Formular) gespeichert werden.

Menüpunkte zur Stelle zuordnen

Die Zuordnung kann auch in phpMyAdmin direkt in der Tabelle u_menue2stelle erfolgen. In diesem Fall müssen aber neben dem Obermenüpunkt auch alle Unterpunkte extra zugeordnet werden. Zusätzlich ist auch die Tabelle u_menue2rolle zu bestücken. Besser ist es aber den Obermenüpunkt über die Stellenverwaltung der Stelle zuzuordnen.

Ändern der Zuordnung von Menüpunkten zu Obermenüs

Wenn ein Untermenü aus einem Obermenü entfernt werden soll, ist am besten zunächst in der Stellenverwaltung das ganze Menü zu entfernen.

Anschließend ändert man die Nummer in der Spalte obermenue in der Tabelle u_menues in die ID des neuen Obermenüpunktes. Wenn der noch nicht existiert, legt man diesen vorher an. Danach kann der Menüpunkt wieder hinzugefügt werden.

Stylen von Menüpunkten

Sollen die Menüpunkte anders als in der Standardeinstellung aussehen können die Klassen dieser überschrieben werden. Folgende Klassen sind in layouts/main.css.php definiert und können in eigenen Style-Dateien überschrieben werden:

  • hauptmenue: Hauptmenüpunkte, das sind solche, die keine Unterpunkte haben.
  • obermenue: Obermenüpunkte, das sind solche, die Unterpunkte haben.
  • untermenues: Div in dem die Untermenüpunkte enthalten sind.
  • untermenue: Untermenüpunkte.
  • ausgewaehltes-menue: Menüpunkt, bei dem die Parameter aus dem Attribut links mit denen in der URL oder Formularen übergebenen Parametern übereinstimmen. (sieht standardmäßig so aus als wäre nichts ausgewählt)

Multilingualität

kvwmap unterstützt für die Darstellung der Oberfläche und Sachdaten verschiedene Sprachen. Es wird ein Konzept verwendet in dem prinzipiell jede Sprache verwendet werden kann. Aktuell sind nicht noch nicht alle Texte der Oberfläche übersetzungsfähig. Bei Bedarf lassen sich diese aber auch einfach über das verwendete Konzept der Multilingualität übersetzen. Bei den Daten hängt die Multilingualität davon ab welche Texte die Sachdaten enthalten. Es wird unterschieden in feste und austauschbare Texte. Fest Texte können durch den Administrator vergeben werden und somit nur eine bestimmte Sprache unterstützt werden. Austauschbare Texte ändern sich wenn der Nutzer eine andere Sprache einstellt.

Unterstützte Sprachen

Der Admin stellt unter Administratorfunktionen in der Variable supportedLanguages die zu unterstützenden Sprachen ein.

ConstantSupportedLanguage.png

Die Sprachen werden kommasepariert im Array angegeben. Aktuell sind folgende Sprachen berücksichtigt und müssen auch so geschrieben werden.

  • english
  • german
  • low-german
  • polish
  • vietnamese

Diese Bezeichnungen müssen genau so für die im folgenden beschriebenen Language-Dateien verwendet werden. Weitere Sprachen, z.B. danish, können hinzugefügt werden. Für diese müssen dann aber jeweils auch die Language-Dateien angelegt werden, zusätzliche Felder im Datenmodell der MariaDB und die Auswahlliste bei den Optionen im Software-Core ergänzt werden. Anfragen dazu bitte auf die Wunschliste setzen. Die in der Variable supportedLanguages angegebenen Sprachen lassen sich dann unter Optionen durch den Benutzer auswählen.

optionsLanguages.png

Die Sprache wird so pro Stelle für die Nutzer in der Rolle hinterlegt. Beim Laden von kvwmap wird die Variable $GUI->user->rolle->language mit der vom Nutzer in der Stelle gewählten Sprache gesetzt und an folgenden Stellen verwendet.

Language-Dateien

Language-Dateien befinden sich im Verzeichnis layouts/languages und enthalten die Texte die in der Oberfläche verwendet werden sollen. Es gibt für jede Sprache eine globale Language-Datei (german.php, english.php, etc.) Des Weiteren kann es für jedes Snippets im Ordner layouts/snippets ein oder mehrere gleichnamige Language-Dateien geben mit dem Postfix _Sprache, z.B. layer_formular_german.php, layer_formular_english.php, etc). Aktuell gibt es für jedes Snippet mindestens die Language-Datei _german und ggf. _english. Für die anderen Sprachen sind die Lanuguage-Dateien noch nicht immer vorhanden, können aber bei Bedarf im Software-Core hinzugefügt werden. Die Language-Dateien bestehen in der Regel aus Zuweisungen von Texten zu Variablen. Die Variablen in den globalen Language-Dateien sind Klassenvariablen des GUI-Objektes und können somit überall verwendet werden. Darin sind Wörter und Texte enthalten die an verschiedenen Stellen der GUI verwendet werden wie Layer, Stelle, Nutzer oder Kurzwörter (und, in, oder). Die Variablen der Snippets sind lokal definiert und fangen in der Regel mit dem Prefix $str an.

Sprachen in der Layer-Definition

Wie an verschiedenen anderen Stellen der Dokumentation schon erwähnt, kann man die Variable $language in der Definition von Layern verwenden. Die Variable $language ist ein sogenannter globaler Layerparameter. Das heißt die Variable wird immer vor dem Lesen von Daten in der Datenbank durch den entsprechenden Wert des Nutzers ersetzt. Steht in dem Layer z.B. column_$language als Attributname im Query-Statement wird für die Abfrage z.B. column_german, column_english etc. verwendet.

Attribute für verschiedene Sprachen

In einigen Tabellen wie classes, layer, stelle u_groups gibt es für eine Spalte mehrere Language-Varianten, z.B. name_german, name_english, etc. Je nachdem welche Sprachen als supportedLanguage ausgewählt wurden kommen die Formularfelder in der Adminoberfläche zur Anzeige.

MultilingualLayerNameFormular.png

Auch die Attribute können dann verschiedene Namensspalten enthalten.

MultilingualAttributeNameFormular.png

Custom Language-Dateien

Da es vorkommen kann, dass die Übersetzungen von einem zum anderen System unterschiedlich ausfallen sollen, gibt es dafür auch ein Konzept. Es sieht vor, dass es im Ordner custom/layouts/languages jeweils Dateien geben kann, die Variablen enthalten können, die die Variablen in den Dateien im Ordner layouts/languages überschreiben. Durch das Überschreiben von Language-Variablen kann auch die Ausprägung in einer einzelnen Sprache angepasst werden. Soll z.B. im Layer-Editor unter Allgemeine Einstellungen nicht mehr "Query" stehen sondern "SQL für Sachdatenabfrage und Suche" und statt "Data" "SQL für Kartendarstellung" ist die Datei custom/layouts/languages/layer_formular.php mit folgenden Variablen anzulegen:

 $strData = "SQL für Kartendarstellung";
 $strPath = "SQL für Sachdatenabfrage und Suche";

Auf diese Weise lassen sich viele Texte in der GUI individuell anpassen. Damit die individuellen Language-Dateien auch greifen muss in den Snippets die Datei "languages/_include_language_files.php" zum Überladen der custom-Dateien Verwendung finden. Das wird nach und nach je nach Bedarf in die Snippets eingebaut. Wer Änderungen vornehmen möchte, meldet das bitte in der Wunschliste an. Außerdem muss die Konstante OVERRIDE_LANGUAGE_VARS aus der Gruppe Layout auf true gesetzt sein.

OVERRIDE LANGUAGE VARS.png

Druckrahmenverwaltung

Der Nutzer hat die Möglichkeit einen Kartenausschnitt in ein PDF zu exportieren. Das Layout des PDF-Dokuments kann mit Hilfe von verschiedenen, voher definierten Druckrahmen festgelegt werden. Im folgenden wird beschrieben, wie die Erstellung eines solchen Druckrahmens erfolgt.

Die Erstellung eines Druckrahmens erfolgt in der Druckrahmenverwaltung. Um diese aufrufen zu können, muss es einen entsprechenden Menüpunkt mit der go-Variable 'Druckrahmen' geben (Tabelle: u_menues). Außderdem muss dieser Menüpunkt der Stelle (Tabelle: u_menue2stelle) und dem Nutzer dieser Stelle (Tabelle: u_menue2rolle) zugeordnet werden. In der Druckrahmenverwaltung werden unter 'Druckrahmenauswahl' alle in der MySQL-Tabelle 'Druckrahmen' gespeicherten Rahmen in einer Auswahlliste angezeigt (1). Wählt man einen der Druckrahmen aus, werden die Parameter des Rahmens unter 'Druckrahmendaten' in einem Formular angezeigt. Ist noch kein Datensatz in der Tabelle 'Druckrahmen' vorhanden, sind sowohl die Auswahlliste als auch die Formularfelder leer.

--Markus Hentschel 12:55, 24. Apr 2007 (CEST) Damit sowohl in der Druckrahmenverwaltung als auch in der späteren Druckvorschau die textlichen Elemente angezeigt werden, müssen ImageMagick und Ghostscript auf dem Server installiert sein. Ist das der Fall, ist in der config.php der Parameter IMAGEMAGICK = 'true' zu setzen. Ghostscript ist zumindest bei SuSE schon installiert. Die Installation von ImageMagick mit JPEG-, PNG- und TIF-Unterstützung wird bei den HowTos erklärt.

Ein Druckrahmen besteht aus mehreren Elementen und hat mehrere Parameter. Als erstes sollte man festlegen, welches Format der Druckrahmen haben soll. Das Formularfeld 'Format' bietet hier 4 verschiedene Auswahlmöglichkeiten (2). Nachdem das Format festgelegt wurde, kann man einen Druckkopf für das Dokument definieren. Der Druckkopf dient in erster Linie als Kopf für das PDF-Dokument, kann aber auch als Hintergrund für das gesamte Dokument benutzt werden. Im Druckkopf sollten alle Informationen enthalten sein, die statisch, d.h. bei jedem PDF-Export konstant sind. Um einen Druckkopf in den Druckrahmen einzubinden, wählt man unter 'Druckkopf: wählen:' eine entsprechende Bilddatei aus (3). Wichtig ist, das diese Datei im Format 'jpg' vorliegt. --HolgerR 13:17, 22. Aug 2006 (CEST) Damit der Druckrahmen auf dem Server abgespeichert werden kann, muss der in der config.php festgelegte 'DRUCKRAHMEN_PATH' physisch auf dem Server vorhanden sein. Um die Datei hochzuladen und ihre Abmessungen einzulesen, sollte man den Druckrahmen an dieser Stelle schon einmal speichern. Zuvor sollte man jedoch noch einen Namen vergeben, damit der Druckrahmen identifiziert werden kann. Dies erfolgt über das Formularfeld 'Name' (4). Jetzt klickt man auf 'Als neuen Rahmen speichern' (5) und der Datensatz wird in die Tabelle 'Druckrahmen' geschrieben. Der Druckrahmen sollte sich nun auch in der Auswahlliste der Druckrahmen befinden.

Die Position und Größe des Druckkopfes kann nun über die entsprechenden Formularfelder x,y (6) und Breite, Höhe (7) festgelegt werden. Die Felder x und y bestimmen dabei den Abstand des Druckkopfes vom linken bzw. oberen Rand des PDF-Dokuments. Die Maßeinheit ist bei allen Positions- und Größenangaben 1 Pixel im PDF. Neben dem Formularfeld 'Format' ist die Auflösung des PDF-Dokuments in Pixeln angegeben (8). Nachdem die Position und Größe des Druckkopfes definiert wurde, klickt man auf 'Änderungen speichern' (9). In der Vorschau (10) sollte nun der Druckrahmen zu sehen sein. Sollte die Position bzw. Skalierung des Druckkopfes noch nicht zufriedenstellend sein, kann diese verändert werden und nach erfolgter Speicherung in der Vorschau überprüft werden.

Als nächsten Schritt sollte man die Position und Größe der Karte festlegen. Dies geschieht analog zum Druckkopf mit den Formularfeldern x und y (11) und Breite und Höhe (12). Nach Speicherung der Änderungen ist die Position der Karte in der Druckrahmenvorschau zu sehen und kann bei Bedarf korrigiert werden. Mit der Karte und dem Dokumentenkopf sind die beiden Hauptelemente des Druckrahmens, die zur korrekten Funktion benötigt werden, definiert worden.

Druckrahmena beschriftet.jpg Druckrahmenb beschriftet.jpg

Neben der Karte und dem Druckkopf lassen sich weitere Elemente zum Druckrahmen hinzufügen. Dazu gehören u.a. ein Freitext (13), der Maßstab (14), das aktuelle Datum (15), die Gemarkung (16), die Flur (17) sowie die Angabe eines ursprünglichen Maßstabes der analogen Flurkarte (18) (hier ist die Datenquelle jedoch noch nicht integriert). Außer dem Freitext sind alle diese Elemente dynamisch, d.h. sie werden vom System automatisch gesetzt. Im Druckrahmenformular lässt sich die Position und die Schriftgröße jedes Elementes definieren. Werden die Änderungen am Druckrahmen gespeichert, so erscheinen auch diese Elemente in der Vorschau und können bei Bedarf angepasst werden.

Zusätzlich zu der normalen Karte lässt sich bei Bedarf auch eine Referenzkarte zum Druckrahmen hinzufügen. Um dies tun zu können, sind mehrere Vorraussetzungen nötig. Zum einen muss ein Rahmen bzw. Hintergrund für die Referenzkarte festgelegt werden. Dieser Hintergrund liegt über der normalen Karte und unter der Referenzkarte. Dazu lässt sich analog zum Druckkopf über 'Ref.hintergrund: wählen:' (19) eine entsprechende jpg-Datei auswählen und durch Klick auf 'Änderungen speichern' hochladen. Die Position und Größe dieses Referenzkartenhintergrunds lässt sich dann über die entsprechenden Felder anpassen (20). Nach der Festlegung des Referenzkartenhintergrunds kann man die Position und Skalierung der Referenzkarte definieren (21). Für die Referenzkarte muss man außerdem noch den Zoomfaktor einstellen, der festlegt, umwieviel diese Karte den Ausschnitt der normalen Karte vergrößert. Ein Zoomfaktor von -2 bewirkt hier beispielsweise, dass die Referenzkarte einen 2mal so großen Kartenausschnitt zeigt. Um festlegen zu können, welche Layer die Referenzkarte zeigen soll, wird für die Darstellung dieser Karte eine separates Mapfile verwendet. Der Pfad zu diesem Mapfile wird in der config.php über die Konstante 'REFMAPFILE' festgelegt. So ist es z.B. möglich, mittels der Referenzkarte eine Flurübersicht zu erzeugen, wie sie in ALK-Auszügen verwendet wird.

Es ist auch möglich amtliche Kartenauszüge über die Call-Schnittstelle der DHK zu erzeugen. Wenn in der config.php die 3 Verbindungsparameter DHK_CALL_URL, DHK_CALL_USER und DHK_CALL_PASSWORD gesetzt sind, erscheint im Kartendrucklayouteditor ein Auswahlfeld "DHK-Call-Schnittstelle". Hier kann die Art des amtlichen Kartenauszugs festgelegt werden. Außerdem müssen die korrekte Kartenhöhe und -breite und das Format gesetzt sein.

Um einen Kartenausschnitt unter Benutzung eines zuvor definierten Druckrahmens in ein PDF zu exportieren, muss es einen entsprechenden Menüpunkt mit der go-Variablen 'Druckausschnittswahl' geben (Tabelle: u_menues). Außderdem muss dieser Menüpunkt der Stelle (Tabelle: u_menue2stelle) und dem Nutzer dieser Stelle (Tabelle: u_menue2rolle) zugeordnet werden.

Wie mit Hilfe der in der Stelle zugeordneten Druckrahmen gedruckt werden kann ist unter dem Punkt Benutzung von kvwmap beschrieben, siehe (Drucken in PDF).

Zugriffsstatistik

Mit dem Anwendungsfall go=StatistikAuswahl läßt sich die Statistik der Zugriffe abfragen und anzeigen. Bei der Abfrage kann man die Intervallart für den Zeitraum auswählen (Monat, Woche, Tag, Zeitraum), den Zeitraum je nach Intervallart, die Stelle und den Nutzer.

Durch die Auswahl zwischen Stelle und Nutzer kann die Statistik so angepasst werden, dass die Zugriffe pro Layer und Stelle oder die Zugriffe pro Layer und Nutzer angezeigt werden können. Wählt man hierbei Stelle und Nutzer aus, werden die Zugriffe pro Layer durch den Nutzer über eine bestimmt Stelle angezeigt.

Die Anzeige der Statistik ist unterteilt in die Zugriffe auf Layer, Karten-Drucke, Buch-Auszüge, CSV-Exporte und Vektor-Exporte

StatistikAuswahl.png StatistikAnzeige.png

Welche Layer geloggt werden sollen wird für jeden Nutzer pro Stelle und Layer in der Tabelle u_rolle2used_layer im Attribut logconsume mit Wert 1 eingetragen, siehe [[1]].

Datenbankadministration

Referenz zur MySQL-Datenbank von kvwmap

Dieser Abschnitt enthält eine Beschreibung der Feldinhalte zu Nutzerdaten und Layern, die in der MySQL-Datenbank von kvwmap gespeichert werden.

Die Referenz entspricht der kvwmap-Version 2.4

Ein Tabellen-Beziehungsmodell (ER-Diagramm) ist als PDF-Datei verfügbar.

Eine ausführliche deutschsprachige Beschreibung aller MapFile-Parameter, die in der Datenbank abgebildet werden, findet sich unter http://mapserver.org/de/mapfile/. Das englische Original ist zu finden unter http://mapserver.org/mapfile/index.html#mapfile.


Alle nummerierten Parameter entsprechen den MapScript-Definitionen. Diese Definitionen können in der map.h der mapServer-Source im Abschnitt "General enumerated types" nachgesehen werden.


Tabelle "classes"

Jede Class wird genau einem Layer zugeordnet. Mit der Class können Daten, die in einem Shape liegen, nach bestimmten Kriterien selektiert und in unterschiedlichen Ausgestaltungen präsentiert werden.

Name

Der Name der Class wird in der Legende angezeigt.

Layer_ID

Die entsprechende ID aus der Tabelle "layer".

Expression

Wenn der Layer mehrere Classes enthält, regelt "Expression" die Zugehörigkeit eines Features zur jeweiligen Class. Wenn kein Ausdruck vorhanden ist, werden alle Features einer Class zugeordnet.

Kvwmap lässt momentan nur logical Expressions zu. Dabei muss das Attribut (Spaltenüberschrift in der DBF-Tabelle des Shapes) explizit angegeben werden. Die Notation erfolgt so:

  • Die komplette Expression wird grundsätzlich mit einer runden Klammer ( ) versehen.
  • Das Attribut wird in eckige Klammern [ ] gesetzt. Handelt es sich um das Attribut eines Shapes, ist darauf zu achten, dass es in Großbuchstaben geschrieben wird. Handelt es sich um das Attribut einer PostGIS-Tabelle, ist darauf zu achten, dass es in Kleinbuchstaben geschrieben wird.
  • Wird eine Zeichenkette abgefragt, wird sowohl die eckige Klammer des Attributs als auch der Ausdruck in einfache Anführungszeichen ' ' gesetzt.
  • Folgende logische Operatoren werden unterstützt: =, >, <, <=, >=, =, lt (lower than), gt (greater than), ge (greater equal), le (lower equal), eq (equal), ne (not equal).
  • logische Ausdrücke können mit "AND" bzw. "OR" beliebig verschachtelt werden.

Beispiel:

([EINWOHNERZAHL] >= 20000 AND '[ART]' ne 'Stadt')

drawingorder

Darstellungsreihenfolge der Classes in der Legende. Wenn nichts angegegeben wird, werden die Classes alphanumerisch sortiert.

text

Möchte man einen feststehenden Text für alle Objekte der class erzeugen, gibt man diesen Text in Hochkommata an.

Tabelle "colors"

speichert Farben im RGB-Schema, die für die (normale und klassifizierte) Suchergebnisanzeige verwendet werden. Farbverläufe kann man z.B. hier erstellen: [2] oder [3]

Tabelle "datendrucklayouts"

speichert layerbezogen die Sachdaten-Drucklayouts.

Tabelle "ddl2freitexte"

speichert die Freitexte eines Sachdaten-Drucklayouts.

Tabelle "ddl2stelle"

weist das Sachdaten-Drucklayout einer Stelle zu.

Tabelle "ddl_elemente"

Speichert die Elemente des Sachdaten-Drucklayouts, d.h. die zu druckenden Attribute des Layers mit ihrer layoutspezifischen Gestaltung.

Tabelle "druckausschnitte"

speichert Kartenausschnitt, Druckmaßstab und verwendeten Druckrahmen, die ein User beim Drucken für spätere Wiederverwendung speichern kann. Wird von kvwmap automatisch gefüllt.

Tabelle "druckfreibilder"

speichert die Grafiken, die in der Druckrahmenverwaltung einem Druckrahmen zugeordnet werden. Wird von kvwmap bei Benutzung des entsprechenden Menüs gefüllt.

Tabelle "druckfreitexte"

speichert die Freitexte, die in der Druckrahmenverwaltung einem Druckrahmen zugeordnet werden. Wird von kvwmap bei Benutzung des entsprechenden Menüs gefüllt.

Tabelle "druckrahmen"

speichert die Parameter der einzelnen Druckrahmen. Diese Tabelle wird von kvwmap bei Benutzung des entsprechenden Menüs gefüllt.

Tabelle "druckrahmen2freibilder"

ordnet die Grafiken aus der Tabelle druckfreibilder den Druckrahmen zu und enthält die Position der Bilder im Druckrahmen sowie die Größe und den Drehwinkel die für die Darstellung der Bilder im Druckrahmen verwendet werden sollen. Muss zur Zeit noch per Hand eingetragen werden. Wenn die Bilder größer sind, als die Größenangaben in dieser Tabelle, wird das Bild gestaucht und erhält damit eine höhere Auflösung.

Tabelle "druckrahmen2freitexte"

ordnet die Texte ausder Tabelle druckfreitexte den Druckrahmen zu. Wird von kvwmap bei Benutzung des entsprechenden Menüs gefüllt.

Tabelle "druckrahmen2stelle"

ordnet die Druckrahmen den Stellen zu. Wird von kvwmap bei Benutzung des entsprechenden Menüs gefüllt.

Tabelle "labels"

MapFile-Doku MapScript-Doku

Sämtliche Parameter dieser Tabelle werden in der MapServer Referenz unter den o.a. Internetadressen ausführlich beschrieben. Hier sollen nur die "Schalter" benannt werden:

font

Gibt die Schriftart an. Der font muss im Ordner "fonts" enthalten und in der fonts.txt eingetragen sein!

type

  • "0" = Truetype
  • "1" = Bitmap

Standardmäßig wird "0" verwendet.

color

Farbe der Beschriftung. Wird angegeben in "R G B" (3 Zahlen mit Leerzeichen getrennt: "125 200 50").

outlinecolor

Angabe einer Farbe, um Beschriftungen zu umranden. Wird angegeben in "R G B" (3 Zahlen mit Leerzeichen getrennt: "125 200 50").

shadowcolor

Erzeugt eine Kopie der Beschriftung in der angegebenen Farbe. Diese wird jedoch nur sichtbar in Kombination mit shadowsizex und shadowsizey, da sie sonst von der Beschriftung verdeckt wird.
Wird angegeben in "R G B" (3 Zahlen mit Leerzeichen getrennt: "125 200 50").

shadowsizex, shadowsizey

Verschiebt die mit shadowcolor erzeugte Kopie der Beschriftung in x- bzw. y-Richtung und erzeugt dadurch eine Art Schlagschatten.

backgroundcolor

Erzeugt ein Rechteck mit der angegebenen Farbe um den Text herum. Wird angegeben in "R G B" (3 Zahlen mit Leerzeichen getrennt: "125 200 50").

backgroundshadowcolor

Erzeugt eine in alle Richtungen um 1 Pixel vergrößerte Kopie des Rechtecks, das unter backgroundcolor erzeugt wurde und legt es optisch hinter das Original. Ohne durch die Verschiebung mit Hilfe von backgroundshadowsizex und backgroundshadowsizey lässt sich somit ein 1 Pixel breiter Rahmen in der angegebenen Farbe erzeugen.
Wird angegeben in "R G B" (3 Zahlen mit Leerzeichen getrennt: "125 200 50").

backgroundshadowsizex, backgroundshadowsizey

Verschiebt die mit backgroundshadowcolor erzeugte Kopie des Rechtecks in x- bzw. y-Richtung und erzeugt dadurch eine Art Schlagschatten.

size

Angabe der Schriftgröße. Bei skalierbarer Beschriftung bestimmt size die Schriftgröße für den unter symbolscale angegebenen Massstab.

Hinweis: Damit die Darstellung skalierbar wird, müssen in der Tabelle used_layer ein Wert für symbolscale und in der Tabelle 
layer die Werte für labelminscale und labelmaxscale gesetzt sein.

minsize, maxsize

Angabe der minimalsten bzw. maximalsten Größe der Texte des Layers bei skalierbarer Darstellung.
minsize bestimmt dabei die Größe für den unter labelmaxscale angegebenen Massstab und maxsize die für den unter labelminscale angegebenen Massstab.

Hinweis: Damit die Darstellung skalierbar wird, müssen in der Tabelle used_layer ein Wert für symbolscale und in der Tabelle 
layer die Werte für labelminscale und labelmaxscale gesetzt sein.

position

  • "0" = Die Beschriftung befindet sich links über dem Bezugspunkt
  • "1" = Die Beschriftung befindet sich rechts unter dem Bezugspunkt
  • "2" = Die Beschriftung befindet sich rechts über dem Bezugspunkt
  • "3" = Die Beschriftung befindet sich links unter dem Bezugspunkt
  • "4" = Die Beschriftung befindet sich rechts vom Bezugspunkt
  • "5" = Die Beschriftung befindet sich links vom Bezugspunkt
  • "6" = Die Beschriftung befindet sich über dem Bezugspunkt
  • "7" = Die Beschriftung befindet sich unter dem Bezugspunkt
  • "8" = Die Beschriftung befindet sich genau auf dem Bezugspunkt
  • "9" = "Auto", kalkuliert eine Beschriftungsposition, die keine andere Beschriftung beeinträchtigen wird.

offsetx, offsety

Versetzt den Text aller Objekte des Layers in X- bzw. Y-Richtung um den angegebenen Betrag (negative Werte sind auch möglich).

angle, autoangle

"angle" speichert einen festen Winkel, unter dem alle Texte des Layers gedreht werden. "autoangle = 1" dreht jeden einzelnen Text nach dem Winkel, der zum entsprechenden Objekt in dem Attribut gespeichert ist, das in der Tabelle layer unter "labelangleitem" gespeichert ist. Default ist 0.

buffer

Erzwingt einen Leerraum um alle Texte dieses Layers in Pixeln. Default ist 0.

antialias

Kantenglättung. Funktioniert nur bei "Truetype".

  • "0" = ja
  • "1" = nein

minfeaturesize, maxfeaturesize

Wird in Pixeln eingegeben. Wenn die Größe eines Objektes (in Pixeln) unter der eingetragenen Grenze liegt, wird der Text des Objekts nicht mehr gezeichnet. Der Eintrag "auto" bewirkt die Beschriftung ausschließlich der Objekte, die größer sind als der zugehörige Text.

partials

Zeigt Texte, die vom Kartenrand abgeschnitten werden.

  • "0" = ja: auch Teile des Textes sollen noch angezeigt werden.
  • "1" = nein: wenn der Text angeschnitten wird, ist er nicht mehr zu sehen.

Wird nichts angegeben, wird standardmäßig "0" gesetzt.

Wenn the_force und partials jeweils den Wert 1 haben, hat the_force Vorrang und über den Kartenrand herausragende Texte werden angezeigt.

wrap

Ermöglicht es, Zeilenumbrüche in Texte einzufügen. Als "wrap" ist der Dezimalwert des entsprechenden ASCII-Zeichens (= "ANSI Character") einzugeben, der dann durch einen Zeilenumbruch ersetzt wird, z.B. "35" für das Zeichen "#".

the_force

Zwingt Beschriftungen zur Anzeige, ohne Rücksicht auf Kollisionen.

  • "0" = nein
  • "1" = ja

Wird nichts angegeben, wird standardmäßig "0" gesetzt.

Wenn the_force und partials jeweils den Wert 1 haben, hat the_force Vorrang und über den Kartenrand herausragende Texte werden angezeigt.

Tabelle "layer"

Jeder Layer beinhaltet einen thematisch logischen und abgegrenzten Teilaspekt der Gesamtdatenmenge. Dabei wird in Raster-, Punkt-, Linien- und Flächenlayer unterschieden. Layer (soweit nicht Rasterlayer) können in kvwmap aus einer PostgreSQL/PostGIS-Datenbank stammen, als Shapes vorliegen oder als WMS/WFS bezogen werden.

Name

Der Name des Layers wird in der Legende angezeigt. Wird kein Name vergeben, wird dieser Layer nicht in der Legende angezeigt. Layernamen sollten keine Sonderzeichen enthalten, Umlaute und Leerzeichen sind dagegen kein Problem.

Datentyp

  • "0" = Punktlayer ("Point")
  • "1" = Linienlayer ("Line")
  • "2" = Flächenlayer ("Polygon")
  • "3" = Rasterlayer ("Raster")
  • "4" = Beschriftungslayer ("Annotation", erzeugt nur Beschriftungen)
  • "5" = Abfragelayer ("Query", wird nicht gezeichnet, kann nur abgefragt werden)
  • "6" = Kreislayer ("Circle", erzeugt Ellipsen durch die Angabe eines Rechtecks)

Ausführlichere Angaben, z.B. zum Ort der Beschriftung, siehe die deutschsprachige Mapfile-Referenz.

Der Datentyp muss nicht derselbe Typ sein wie das Feature selbst. Eine Polygon Feauture kann beispielsweise auch als Punkt-, Linien- oder Abfragelayer generiert werden.

Gruppe

Layer werden einer Gruppe zugeordnet. In der Legende erscheinen sie dann unter dieser Gruppenbezeichnung.

Query

Dieses Feld enthält vordefinierte SQL-Statements für die Sachdatenabfrage von PostGIS-Layern. Der einfachste Fall ist die Abfrage auf eine Tabelle ohne Bedingungen:

SELECT * FROM ax_gebaeude WHERE 1=1

Wichtig: Die WHERE-Bedingung muss immer mit angegeben werden. Gibt es keine Bedingung, wird "WHERE 1=1" angehängt.

Die Auswahl und die Reihenfolge der Attribute in der Abfrage bestimmt die Anzeige und Reihenfolge der Attribute in der Sachdatenanzeige. Deswegen sollten die Attribute immer explizit genannt werden:

SELECT gml_id, gebaeudefunktion, name, wkb_geometry FROM ax_gebaeude WHERE endet IS NULL

Wichtig: Soll der Nutzer von der Sachdatenanzeige zum Objekt in der Karte zoomen können, muss das Geometrie-Attribut in der Query angegeben werden.

Die Abfragen können beliebigen Umfang annehmen, also z.B. auch mehrere Tabellen verknüpfen oder die Sachdatenanzeige sogar aus einer anderen Tabelle erzeugen als der Tabelle, die für die Kartendarstellung in Data verwendet wird.

SELECT g.gml_id, array_to_string(array(select gm.bezeichnung||', '||l.bezeichnung||' '||h.hausnummer from 
alkis.ax_lagebezeichnungmithausnummer h, alkis.ax_gemeinde gm, alkis.ax_lagebezeichnungkatalogeintrag l where 
h.gemeinde = gm.gemeinde and gm.endet is not null and h.gemeinde = l.gemeinde and h.lage = l.lage and l.endet 
is not null and h.gml_id=any(g.zeigtauf)),' ') as lagemithausnummer, f.bezeichner as gebaeudefunktion, 
g.name, g.wkb_geometry 
FROM ax_gebaeude g, ax_gebaeude_funktion f
WHERE endet IS NULL AND f.wert = g.gebaeudefunktion

Wichtig: Im Gegensatz zum Data-Eintrag wird in der Query der Schema-Name nicht angegeben (das passiert in schema). Nur in Subqueries oder wenn Tabellen aus anderen Schemata herangezogen werden, muss der Schema-Name dieser Tabellen mit angegeben werden.


Schwierigkeiten bereiten möglicherweise komplexe SQL-Befehle, z.B. wenn oids uneindeutig werden. In diesen Fällen bietet sich an, die eigentliche Abfrage in einen View zu schreiben und in Query (vielleicht auch in Data) auf diesen View zuzugreifen. Möglicherweise ist es beim View dann allerdings nötig, Rules zu schreiben, die die INSERT-, UPDATE- und DELETE-Anweisungen durchführen.

Die Sachdatenanzeige erfolgt über den Generischen Layereditor. Bei besonderen Darstellungen kann alternativ auch ein Template angelegt werden, dessen Dateiname im Feld "template" der Tabelle used_layer eingetragen wird.

Data

  • Bei Anbindung eines Shapes der Name des Shapes ohne Endung.
  • Bei Daten aus einer PostGIS-Tabelle wird die Geometriespalte und der Tabellenname angegeben, Beispiel:
the_geom from bplan as foo using unique oid using srid=25833

Genau wie bei Query können auch bei Data komplexe Abfragen in Form eines SELECT definiert werden. Dieses SELECT wird in eine Klammer gesetzt und muss alle für den Mapserver notwendigen Elemente aufführen: Das unique-Attribut (üblicherweise oid), eventuelle Beschriftungs- und Klassifizierungsattribute und natürlich das Geometrie-Attribut. Befinden sich die abgefragten Tabelle in einem anderen Schema als public, muss der Schema-Name mit angegeben werden.

Das eingeschlossene SQL-Statement kann auch in einem View gespeichert werden.

schema

Speichert den Schemanamen in der Postgre-DB, in der die Tabelle liegt. Default ist "public".

documentpath

speichert die Angabe eines Pfades für einen Ordner, in dem layerbezogen die Dokumente abgelegt werden sollen. Wird hier nichts angegeben, ist CUSTOM_IMAGE_PATH aus der config.php der default.

tileindex

Wird nur bei Rasterlayern gesetzt. Wenn Rasterbilder gekachelt vorliegen und in einem Bildkatalog indiziert wurden, wird der Name des Index-Shapes hier angegeben. Die Eingabe im Feld "Data" entfällt. Hinweis: Die Indizierung kann z.B. mit dem Werkzeug gdaltindex aus der GDAL-Installation erfolgen.

tileitem

Wird nur bei indizierten Rasterlayern gesetzt. Attributname (= Spaltenüberschrift im Index­shape), in dem die Pfade zu den einzelnen Bildern stehen.

labelangleitem

Enthält den Attributnamen der Sachdaten des Layers, der die Winkel der Texte enthält. Braucht nur ausgefüllt werden, wenn beschriftet werden soll und der Text nach bestimmten Werten in den Sachdaten ausgerichtet werden soll.

labelitem

Wird nur gesetzt, wenn eine Beschriftung erzeugt werden soll. Attributname (= Spaltenüberschrift im entsprechenden Shape), aus dem die Beschriftung entnommen werden soll.

labelmaxscale

Größte Maßstabszahl, über die hinaus der Layer nicht mehr beschriftet wird (z.B. 400.000)

labelminscale

Kleinste Maßstabszahl, unterhalb der der Layer nicht mehr beschriftet wird (z.B. 500)

labelrequires

macht die Beschriftung abhängig von der Darstellung der Beschriftung eines anderen Layers, siehe Feld "requires" in der Tabelle used_layer.

connection

Die Angabe der connection entfällt bei Shapefiles. Die connection ist im Falle einer Datenbank die Zeichenkette der Datenbankverbindung, bestehend aus Benutzername, Passwort, Datenbankname, Hostnamen, Name des Vorgangs. Beispiel:

user=kvwmap password=****** dbname=kvwmapsp159 host=localhost port=5432

Achtung, bei der Verwendung von kvwmap in einem Docker Container, der auf dem Image kvwmap-server basiert, muss bei host nicht localhost, sondern pgsql angegeben werden. pgsql wird in diesem Fall in der Datei /etc/hosts aufgelößt in die IP des Containers in dem die Postgre-Datenbank läuft.

In der connection kann auch ein Dienst angegeben werden. Vom OGC-konformen Aufruf wird der "feste" Teil eingegeben, die änderbaren Parameter SRS, WIDTH, HEIGHT, BBOX und FORMAT werden von kvwmap bei jedem Aufruf an die in connection angegebene URL angehängt. Beispiel für eine WMS-Angabe:

http://geoportal.lk-nvp.de:8080/cgi-bin/mapserv?MAP=/home/fgs/fgs/www/wms/gemarkungen_fluren.map&REQUEST=getMap&VERSION=1.1.1&LAYERS=Gemarkungen,Fluren,Gemarkungsnamen,Flurnummern

Und so sieht der Aufruf beispielsweise vollständig aus:

 http://geoportal.lk-nvp.de:8080/cgi-bin/mapserv? \\
 MAP=/home/fgs/fgs/www/wms/gemarkungen_fluren.map& \\
 REQUEST=getMap& \\
 VERSION=1.1.1& \\
 LAYERS=Gemarkungen,Fluren,Gemarkungsnamen,Flurnummern& \\
 SRS=EPSG:2398& \\
 WIDTH=600&HEIGHT=500& \\
 BBOX=4550000,6010000,4560000,6018000& \\
 FORMAT=image/png
 
(Zur Übersichtlichkeit ist der Aufruf in mehrere Zeilen aufgetrennt.)

printconnection

Erlaubt die Angabe eines WMS, der im Druck für diesen Layer verwendet wird.

connectiontype

Der connectiontype ist die Einstellung des Verbindungstyps, z.B.:

  • "6" = postgis
  • "7" = WMS
  • "9" = WFS

Die Angabe des connectiontypes kann bei Shapefiles entfallen.

classitem

Attributname (= Spaltenüberschrift im entsprechenden Shape), aus dem die Class erzeugt werden soll.

filteritem

Angabe zum Einsatz der "Filter"-Ausdrücke aus der Tabelle "used_layer". Im Regelfall wird kein Filter definiert, dann sollte das Feld mit "id" gefüllt sein. Wird der Layer aus einer Sicht erzeugt, muss ein in der Sicht verwendeter Attributname (z.B. "objnr") eingetragen werden.

tolerance

Die Empfindlichkeit von punktbasierten Abfragen. Wie weit darf man den Punkt verfehlen, damit er dennoch gefangen wird? Gilt in kvwmap bei der Abfrage von PostGIS-Layern auch beim Aufziehen von Rechteckboxen.

toleranceunits

Einheit der Tolerance-Werte. Standardmäßig ist "pixels" gesetzt. Für die Abfrage von PostGIS-Layern wird die Angabe von "tolerance" mit der aktuellen Pixelgröße multipliziert. Ist "toleranceunits" leer wird auch die Pixelgröße verwendet, ist sie "meters" wird die "tolerance" mit 1 multipliziert.

epsg_code

Die Angabe des Koordinatensystems, in dem die Daten dieses Features vorliegen. Stimmt das originäre Koordinatensystem nicht mit dem Ausgabekoordinatensystem überein, dass im Feld "epsg_code" in der Tabelle Rolle definiert wird, werden die Koordinaten vom MapServer on-the-fly transformiert. Dieses Feld hat keine Bedeutung bei WMS-Layern. Dort wirkt das Feld ows_srs.

template

Defaulttemplate, der beim Einfügen des Layers in eine Stelle übernommen wird.

queryable

Defaultwert für die Abfragbarkeit des Layers, der beim Einfügen des Layers in eine Stelle übernommen wird.

transparency

Defaultwert für die Transparenz des Layers, der beim Einfügen des Layers in eine Stelle übernommen wird.

drawingorder

Defaultwert für die Zeichenreihenfolge des Layers, der beim Einfügen des Layers in eine Stelle übernommen wird.

minscale, maxscale

Defaultwerte für den Maßstabsbereich des Layers, die beim Einfügen des Layers in eine Stelle übernommen werden.

offsite

Defaultwert für den transparent zu zeichnenden RGB-Farbwert, der beim Einfügen des (Raster-)Layers in eine Stelle übernommen wird.

ows_srs

Angabe des Ausgabekoordinatensystems, wenn der Layer als WMS bzw. WFS von kvwmap zur Verfügung gestellt werden soll oder wenn der Layer einen externen WMS einbindet, in der Form:

"EPSG:<code>"

Es können alle Koordinatenreferenzsysteme angegeben werden, die der eigene kvwmap-Dienst anbieten soll bzw. alle Koordinatenreferenzsysteme, die die dienstanbietende Stelle im getCapabilities anbietet, in der Form:

"EPSG:<code1> EPSG:<code2> EPSG:<code3>"

Hat der Nutzer in seinen Optionen eine der angegebenen Kartenprojektionen ausgewählt, wird der Dienst in diesem EPSG angefordert (horizontale Texte und Linien erscheinen horizontal). Hat der Nutzer eine Kartenprojektion ausgewählt, die in diesem Feld nicht aufgelistet ist, transformiert der Mapserver das gelieferte Kartenbild (horizontale Texte und Linien erscheinen u.U. schräg).

wms_name

Angabe des Layernamens, wenn der Layer als WMS bzw. WFS zur Verfügung gestellt werden soll. Wird das Feld freigelassen, wird der im Feld "Name" verwendete Layername ausgegeben. Hinweis: Bei Layernamen, die deutsche Sonderzeichen enthalten, empfiehlt sich die Angabe eines WMS-Namens ohne deutsche Sonderzeichen.

wms_server_version

kvwmap unterstützt alle WMS-Versionen bis einschließlich 1.3.0

wms_format

Das Rasterformat des Ausgabebildes, wenn der Layer als WMS bzw. WFS zur Verfügung gestellt werden soll.

wms_connectiontimeout

Zeitspanne, nach der der WMS als "nicht verfügbar" klassifiziert wird und der Verbindungsaufbau auf diesen Layer abgebrochen wird.

wms_auth_username

Basiert der Layer auf einem passwortgeschützten WMS, wird hier der entsprechende Username gespeichert.

wms_auth_password

Basiert der Layer auf einem passwortgeschützten WMS, wird hier das entsprechende (verschlüsselte) Passwort gespeichert.

wfs_geom

Gibt bei WFS-Diensten mit mehreren Geometrie-Attributen dasjenige Attribut an, das Mapserver als Geometrie verwenden soll.

selectiontype

"radio" erzeugt in der Legende einen Radiobutton statt des üblichen Häkchenfeldes zum Ein- oder Ausschalten des Layers. Sind alle Layer einer Gruppe "radio", so kann also immer nur ein Layer in dieser Gruppe angeschaltet sein. Default ist NULL.

querymap

"1" = in der Sachdatenanzeige wird eine kleine Übersichtskarte mit dem Objekt gezeichnet. Default ist 0.

logconsume

Definiert, ob Zugriffe auf diesen Layer geloggt werden sollen:

  • "0" = Dieser Layer soll generell nicht geloggt werden
  • "1" = Dieser Layer kann geloggt werden.

Ob die Zugriffe auf die mit "1" gekennzeichneten Layer tatsächlich in der Tabelle u_consume2layer protokolliert werden, entscheidet die Einstellung des Feldes "logconsume" der jeweiligen Stelle, in der dieser Layer aufgerufen wird.

kurzbeschreibung

Freitext zur Beschreibung des Layers und dessen Inhalt. Kann thematische, zeitliche und räumliche Beschreibungen enthalten. Bei WMS entspricht das dem was in Abstract steht.

datasource

Quellenangabe zu den Daten, die in dem Layer angezeigt werden.

dataowner_name, dataowner_email, dataowner_tel

Name, E-Mail-Adresse und Telefonnummer des Eigentümers der Daten

uptodateness

Aktualität der Daten, die im Layer angezeigt werden.

updatecycle

Angaben darüber wann, wie oft und wie die Daten aktualisiert werden.

metadatalink

Ein Link zu einem Dokument in dem weiterführende Beschreibungen zum Layer oder dessen Daten enthalten sind, z.B. zu einem Metadatendokument in einem Metainformationssystem oder dem Capabilities-Dokument eines Dienstes.

version

Ein String zu Versionierung des Layers. Wird für die Synchronisierung mit kvmobile verwendet. Neue Versionen müssen bei alphanumerischer Sortierung weiter unten sein. z.B. 1.0.0 ist älter als 1.1.0

comment

Ein Kommentar zum Layer. Dieser wird z.B. dafür verwendet um dem Client mitzuteilen was sich an der Konfiguration des Layers geändert hat und warum. Ansonsten kann der Kommentar auch einfach nur für die Administratoren verwendet werden.

Tabelle "layer_attributes"

In dieser Tabelle wird definiert, wie die Attribute in der Sachdatenanzeige dargestellt werden. Wie auf die Attribute in den einzelnen Stellen zugegriffen werden darf, wird in der Tabelle layer_attributes2stelle definiert.

Jedes Attribut eines Layers kann im Generischen Layereditor angezeigt werden, wenn es im Query-Statement genannt wird.

name

Attributname, wie er im Query-Statement aus der Datenbank geholt wird (also nicht unbedingt identisch mit dem Tabellenattributnamen).

real_name

Tatsächlicher Tabellen-Attributname auf Datenbankebene.

tablename

Tatsächlicher Tabellen-Name auf Datenbankebene.

table_alias_name

Tabellen-Name, wie er im Query-Statement aus der Datenbank geholt wird (i.d.R. als Alias).

type

Datentyp des Attributes, wie er im Query-Statement aus der Datenbank geholt wird.

geometrytype

Geometrietyp des Attributs, wenn es vom Typ geometry ist.

constraints

Einschränkungen, die auf Datenbankebene in der Tabelle gesetzt sind.

nullable

'1', wenn das Attribut auf Datenbankebene NOT NULL ist. Default '0'.

length

Einschränkung der Zeichenkettenlänge auf Datenbankebene.

decimal_length

Begrenzung der Anzahl der Nachkommastellen von Zahlen.

default

Standardwerte auf Datenbankebene, die bei Nichtausfüllen automatisch gesetzt werden bzw. von kvwmap im Generische Layereditor als Vorgabewert bei einem neuen Datensatz automatisch vorgeschlagen werden. Betrifft auch Vorgaben aus Sequenzen.

form_element_type

Beschreibung des Formelements, in dem das Attribut angezeigt wird:

  • Text
  • Textfeld
  • Auswahlfeld
  • Autovervollständigungsfeld
  • Checkbox
  • Geometrie
  • SubFormPK
  • SubFormFK
  • SubFormEmbeddedPK
  • Time
  • Dokument
  • Link
  • dynamicLink
  • User
  • UserID
  • Stelle
  • StelleID
  • Fläche
  • Länge
  • Zahl
  • mailto

SubFormPK und SubFormFK dienen der Erzeugung verschachtelter Tabellen. Time, User, UserID, Stelle, StelleID, Fläche und Länge werden von kvwmap automatisch gefüllt. Weiter Informationen siehe die Dokumentation zum Generischen Layereditor.

options

Zuweisung bestimmter Vorgabewerte für den Attributtyp Auswahlfeld

alias

Zuweisung von (langschriftlichen) Attributnamen für die Anzeige im Generischen Layereditor zur besseren Lesbarkeit.

alias_<language>

Weitere Aliasnamen in anderen Sprachen.

tooltip

Der hier gespeicherte Text erscheint in der Sachdateneinzeige des GLE als Tooltipp, wenn man mit dem Cursor über den Attributnamen fährt.

group

Bezeichnung der Gruppe zu der das Attribut gehören soll. Die definition der Attribute im Layer sollte sein, dass Attribute, die den gleichen Gruppennamen haben direkt nebeneinander liegen.

arrangement

'0': Das Attribut wird unter dem vorhergehenden angezeigt '1': Das Attribut wird rechts neben dem vorherigen angezeigt

labeling

NULL oder '0': Die Beschriftung des Attributes wird links neben dem Wert angezeigt. '1': Die Beschriftung des Attributes wird über dem Wert angezeigt. '2': Die Beschriftung des Attributes wird garnicht angezeigt.

raster_visibility

NULL oder '0': Attribut wird im Rastermodus nicht dargestellt. '1' Das Attribut wird im Rastermodus dargestellt.

mandatory

'1': es handelt sich um ein Pflichtattribut in der Layersuche, das ausgefüllt werden muss. Default ist '0'.

quicksearch

Gibt an ob das Attribut bei der Schnellsuche verwendet werden soll.

order

Speichert die Reihenfolge der Attribute in der Query-Angabe, die maßgeblich für die Reihenfolge der Attribute in der Sachdatenanzeige ist.

privileg

Setzt die Default-Rechte für das Attribut. Mögliche Werte sind

  • '0':der User kann das Attribut lesen, aber nicht editieren
  • '1': der User kann das Attribut editieren
  • '-1': das Attribut kann nur zum Exportieren, nicht zur Anzeige verwendet werden
  • gibt es für ein Attribut keinen Eintrag oder ist der Wert NULL, ist das Attribut nicht sichtbar und kann auch nicht für Suche, Export oder Verknüpfungen zu anderen Attributen verwendet werden.

query_tooltip

Definiert ob das Attribut im Abfragemodus im Tooltip angezeigt werden soll.

Tabelle "layer_attributes2stelle"

Setzt für jedes Attribut des Layers in jeder Stelle die Rechte des Benutzers auf das Attribut.

layer_id und stelle_id

ebendiese

attributname

Attributname, wie er im Query-Statement aus der Datenbank geholt wird (also nicht unbedingt identisch mit dem Tabellenattributnamen).

privileg

Setzt die Rechte für das Attribut innerhalb der Stelle, die in stelle_id definiert ist. Mögliche Werte sind

  • '0':der User kann das Attribut lesen, aber nicht editieren
  • '1': der User kann das Attribut editieren
  • gibt es für ein Attribut keinen Eintrag, wird das Attribut nicht abgefragt und es besteht kein Zugriff darauf. Auch nicht in der Suche, im Export oder Druck.

tooltip

Bestimmt, ob das Attribut beim Überfahren des Objekts mit der Maus als Tooltip angezeigt wird oder nicht:

  • "0" = wird nicht als Tooltip angezeigt
  • "1" = wird als Tooltip angezeigt

Tabelle "layer_parameter"

In dieser Tabelle werden Parameter beschrieben, mit denen dynamische Layer definiert werden können. Siehe auch selectable_layer_params in Tabelle stelle

Tabelle "notifications"

Speichert die Benachrichtigungen, die der Admin für die Nutzer angelegt hat.


id ID der Benachrichtigung. Primärschlüssel.

veroeffentlichungsdatum Datum ab wann die Benachrichtigung zu sehen sein soll.

ablaufdatum Datum bis zu dem die Benachrichtigung angezeigt werden soll.

stellen_filter Eine kommaseparierte Liste von Stellen-ID's oder 'nicht in Gaststellen'. Ohne Eintrag oder mit leerem String werden die Benachrichtiungen in allen Stellen angezeigt.

notification Der Text, der angezeigt werden soll. Kann HTML-Tags enthalten.

Tabelle "m_grids"

Dient der Erzeugung eines Gitternetzes.

Tabelle "m_grids2used_layer"

Ordnet das Gitternetz aus der Tabelle "m_grids" einem Layer zu.

Tabelle "referenzkarten"

Diese Tabelle regelt den Aufbau der Übersichtskarte. Die Koordinatenwerte der linken unteren bzw. rechten oberen Ecke müssen der tatsächlichen ausdehnung des Koordinatenausschnitts im Koordinatensystem der Stelle entsprechen.

Name

Bezeichnung für die Übersichtskarte, kann frei gewählt werden.

Dateiname

Name der Rasterbild-Datei. Pfad zur Übersichtskarte ist in der config.php gesetzt!

xmin, ymin, xmax, ymax

Ausdehnung der Übersichtskarte.

width, height

Größe der Übersichtskarte (in Pixeln), z.B. 120, 90.

Tabelle "rolle"

Durch die Rolle werden dem jeweiligen Benutzer (User) beim Start von kvwmap verschiedene Stellen (mindestens eine) zunächst angeboten und nach erfolgter Auswahl zugeordnet. Für jeden User können beliebig viele Rollen angelegt werden. Zu jeder Rolle gehört genau eine Stelle. Erst durch die Rolle (d.h. eben durch die Zuweisung des Benutzers zu einer Stelle) werden dem Benutzer bestimmte Rechte verliehen, die sich aus der Zuordnung zur Stelle ergeben.

user_id

Die entsprechende ID aus der Tabelle "user". Es können beliebig viele Rollen angelegt werden, in denen die user_id identisch ist, nur muss jeweils das Feld "stelle_id" anders belegt werden.

stelle_id

Die entsprechende ID aus der Tabelle "stelle". Zum Begriff "Stelle" siehe dort.

nImageWidth, nImageHeight

Größe des Kartenfensters beim Start (in Pixeln), z.B. "500, 500". Diese Einstellung wird aus der jeweils letzten Sitzung übernommen.

minx, miny, maxx, maxy

Ausdehnung des Kartenausschnitts beim Start (in Koordinaten). Diese Einstellung wird aus der jeweils letzten Sitzung übernommen.

nzoomFaktor

Faktor, der das Maß des Herein- bzw. Herauszoomens bestimmt. "2" ist Verdoppelung bzw. Halbierung des Maßstabs. Diese Einstellung wird aus der jeweils letzten Sitzung übernommen.

selectedButton

Speichert, welcher Zoom-Button beim Beenden aktiviert war.

epsg_code

Definiert das Ausgabekoordinatensystem für den jeweiligen User in dieser Stelle. Hinweis: Jeder User einer Stelle kann also sein Kartenbild in einem anderen Koordinatensystem erhalten.

epsg_code2

Definiert ein zusätzliches Ausgabekoordinatensystem für den jeweiligen User in dieser Stelle, das nur für die Anzeige unter der Karte verwendet wird.

active_frame

Hier wird die aktuelle Druckrahmen-ID gespeichert.

last_time_id

Speichert den Zeitpunkt des letzten aufgerufenen Kartenausschnitts eines Users.

gui

speichert die graphische Oberfläche, die der User ausgewählt hat. Standard: "gui.php". Hinweis: Eigene GUIs können im Ordner layouts/custom von kvwmap gespeichert werden. Sie werden dann z.B. so angegeben: "custom/gui_1".

language

Speichert die Sprachversion, die der User in der Stelle auswählt.

charset

Speichert den entsprechenden zu verwendenden Zeichensatz, abhängig von language.

hidemenue

Speichert, ob der User in der Stelle das Menü zu- oder weggeschaltet hat.

hidelegend

Speichert, ob der User in der Stelle die Legende zu- oder weggeschaltet hat.

fontsize_gle

Speichert die Textgröße, die der User für die Sachdatenanzeige in der Stelle ausgewählt hat.

highlighting

Speichert, ob der User in der Stelle die Objekte gehighlightet haben will oder nicht.

buttons

Speichert, welche Buttons der Navigationsleiste der User in der Stelle benutzen will.

scrollposition

Speichert die Position des Scrollbalkens an der Legende.

result_color

Speichert die ID der Farbe aus der Tabelle colors, die für die Anzeige von Suchergebnissen verwendet werden soll.

redline_text_color

Speichert die Farbe in der die Texte der Redline-Funktion gezeichnet werden sollen (varchar(7) Farbwert in HTML-Farbnotation, NOT NULL, default '#ff0000')

redline_font_family

Speichert die Font-Family in der die Texte der Redline-Funktion gezeichnet werden sollen (varchar(25) NOT NULL, default 'Arial', im Auswahlfeld im Quellcode von rollenwahl.php fest vorgegebene Optionen: 'Arial', 'Courier', 'Helvetica', 'Verdana')

redline_font_size

Speichert die Font-Größe in der die Texte der Redline-Funktion gezeichnet werden sollen (integer NOT NULL, default 16, im Auswahlfeld im Quellcode von rollenwahl.php fest vorgeben von min 10 bis max 40 Schrittweite 1, verwendet als Größe in Pixel)

redline_font_weight

Speichert die Schriftschnitt in der die Texte der Redline-Funktion gezeichnet werden sollen (varchar(25) NOT NULL, default 'bold', im Auswahlfeld im Quellcode von rollenwahl.php fest vorgegebene Optionen: 'normal', 'bold', 'bolder', 'lighter', 'initial', 'inherit', '100', '200', '300', '400', '500', '600', '700', '800', '900')

Tabelle "rollenlayer"

Ersetzt die Einträge in den Tabellen layer, used_layer, u_rolle2used_layer und classes, wenn ein Layer nicht allen Usern der Stelle zur Verfügung stehen soll, z.B. die Suchergebnislayer. Zu den entsprechenden Feldern siehe die Beschreibungen in den genannten Tabellen.

Tabelle "rolle_nachweise"

Dient der Speicherung von Suchpolygonen für die Fachschale Nachweisverwaltung.

Tabelle "rolle_saved_layers"

Dient der Speicherung von Einstellungen des Themenbaumes.

id

Fortlaufende Zahl als Identifier der Tabelle

user_id, stelle_id

ID des Nutzers und der Stelle, für die die Einstellungen gespeichert werden sollen.

name

Bezeichnung der Einstellung. Wird verwendet für die Anzeige in der Auswahlliste der Einstellungen.

layers

Kommagetrennte Liste von ID's deren Layer in der Themeneinstellung für die Anzeige in der Karte eingeschaltet sein sollen.

query

Kommagetrennte Liste von ID's deren Layer in der Themeneinstellung für die Info-Abfrage eingeschaltet sein sollen.

CREATE TABLE `rolle_saved_layers` (
  `id` int(11) NOT NULL,
  `user_id` int(11) NOT NULL,
  `stelle_id` int(11) NOT NULL,
  `name` varchar(255) NOT NULL,
  `layers` text NOT NULL,
  `query` text
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

Tabelle "stelle"

Der Begriff "Stelle" meint eine Arbeitsstelle oder besser Arbeitsaufgabe. An die Stelle ist eine festgelegte Benutzeroberfläche geknüpft mit allen daran hängenden Rechten an Funktionen, räumlicher Ausdehnung und Bedienelementen. Die Stelle definiert auch den Zugriff auf die Daten, die der Benutzer sehen und abfragen darf.

Bezeichnung

Wenn der Benutzer kvwmap startet, kann er aus den Stellen auswählen, die ihm über die Rolle zugewiesen wurden. In der Auswahl erscheint die Bezeichnung der Stellen. Zusätzlich zur Deutschen bezeichnung können die Bezeichnungen in Plattdeutsch, Englich, Polnisch und Vietnamesisch angegeben werden. Die Sprachen sind an den Spaltennamen Bezeichnung mit _ angehängt, siehe Tabellendefinition unten.

start, stop

Damit kann die zeitliche Zuordnung des Benutzers zur Stelle eingestellt werden, z.B. bei Auslegungsfristen für Bürgerbeteiligungen oder für zeitlich begrenzte Gast-Zugriffe.

minxmax, minymax, maxxmax, maxymax

Maximal erlaubte Ausdehnung (in Koordinaten) des Kartenausschnitts, z.B. der gesamte Landkreis, die Stadt oder eine Gemeinde.

epsg-code

Default-EPSG, wenn die Stelle als neue Stelle kopiert wird.

Referenzkarte_ID

Die entsprechende ID aus der Tabelle "referenzkarten" zur Anbindung der Übersichtskarte. Zum Begriff "Referenzkarte" siehe dort.

Authentifizierung

Regelt, ob für den Zugriff auf diese Stelle eine Benutzerauthentifizierung nötig ist ('1') oder nicht ('0').

ALB_status

Regelt die PDF-Ausgabe des ALB.

  • "30" = Eigentümerangaben nicht sichtbar
  • "35" = Eigentümerangaben sichtbar.

wappen

Dateiname des zugehörigen Wappens (Pfad wird in die config.php eingetragen).

wappen_link

Die URL, die hier eingegeben wurde, wird beim Klick auf das Wappen in einem neuen Tab im Browser aufgerufen.

alb_raumbezug

Mit "alb_raumbezug" und "alb_raumbezug_wert" kann man eine räumliche Einschränkung auf die ALB-Daten für eine Stelle vornehmen. Auswahlmöglichkeiten: "Kreis", "Amt", "Gemeinde".

alb_raumbezug_wert

Gibt den Schlüssel des Kreises/des Amtes/der Gemeinde an.

logconsume

  • "0" = es erfolgt keine Protokollierung der Layerzugriffe für die User dieser Stelle
  • "1" = wenn ein User dieser Stelle in der Karte navigiert oder eine Layerauswahl vornimmt, werden alle logbaren Layer in der Tabelle u_consume2layer mit Angabe eines Zeitstempels gespeichert.

Hinweis: Es werden nur die Layer der Stelle protokolliert, die im Feld "logconsume" der Tabelle layer als protokollierbar gekennzeichnet sind.

pgdbhost, pgdbname, pgdbpasswd

Wenn in der config.php POSTGRES_DBNAME nicht gesetzt ist, werden die Zugangsdaten für die PostgreSQL-Datenbank aus diesen Einstellungen für die Stelle entnommen.

wms_... und ows_ ...

Einträge, die relevant sind, wenn Daten der Stelle als Dienst angeboten werden. Die Einträge erscheinen im GetCapabilities-Dokument, bzw. werden für die Bereitstellung des Dienstes verwendet.

check_client_ip

  • "1" = es erfolgt eine Prüfung ob der User von einer der in der Tabelle user in Spalte ips eingetragenen IP Adressen aus auf kvwmap zugreift.
  • "0" = keine Prüfung

check_password_age

  • "1" = es erfolgt eine Prüfung ob das Password des Nutzers zum Zeitpunkt des Einloggens älter ist als in Spalte allowed_password_age für die Stelle angegeben. Tritt der Fall ein, muss der Nutzer erst sein Passoword ändern um sich einloggen zu können. (Funktion ist in Version 1.7.0 in Arbeit)
  • "0" = es erfolgt keine Prüfung

allowed_password_age

Erlaubtes Alter der Passwörter der Benutzer die sich an der Stelle anmelden wollen. Angegeben als ganze Zahl, eine Anzahl von Monaten definiert. Wirkt nur wenn check_password_age=1 für die Stelle gesetzt ist.

use_layer_aliases

  • "1" = In dieser Stelle werden Layer-Aliase verwendet.
  • "0" = Es werden keine verwendet.

selectable_layer_params

Die hier angegebenen Namen dürfen in der GUI für die Auswahl von Parametern verwendet werden. Es dürfen nur Parameter kommagetrennt eingegeben werden, die in der Tabelle layer_parameter vordefiniert sind.

hist_timestamp

  • "1" = In dieser Stelle darf ein Datum für den Stand der ALKIS-Daten ausgewählt werden.
  • "0" = History wird nicht verwendet und ist nicht Einstellbar

default_user_id

Nutzer Id der default Rolle. Die Einstellungen dieser Rolle werden für das Anlegen neuer Rollen für diese Stelle verwendet. Ist dieser Wert nicht angegeben oder die angegebene Rolle existiert nicht, werden die Defaultwerte der Rollenoptionen bei der Zuordnung eines Nutzers zu dieser Stelle verwendet. Die Angabe ist nützlich, wenn die Einstellungen in Gaststellen am Anfang immer gleich sein sollen. Außerdem werden die für den Default-Nutzer in der Stelle gespeicherten Themeneinstellungen aus der Tabelle rolle_saved_layers für jeden Gast mit angelegt, damit die Gäste ebenfalls darauf zugreifen können.

version

Ein String zu Versionierung der Stelle. Wird für die Synchronisierung mit kvmobile verwendet. Neue Versionen müssen bei alphanumerischer Sortierung weiter unten sein. z.B. 1.0.0 ist älter als 1.1.0

comment

Ein Kommentar zur Stelle. Dieser wird z.B. dafür verwendet um dem Client mitzuteilen was sich an der Konfiguration der Stelle geändert hat und warum. Ansonsten kann der Kommentar auch einfach nur für die Administratoren verwendet werden.

Tabellenstruktur:

CREATE TABLE `stelle` (
 `ID` int(11) NOT NULL,
 `Bezeichnung` varchar(255) NOT NULL DEFAULT ,
 `Bezeichnung_low-german` varchar(255) DEFAULT NULL,
 `Bezeichnung_english` varchar(255) DEFAULT NULL,
 `Bezeichnung_polish` varchar(255) DEFAULT NULL,
 `Bezeichnung_vietnamese` varchar(255) DEFAULT NULL,
 `start` date NOT NULL DEFAULT '0000-00-00',
 `stop` date NOT NULL DEFAULT '0000-00-00',
 `minxmax` double DEFAULT NULL,
 `minymax` double DEFAULT NULL,
 `maxxmax` double DEFAULT NULL,
 `maxymax` double DEFAULT NULL,
 `minzoom` int(11) NOT NULL DEFAULT '8',
 `epsg_code` int(5) NOT NULL DEFAULT '2398',
 `Referenzkarte_ID` int(11) DEFAULT NULL,
 `Authentifizierung` enum('0','1') NOT NULL DEFAULT '1',
 `ALB_status` enum('30','35') NOT NULL DEFAULT '30',
 `wappen` varchar(150) NOT NULL DEFAULT 'wappen_doberan.png',
 `wappen_link` varchar(255) DEFAULT NULL,
 `logconsume` enum('0','1') DEFAULT NULL,
 `ows_title` varchar(255) DEFAULT NULL,
 `wms_accessconstraints` varchar(255) DEFAULT NULL,
 `ows_abstract` varchar(255) DEFAULT NULL,
 `ows_contactperson` varchar(255) DEFAULT NULL,
 `ows_contactorganization` varchar(255) DEFAULT NULL,
 `ows_contactemailaddress` varchar(255) DEFAULT NULL,
 `ows_contactposition` varchar(255) DEFAULT NULL,
 `ows_fees` varchar(255) DEFAULT NULL,
 `ows_srs` varchar(255) DEFAULT NULL,
 `protected` enum('0','1') NOT NULL DEFAULT '0',
 `check_client_ip` enum('0','1') NOT NULL DEFAULT '0',
 `check_password_age` enum('0','1') NOT NULL DEFAULT '0',
 `allowed_password_age` tinyint(4) NOT NULL DEFAULT '6',
 `use_layer_aliases` enum('0','1') NOT NULL DEFAULT '0',
 `selectable_layer_params` mediumtext,
 `hist_timestamp` tinyint(1) NOT NULL DEFAULT '0',
 `default_user_id` int(11) DEFAULT NULL,
 `style` varchar(100) DEFAULT NULL,
 `show_shared_layers` tinyint(1) DEFAULT '0',
 `pgdbhost` varchar(255) NOT NULL,
 `pgdbname` varchar(255) NOT NULL,
 `pgdbuser` varchar(255) NOT NULL,
 `pgdbpasswd` varchar(255) NOT NULL,
 `postgres_connection_id` int(11) NOT NULL,
 `version` varchar(10) NOT NULL DEFAULT '1.0.0',
 `comment` text

) ENGINE=InnoDB DEFAULT CHARSET=utf8 PACK_KEYS=0;

Tabelle "stelle_gemeinden"

Sowohl Adress-, Eigentümer-, Grundbuchblatt- als auch Flurstückssuche können auf die Gemeinden, Gemarkungen und Fluren auf die die Stelle Zugriff haben soll, eingeschränkt werden.

Stelle_ID

Die ID der Stelle, die die Einschränkung erfahren soll.

Gemeinde_ID

Der (achtstellige) Gemeindeschlüssel der Gemeinde, die in dieser Stelle zur Auswahl stehen soll. Sollen mehrere Gemeinden in der Stelle zur Auswahl stehen, werden für die entsprechende Stelle mehrere Einträge erzeugt.

Gemarkung

Der (sechsstellige) Gemarkungsschlüssel der Gemarkung, die in dieser Stelle zur Auswahl stehen soll. Sollen mehrere Gemarkungen in der Stelle zur Auswahl stehen, werden für die entsprechende Stelle mehrere Einträge erzeugt. Das Feld Gemeinde_ID muss auch ausgefüllt sein.

Flur

Die Flurnummer der Flur, die in dieser Stelle zur Auswahl stehen soll. Sollen mehrere Fluren in der Stelle zur Auswahl stehen, werden für die entsprechende Stelle mehrere Einträge erzeugt. Die Felder Gemarkung und Gemeinde_ID müssen auch ausgefüllt sein.

Tabelle "styles"

Styles beinhalten Parameter zur Symbolisierung und Ausgestaltung der im Layer enthaltenen Geometrien.

symbol

Die laufende Nummer des Symbols in der Symboldatei (z.B. symbols.sym). Beginnend mit 1, ist also das fünfte Symbol die Nummer 5. In der Symboldatei müssen dafür keine Nummern explizit angegeben werden.

Hinweis: Große Schwierigkeiten gibt’s, wenn Symbole in die Symbol-Datei eingefügt werden. Besser nur den Symbolnamen verwenden und das Feld "Symbol" grundsätzlich freilassen.

symbolname

Wenn die Symbole der Symboldatei Namen haben, sollten diese benutzt werden. Diese Verfahrensweise ist derjenigen der Symbolnummern vorzuziehen.

size

Angabe der Höhe von Punkt-, Linien- bzw. Flächensymbolen in Pixeln. Werden sizeunits gesetzt, bezieht sich die Angabe auf die definierte Einheit (momentan von kvwmap noch nicht unterstützt).

Für Symbole vom Typ HATCH (nur bei Flächenlayern) ist der angegebene Wert der Abstand zwischen den Schraffurlinien.

Bei skalierbaren Symbolen bestimmt size deren Höhe für den unter symbolscale angegebenen Maßstab.

Hinweis: Damit die Darstellung skalierbar wird, muss zusätzlich ein Wert für minsize und maxsize vergeben werden, sowie in Tabelle
used_layer ein symbolscale gesetzt sein.

Die Umrandungen von Flächenlayern werden immer mit size=1 erzeugt. Sollen hier andere Größen bzw. auch Muster erscheinen, müssen Fläche und Umringslinie über zwei Classes und zwei Styles separat definiert werden.

Sollen Flächenlayer, die nur eine Farbe enthalten (siehe color), druckbar sein, darf für size niemals der Wert "0" gesetzt werden. Bei der Druckaufbereitung wird der Wert für size mit in die Umrechnung der Auflösung mit einbezogen. Wenn size=0 eingestellt ist hat das zur Folge, dass der entsprechende layer weder in der Druckvorschau noch im Druck ausgegeben wird.

color

Farbe des Symbols/der Linie/der Fläche. Wird angegeben in "R G B" (3 Zahlen mit Leerzeichen getrennt: "125 200 50") oder durch Angabe eines Attributs des Layers, in dem die jeweilige Farbe gespeichert ist.

backgroundcolor

Angabe einer Farbe für nicht-transparente Symbole.

outlinecolor

Angabe einer Farbe, um Polygone und bestimmte Markersymbole zu umranden. Linien haben keine outlinecolor, hier müssen gegebenenfalls mehrere Styles miteinander kombiniert werden.

colorrange

Erzeugt einen Farbverlauf innerhalb eines Wertebereichs (datarange). Die Angabe erfolgt in "R G B R G B" (6 Zahlen mit Leerzeichen getrennt: "0 127 255 223 255 0" für Azurblau bis Zitronengelb).

datarange

Legt den Wertebereich für colorrange fest. Die Angabe erfolgt mittels 2 durch ein Leerzeichen getrennter Werte. Das wertgebende Attribut und der Bereich müssen zuvor in der class unter Expression festgelegt werden, z.B. ([Attribut] > 0 AND [Attribut] < 70).

opacity

Bestimmt die Deckkraft des Styles von 0 (voll transparent) bis 100 (volle Deckkraft).

minsize, maxsize

Angabe der minimalen bzw. maximalen Größe von Punkt-, Linien- oder Flächensymbolen bei skalierbarer Darstellung.

Hinweis: Damit die Darstellung skalierbar wird, muss zusätzlich ein Wert für minsize und maxsize vergeben werden, sowie in Tabelle
used_layer ein symbolscale gesetzt sein.

angle

Winkelangabe von Symbolen und Schraffuren in Grad. In Kombination mit geomtransform kann auch "AUTO" als Wert gesetzt werden, um zum Beispiel Linien mit Pfeilspitzen oder Befiederung zu versehen.

angleitem

Angabe eines Attributs des Layers, in dem der jeweilige Winkel gespeichert ist.

antialias

'1': Schaltet die Kantenglättung bei TrueType- und Cartoline-Symbolen ein. Hat keine Auswirkungen auf andere Style-Typen.

width

Angabe der Breite der zu zeichnenden Linien in Pixeln.

Für Symbole vom Typ HATCH (nur bei Flächenlayern) gibt der angegebene Wert die Breite der Schraffurlinien an.

Bei skalierbarer Darstellung bestimmt width die Linienbreite für den unter symbolscale angegebenen Maßstab.

minwidth, maxwidth

Angabe der minimalen bzw. maximalen Breite von Linien bei skalierbarer Darstellung.

Hinweis: Damit die Darstellung skalierbar wird, muss zusätzlich ein Wert für minsize und maxsize vergeben werden, sowie in Tabelle
used_layer ein symbolscale gesetzt sein.

sizeitem

Wenn die Größe der Linien in einem Attribut gespeichert wird, kann man den Attributnamen angeben. Damit können die Objekte einer Klasse verschieden breite Linien bzw. verschieden große Symbole bekommen.

offsetx, offsety

Verschiebt das Symbol um den angegebenen Betrag in X- bzw. Y-Richtung. Die Eingabe von negativen Werten ist möglich. Einen Sonderfall bildet ein offsety-Wert von "-99". Dieser versetzt Linien parallel nach links oder rechts bzw. Flächenbegrenzungslinien nach innen oder außen um den angegebenen offsetx-Wert.

pattern

Dient der Darstellung von Linienmustern, durch Angabe von Strich- und Pausenlängen (in Pixeln), z.B. "1 4 15 4 15 4" für eine Kreisgrenze.

geomtransform

Erzeugt eine neue Geometrie aus der vorhandenen Geometrie. Mögliche Werte sind:

  • bbox: Erzeugt einen rechteckigen Begrenzungsrahmen um die Geometrie
  • centroid: Erzeugt einen Punkt im Flächenschwerpunkt der Geometrie
  • start: Erzeugt einen Punkt am ersten Punkt der Geometrie
  • end: Erzeugt einen Punkt am letzten Punkt der Geometrie
  • vertices: Erzeugt Punkte auf allen Scheitelpunkten der Geometrie zwischen dem Anfangs- und Endpunkt

Eine beispielhafte Darstellung findet sich unter Transformations for simple styling (CLASS STYLE only)

gap

Bestimmt den Abstand zwischen Symbolen (Mitte zu Mitte) bei Liniendekorationen und Flächenfüllungen. Bei Liniendekorationen sorgt ein negativer Wert zusätzlich dafür, dass die Symbole entlang der Linie ausgerichtet werden, während ein positiver Wert alle Symbole nach oben ausrichtet.

initialgap

In Kombination mit gap verschiebt sich der Beginn der Liniendekoration um den angegebenen Wert.
In Kombination mit pattern verschiebt sich das Linienmuster um den angegebenen Wert, jedoch nicht der Beginn.

linecap

Bestimmt die Darstellung der Linienenden. Mögliche Werte sind:

  • butt: Stoppt die Linie exakt am Ende mit einem geraden Schnitt
  • round: Erzeugt ein abgerundetes Ende, jedoch um width/2 über das eigentliche Linienende hinaus verlängert
  • square: Erzeugt einen geraden Schnitt, jedoch um width/2 über das eigentliche Linienende hinaus verlängert

Standardmäßig ist round gesetzt.

linejoin

Bestimmt die Darstellung der Scheitelpunkte. Mögliche Werte sind:

  • none: Stoppt jeden Schenkel einzelnd exakt am Ende mit einem geraden Schnitt
  • bevel: Stoppt beide Schenkel zusammen mit einem geraden Schnitt, jedoch über das eigentliche Linienende hinaus verlängert
  • round: Erzeugt ein abgerundetes Ende, jedoch über das eigentliche Linienende hinaus verlängert
  • miter: Lässt beide Außenkanten der Linie über das eigentliche Linienende spitz zusammenlaufen

Standardmäßig ist round gesetzt.
Eine beispielhafte Darstellung findet sich unter LINEJOIN

linejoinmaxsize

Funktioniert nur in Kombination mit dem Wert "miter" unter linejoin und legt fest, wie weit die Außenkanten der Linien maximal über das eigentliche Linienende hinaus zusammenlaufen dürfen. Das Maximum berechnet sich wie folgt:

m_max = width * linejoinmaxsize

Standartwert ist "3".
Eine beispielhafte Darstellung findet sich unter LINEJOINMAXSIZE (only relevant for LINEJOIN miter)


Die Anwendergruppe kvwmap veröffentlicht Symbole, Signaturen und karthographische HowTos hier in diesem WIKI. Weitere Informationen zur Erstellung von Symbolen und Liniensignaturen z.B. hier: http://mapserver.org/de/mapfile/symbology/construction.html

Tabelle "used_layer"

Jeder Stelle können beliebig viele Used Layer zugeordnet werden. Zu jedem Used Layer gehört genau ein Layer. Umgekehrt ausgedrückt: Durch die Tabelle "used_layer" kann ein Layer beliebig vielen Stellen zugeordnet werden.

stelle_id

Die entsprechende ID aus der Tabelle "stelle".

layer_id

Die entsprechende ID aus der Tabelle "layer". Zum Begriff "Layer" siehe dort.

queryable

Layer können als abfragbar ("1") oder nicht abfragbar ("0") gekennzeichnet werden. Entsprechend ist das Info-Häkchenfeld in der Legende vorhanden oder nicht.

drawingorder

Die Zeichenreihenfolge, in der die Layer dargestellt werden, ist entscheidend für das Aussehen der Karte. Der Layer mit der kleinsten drawingorder wird zuerst gezeichnet. Die drawingorder regelt weiterhin die Position des Layers innerhalb der Gruppe in der Themenauswahl/Legende. Die drawingorder kann bis zu elf Stellen besitzen, es empfiehlt sich also, großzügig bei der Vergabe zu sein, um später in kvwmap integrierte Layer noch sinnvoll einfügen zu können. Rasterlayer sollten zuerst gezeichnet werden, Beschriftungslayer zuletzt.

Durch die Angabe der Zeichenreihenfolge in den Used Layern kann jeder Stelle individuell eine eigene Zeichenreihenfolge gegeben werden.

minscale

Kleinste Maßstabszahl, unterhalb der der Layer nicht mehr angezeigt wird (z.B. 500).

maxscale

Größte Maßstabszahl, über die hinaus der Layer nicht mehr angezeigt wird (z.B. 10.000).

offsite

erzeugt einen Farbindex [R G B] bei Rasterlayern, um sie transparent zu machen.

transparency

Wert, der angibt, wie opak der Layer sein soll, zwischen

  • "0" = vollkommen durchsichtig und
  • "100" = gar nicht durchsichtig.

postlabelcache

Zeichnet den Layer nach allen anderen und auch nach der Beschriftung, wenn "1" angegeben wird.

Filter

Dieser Parameter erlaubt für Daten spezifische Attributfilter einzusetzen, die zur selben Zeit abgearbeitet werden wie die räumlichen Filter, aber bevor irgendwelche CLASS-Ausdrücke ausgewertet werden.

Beispiel zur Einschränkung über den Gemarkungsschlüssel:

  • für eine bestimmte Gemarkung - (gemkgschl = '132100')
  • oder bei mehreren Gemarkungen - (gemkgschl = '132100' or gemkgschl = '132105')
  • oder mit Platzhaltern - (gemkgschl = '1321%')

"gemkschl" ist der Spaltenname zu den Objekten, die in der PostgreSQL-Datenbank gehalten werden, und um dessen Wert die Anfrage gefiltert werden soll.

template

Angabe eines PHP-Snippets, wenn NICHT der Generische Layereditor für die Sachdatenanzeige verwendet werden soll. Wenn Layer in verschiedenen Stellen unterschiedliche Sachdatenanzeigen bekommen sollen, können verschiedene Templates zur Anzeige definiert werden. (Beispiel: biotope_amt1.php, biotope_amt2.php, etc.)

symbolscale

Gibt den Massstab an, bei dem ein Punkt-/Linien-/Flächensymbol, eine Linie oder eine Beschriftung die Größe/Breite haben soll, die ihm in der Tabelle styles bzw. labels als size/width zugewiesen ist. Dies funktioniert nur, wenn gleichzeitig die Felder minsize und maxsize bzw. minwidth und maxwidth in der Tabelle styles bzw. labels mit Werten gefüllt sind.

Werden bei symbolscale keine Angaben gemacht, hat das Symbol, die Linie oder die Beschriftung immer genau die Größe/Breite, die durch size/width definiert ist.

requires

Angabe um den Zusammenhang zum Anzeigen des Layers festzulegen. Beispiel für einen Layer "Gebäudepunkte":

([Gebäude] = 1)

D.h. der Layer "Gebäudepunkte" ist nur dann sichtbar, wenn auch der Layer "Gebäude" sichtbar ist. Hinweis: In der Legende bzw. Themenauswahl erscheint der Layername dann nicht mehr (im Beispiel also der Layer "Gebäudepunkte"), es werden nur noch seine Classes angezeigt.

logconsume

entscheidet, ob der Zugriff auf den Layer in der Tabelle u_consume2layer geloggt werden soll.

privileg

Regelt den grundsätzlichen Zugriff auf sämtliche Objekte des Layers in der Stelle im Generischen Layereditor. Die Rechte auf die einzelnen Attribute des Layers werden in der Tabelle layer_attributes2stelle gesetzt.

  • "0" = Der User darf sämtliche Attribute lesen und bearbeiten
  • "1" = Der User darf lesen, bearbeiten und neue Datensätze erzeugen
  • "2" = Der User darf lesen, bearbeiten, neue Datensätze erzeugen und Datensätze löschen.

start_aktiv

'1': Schaltet den Layer automatisch ein, wenn es sich um eine Gast-Stelle handelt. Default ist '0'.

Tabelle "user"

In dieser Tabelle werden die einzelnen Benutzer von kvwmap eingetragen. Jeder Benutzer wird mit Name und Vorname einzeln eingetragen. Das Anlegen von Gruppenbezeichnungen ("Naturschutz", "Kataster" o.ä.) empfiehlt sich nicht. Hier erfolgt keine Zuweisung von Rechten oder Daten!

login_name

Der Login-Name erscheint im Browserfenster als "Nutzer" unten rechts.

ips

Hier können eine oder mehrere mit ; getrennte IP Adressen oder Hostnamen (z.B. bei Nutzung von dynDNS bei keiner festen IP) eingetragen werden, von denen der Nutzer aus auf kvwmap zugreifen darf. Tritt aber nur in Kraft, wenn in Tabelle stelle in die Spalte check_client_ip eine 1 eingetragen wurde. Wenn check_client_ip=1 ist und in dieser Spalte ips steht nichts, bekommt der User keinen Zugang.

password Hier wird das mit der Methode SHA1 verschlüsselte Passwort gespeichert. Passwörter sind mit der Methode SHA1() zu codieren sind dann 40 Zeichen lang.

passwort In dem Attribut wurden bis zum 05.09.2022 Passwörter mit der Methode MD5 codiert hinterlegt. Bei der Umstellung auf SHA1 Passwörter prüft kvwmap bei der Anmeldung ob das MD5 codierte Passwort zum angegebenen Passwort passt und wenn ja, wird das Passwort sha1 codiert in dem Attribut password hinterlegt. Die Authentifizierung erfolgt nur noch über das Attribut password. Wenn das SHA1 Passwort im Attribut password hinterlegt wird, wird gleichzeitig das MD5 verschlüsselte Passwort gelöscht.

password_setting_time

Hier wird das Datum eingetragen an dem der Nutzer das letzte mal das Passwort geändert hat. Wird berücksichtigt, wenn in der Stelle in der der Nutzer sich anmelden will (siehe Tabelle stelle), der Parameter check_password_age = 1 gesetzt ist. Die Zeitdifferenz zwischen der aktuellen Zeit und der hier eingetragenen darf dann nicht größer sein als in der Spalte allowed_password_age in der Tabelle stelle.

Funktion

Wenn es sich um einen Gast-Nutzer handelt, wird 'gast' eingetragen. Default ist 'user'.

stelle_id

Hier wird die Stelle angegeben, der dieser User beim ersten Start von kvwmap zugeordnet sein soll.

Tabelle "user2notifications"

Speichert die Zuordnung der Nutzer zu den Benachrichtigungen. Wenn der Nutzer eine Benachrichtigung nicht mehr sehen will, wird die Zuordnung zwischen der Benachrichtigung und dem Nutzer in der Tabelle user2notifications entfernt.


user_id ID des Nutzers aus der Tabelle user. notification_id ID der Benachrichtigung in der Tabelle notifications.

Tabelle "u_attributfilter2used_layer"

Speicherung der Attribut-Filter der Layer einer Stelle. Diese Tabelle wird von kvwmap bei Benutzung des entsprechenden Menüs gefüllt.

Tabelle "u_consume"

Speichert die räumliche Ausdehnung aller Kartenausschnitte, die von den Benutzern generiert werden. Diese Tabelle wird von kvwmap bei Benutzung des entsprechenden Menüs gefüllt.

user_id

Speichert die ID-Nummer des Benutzers.

stelle_id

Speichert die ID-Nummer der Stelle, die der User im Moment der Ausschnittgenerierung gewählt hat.

time_id

Speichert Datum und Uhrzeit des Zeitpunkts, an dem der Ausschnitt erzeugt wurde.

activity

Speichert die Art des Zugriffs.

nimagewidth, nimageheight

Speichert die Kartenfenstergröße.

minx, miny, maxx, maxy

Speichert die Eckpunktkoordinaten des erzeugten Kartenausschnitts.

prev, next

Speichert, ob dieser Kartenausschnitt über die History-Funktion entstanden ist und ob er einen Vorgänger- bzw. Nachfolgerkartenausschnitt hat.

Tabelle "u_consume2comments"

Wenn ein Nutzer einen räumlichen Ausschnitt über die Funktion Kartenausschnitt speichern speichert, dann wird von kvwmap diese Tabelle bei Benutzung des entsprechenden Menüs gefüllt.

Tabelle "u_consume2layer"

Diese Tabelle speichert die Auswahl der Layer, die ein Benutzer in einer Stelle auswählt. Damit diese Protokollierung erfolgt, muss das Feld "logconsume" der entsprechenden Stelle in der Tabelle stelle mit "1" belegt werden.

Tabelle "u_consumeALB"

Speichert die druckenden Zugriffe eines Users auf das ALB, das jeweils ausgedruckte ALB-Format und die Anzahl der ausgedruckten Seiten. Wird von kvwmap bei Benutzung des entsprechenden Menüs ausgefüllt.

Tabelle "u_consumeALK"

Speichert die druckenden Zugriffe eines Users auf die ALK und den jeweils verwendeten Druckrahmen. Wird von kvwmap bei Benutzung des entsprechenden Menüs ausgefüllt.

Tabelle "u_funktion2stelle"

Die Zuweisung der Funktionen zur jeweiligen Stelle. Dadurch wird erreicht, dass bestimmte Funktionen nur bestimmten Stellen zur Verfügung stehen.

Funktion_id

Die entsprechende ID aus der Tabelle "u_funktionen".

Stelle_id

Die entsprechende ID aus der Tabelle "stelle".

Erlaubt

Wenn eine Funktion zugeordnet werden soll, muss sie mit "1" auch explizit erlaubt werden.

Tabelle "u_funktionen"

Funktionen sind spezielle Anwendungen, deren Ablauf in der index.php definiert wird. Mit Funktionen sind nicht die Navigationswerkzeuge oder die Menüs gemeint, sondern bestimmte Anwendungen wie etwa die Anzeige von Eigentümerdaten, für die benutzerbezogen Rechte vergeben werden müssen.

Bezeichnung

Der Name wird in der Funktionenauswahl angezeigt.

Link

Der Link weist auf den Anwendungsfall, der in der index.php definiert ist. Zur Schreibweise siehe Tabelle u_menues.

Derzeit läuft es so, dass man die Funktion so definiert, wie der Anwendungsfall, den man schützen will. Also wenn man z.B. den Anwendungsfall: "ALB_Aenderung" schützen möchte, muss "ALB_Aenderung" in Bezeichnung eingegeben werden.

In der index.php werden diese Einschränkungen für den jeweiligen Anwendungsfall aber nur dann wirksam, wenn die Rechteeinschränkung abgefragt wird.

Ein Anwendungsfall ohne Rechteeinschränkungsmöglichkeit:

case "Anwendungsfall" :
{
 $GUI->functiondieausgefuehrtwerdensoll();
}

Anwendungsfall mit Einschränkungsmöglicheit:

case "Anwendungsfall" :
{
   if ($GUI->Stelle->isFunctionAllowed($GUI->formvars['go'])) {
     $GUI-> functiondieausgefuehrtwerdensoll();
   }
   else {
     # Benutzer ist nicht berechtigt zum Ausführen der Funktion
     $GUI->Fehlermeldung='Sie sind nicht berechtigt diesen Anwendungsfall auszuführen.';
     $GUI->rollenwahl($Stelle_ID);
     $GUI->output();
   }
}

Man sieht, dass im Falle der erteilten Berechtigung der Anwendungsfall ausgeführt wird und man sonst auf die Stellenauswahl geleitet wird. Man könnte meinen, dass diese Verzweigung generell für alle Anwendungsfälle vor der Abarbeitung der cases ausgeführt werden könnte, dann kann man aber nicht individuell entscheiden was geschehen soll, wenn keine Rechte vorliegen.

Bisher gilt also, wenn Sie Anwendungsfälle extra schützen wollen (zusätzlich zu der Möglichkeit den Link zur Anwendung in der Stelle gar nicht erst anzuzeigen) dann teilen sie es den Entwicklern mit und diese können das fest in die index.php aufnehmen. Es hindert sie natürlich keiner daran ihre eigene index.php zu erstellen. Achtung dann aber beim Update.

Tabelle "u_groups"

Speichert den Namen einer Gruppe. Alle Layer werden einer Gruppe zugeordnet.

Tabelle "u_groups2rolle"

Speichert benutzerbezogen, ob die Layer einer Gruppe gerade sichtbar sind oder nicht.

Die Felder "user_id", "stelle_id" und "id" müssen für jeden User in jeder Stelle erstellt werden. In das Feld "Status" speichert kvwmap den jeweiligen Zustand der Gruppe.

Tabelle "u_labels2classes"

Da mehrere Label zu einer Class gehören können, wird die Zuordnung des jeweiligen Labels in einer eigenen Tabelle vorgenommen.

class_id

Die entsprechende ID aus der Tabelle "classes".

label_id

Die entsprechende ID aus der Tabelle "labels".

Tabelle "u_menue2rolle"

Speichert für jeden User, ob ein Menü aufgeklappt ist oder nicht.

Tabelle "u_menue2stelle"

Die Zuweisung der Menüs zur jeweiligen Stelle. Dadurch wird erreicht, dass bestimmte Menüs nur bestimmten Stellen zur Verfügung stehen.

stelle_id

Die entsprechende ID aus der Tabelle "stelle".

menue_id

Die entsprechende ID aus der Tabelle "u_menues".

menue_order

Reihenfolge der Darstellung bei der Sortierung der Menüs in der Stelle. Das Menü mit der kleinsten Menue_order-Nummer wird zuerst gezeichnet. Die Nummer kann bis zu elf Stellen besitzen, es empfiehlt sich also, großzügig bei der Vergabe zu sein, um später für die Stelle hinzukommende Menüs noch einfügen zu können.

Tabelle "u_menues"

Menüs sind bestimmte Funktionen, z.B. die Suchfunktionen oder die Hilfe. Mit Menü ist nicht die Themenauswahl oder die Navigationsleiste gemeint. Jeder Stelle können unterschiedliche Menüs zugeordnet werden.

Menüs werden weiterhin für die Fachschalen benötigt.

name

Der Name wird im Menütext angezeigt.

links

Der Link weist auf den Anwendungsfall, der in der index.php definiert ist. Beispiel: Der Nutzer soll Flurstücke suchen können. Der Anwendungsfall in der index.php lautet "Flurstueck_Auswaehlen". Der entsprechende Eintrag im Feld "Links" lautet dann "index.php?go=Flurstueck_Auswaehlen"

obermenue

Die Menüs werden verschachtelt. Es gibt Obermenüs und darunter angeordnet Untermenüs. Soll ein Menü ein Untermenü sein, so wird hier die ID des entsprechenden Obermenüs angegeben. Beispiel: Die Flurstückssuche soll keinem Obermenü zugeordnet werden. Im Feld wird eine "0" eingetragen.

Beispiel: Die ALB-Fortführung soll ein Untermenü im Menü "Fortführung" sein. Das Menü "Fortführung" hat die ID "17". Diese ID wird im Feld eingetragen.

menueebene

Die Verschachtelungstiefe wird in Ebenennummern beginnend bei "1" angegeben. Beispiel: Die Flurstückssuche soll in der Verästelung am Anfang stehen. Im Feld wird eine "1" eingetragen. Beispiel: Die ALB-Fortführung soll in der Verästelung unter dem Menü "Fortführung" erscheinen. Im Feld wird eine "2" eingetragen, da das Menü "Fortführung" die Menüebene "1" hat.

target

"_blank" öffnet ein neues Fenster. Das kann z.B. bei der Hilfe nützlich sein. Standardmäßig wird nichts eingetragen, dann wird die Funktion im gleichen Fenster ausgeführt.

order

Mit der Spalte "order" lassen sich die Menüpunkte sortieren. Allerdings wirkt sich diese Sortierung nicht global und sofort aus, sondern durch die Werte in dieser Spalte wird die Reihenfolge der Menüpunkte für die Stellen-Zuweisung in kvwmap festgelegt. Diese Spalte ist also dafür da, damit beim Zuweisen eines Obermenüpunktes mit seinen Unterpunkten an eine bestehende Menüstruktur einer Stelle der neue Menüpunkt nicht immer ganz unten angehängt wird, sondern eben entsprechend seinem Wert "order" innerhalb der vorhandenen Menüstruktur. Für Untermenüpunkte gilt der Wert der Spalte "order" nur innerhalb des jeweiligen Obermenüpunktes. Dort können dann Werte wie z.B. 1,2,3,4,5 drin stehen, während der zugehörige Obermenüpunkt den order-Wert 3 hat.

button_class

Hier kann eine css-Klasse angegeben werden, die in der custom.css definiert wird. Wenn eine Klasse angegeben ist, kann der Menüpunkt als Button oberhalb des Menüs dargestellt werden (wenn der Nutzer die entsprechende Option "Menüs als Schaltflächen" in den Optionen auswählt).

Die Buttons haben normalerweise nur ein Bild als Inhalt, so dass die Klassendefinition relativ einfach ist:

.menue_xy{
  background-image: url(../graphics/custom/bild_xy.png);
}

Tabelle "u_rolle2used_layer"

Die Tabelle speichert beim Verlassen von kvwmap den Status der Häkchenfelder in der Legende. Damit werden die Einstellungen eines Benutzers gespeichert, unabhängig davon, ob ein anderer Benutzer in der selben Stelle andere Einstellungen vornimmt.

aktivStatus

Speichert benutzerbezogen den letzten Zustand dieses Layers in Bezug auf die Sichtbarkeit.

  • "0" = Layer ist ausgeschaltet
  • "1" = Layer ist eingeschaltet
  • "2" = Layer ist eingeschaltet, aber in der Legende nicht sichtbar, weil die Gruppe zugeklappt ist.

queryStatus

Speichert benutzerbezogen den letzten Zustand dieses Layers in Bezug auf seine Abfragbarkeit.

  • "0" = Layer ist nicht abfragbar geschaltet
  • "1" = Layer ist abfragbar geschaltet
  • "2" = Layer ist abfragbar geschaltet, aber in der Legende nicht sichtbar, weil die Gruppe zugeklappt ist.

showclasses

Speichert benutzerbezogen, ob die Classes des Layers ein- oder ausgeblendet sind.

logconsume

  • "0" = Layer wird nicht geloggt.
  • "1" = Layer wird innerhalb der Stelle für den bestimmten Nutzer geloggt. Z.B. für User Müller innerhalb der Gemeinde xy für den Layer Flurstücke.

Damit die Protokollierung erfolgt, muss entweder in der Tabelle stelle oder in der Tabelle layer oder in der Tabelle used_layer das Feld "logconsume" = "1" gesetzt sein.

Tabelle "u_styles2classes"

Da mehrere Styles zu einer Class gehören können, wird die Zuordnung des jeweiligen Styles in einer eigenen Tabelle vorgenommen.

class_id

Die entsprechende ID aus der Tabelle "classes".

style_id

Die entsprechende ID aus der Tabelle "styles".

drawingorder

Legt die Zeichnungsreihenfolge der Styles fest, wenn (z.B. bei komplexeren Linienausgestaltungen) mehrere Styles in einer Class enthalten sind.

Referenz zur PostGIS-Datenbank von kvwmap

Tabelle "spatial_ref_sys_alias"

In dieser Tabelle können den verwendeten Koordinatenreferenzsystemen Aliasnamen, räumliche Geltungsbereiche und das System beschreibende Datums- und Projektionsparameter zugeordnet werden.

Die Datums- und Projektionsparameter werden verwendet, um bei Shape-Dateien das verwendete Koordinatenreferenzsystem aus der prj-Datei zu ermitteln. Die Spalten "datum", "projection" und "unit" haben Array-Datentypen, damit hier mehrere Varianten von prj-Parametern eingetragen werden können.

spatial ref sys alias.PNG

srid

Der EPSG-Code des Koordinatenreferenzsystems. Primärschlüssel.

alias

Der Aliasname, der für die Bezeichnung des Systems verwendet werden soll.

minx

Rechtswert der linken unteren Ecke des räumlichen Geltungsbereichs.

miny

Hochwert der linken unteren Ecke des räumlichen Geltungsbereichs.

maxx

Rechtswert der rechten oberen Ecke des räumlichen Geltungsbereichs.

maxy

Hochwert der rechten oberen Ecke des räumlichen Geltungsbereichs.

datum

Mehrere Varianten der Bezeichnung des Datums als Array.

projection

Mehrere Varianten der Bezeichnung der Projektion als Array.

false_easting

Additionskonstante zum Rechtswert bezogen auf den Mittelmeridian.

central_meridian

Die geographische Länge des Mittelmeridians.

scale_factor

Maßstabsfaktor für die Projektion.

unit

Mehrere Varianten der Bezeichnung der Einheit als Array.

MySQL-Tabellen in PostgreSQL nutzen

Zur Einbindung von MySQL-Tabellen, z.B. user in Postgres kann der fdw_mysql verwendet werden. Hier wird beschrieben welche Schritte dafür erforderlich sind.

  • Einrichten eines MySQL-Nutzers mit dem von Postgres aus auf die MySQL-Datenbank zugegriffern werden soll. Wenn man den kvwmap-Nutzer verwendet kann das Anlegen eines neuen Nutzers und dessen Rechteeinstellung entfallen. Ggf. die IP des Postgres-Containers anpassen.
mysql> create user 'fdw_user'@'172.0.10.%' identified by 'secret_password';
  • Festlegung der Rechte für den Nutzer in MySQL.
mysql> grant select,insert,update,delete on EMP to fdw_user@'%';
mysql> grant select,insert,update,delete on DEPT to fdw_user@'%';
  • Installation von fdw_mysql auf dem Postgres-Server. Ist bei Verwendung des Images pkorduan/docker-postgis schon enthalten.
pgsql-server$ apt-get update; apt-get install postgresql-<PG_MAJOR>-mysql-fdw
  • Installieren der Erweiterung in der kvwmap-Datenbank
postgres=# create extension mysql_fdw;
  • Definition einer Serverdefinition, die auf den MySQL-Server verweist.
postgres=# CREATE SERVER mysql_kvwmapdb FOREIGN DATA WRAPPER mysql_fdw OPTIONS (host 'mysql', port '3306');
  • Definition eines User mappings. Ggf. fdw_user durch kvwmap ersetzen
postgres=# CREATE USER MAPPING FOR PUBLIC SERVER mysql_kvwmapdb OPTIONS (username 'fdw_user',password 'secret_password');
  • Anlegen der Fremdtabelle in Postgres auf Basis einer existierenden MySQL-Tabelle. Im Beispiel wird die Tabelle admin.nutzer angelegt auf der Basis der MySQL-Tabelle user.
CREATE FOREIGN TABLE admin.nutzer(
  id integer NULL,
  login_name text NULL COLLATE pg_catalog."default",
  name text NULL COLLATE pg_catalog."default",
  vorname text NULL COLLATE pg_catalog."default",
  phon text NULL COLLATE pg_catalog."default",
  email text NULL COLLATE pg_catalog."default",
  organisation text NULL COLLATE pg_catalog."default",
  "position" text NULL COLLATE pg_catalog."default"
)
SERVER mysql_server
OPTIONS (dbname 'kvwmapdb', table_name 'user');

Diese Tabelle kann dann als ganz normale Postgres-Tabelle verwendet werden. Beim Schreiben in die Tabelle bitte Vorsicht. Abhängigkeiten zu anderen Tabellen in MySQL müssen berücksichtigt werden. Ein weiteres Beispiel für die Einbindung der Layer aus MySQL:

CREATE FOREIGN TABLE admin.layer(
  layer_id integer NULL,
  name character varying NULL COLLATE pg_catalog."default",
  alias character varying NULL COLLATE pg_catalog."default",
  maintable character varying NULL COLLATE pg_catalog."default"
)
SERVER mysql_server
OPTIONS (dbname 'kvwmapdb', table_name 'layer'); 

Datenbank-Migration

kvwmap-Installationen die PostgreSQL < Version 12 verwenden, nutzen häufig die OID in der Layerdefinition. Ab Version 12 werden OIDs außerhalb des system catalog nicht mehr unterstützt. Für ein Upgrade auf eine aktuelle PostgresQL-Version müssen die OID-Spalten somit aus Layer-Definitionen, Tabellen, Views, Indizes, Constraints und Funktionen entfernt bzw. durch eine Alternative ersetzt werden. Für PostgreSQL-Details siehe PostgreSQL 12 Release Notes

Layer anpassen

Eine Übersicht der anzupassenden Objekte liefert /kvwmap/index.php?go=layer_check_oids Layer können hier halbautomatisch angepasst werden.

Die Tabelle mit den Layern enthält die Spalten

  • Layer - Bezeichnung des Layers mit Checkbox zur Auswahl des Layers
  • ID-Spalte
  • Query
  • Data
  • oid-Alternative - wenn möglich, wird hier eine Alternative zur bisherigen OID ermittelt, diese wird hier angezeigt
  • Haupttabelle
  • Fehlermeldungen, falls die Analyse des Layers nicht problemlos möglich war

Ein Layer kann in 3 Feldern oids verwenden: als ID-Spalte, im Query-Feld und im Data-Feld. Wenn bei einem Layer hier eine oid verwendet wird, erscheint die Tabellenzelle rot. Das bedeutet, dass hier Anpassungsbedarf besteht.

Wenn eine oid-Alternative ermittelt werden konnte, kann diese in den 3 Feldern ID-Spalte, Query und Data gegen die oid ersetzt werden. Dazu dienen die 3 Schaltflächen oben rechts. Klickt man auf die Schaltflächen, wird die entsprechende Aktion für alle selektierten Layer durchgeführt. Für das Query- und das Data-Feld wird außerdem in einer gelben Zelle angezeigt, wie Query bzw- Data nach der Ersetzung aussehen werden. Bei Bedarf kann man hier auch von Hand Anpassungen vornehmen. Bei Klick auf die entsprechende Schaltfläche wird der Inhalt aus dem gelb hinterlegten Textfeld verwendet.

Datenbankobjekte anpassen

Die Seite zeigt unterhalb der Layer-Tabelle zeigt auch anzupassende Datenbankobjekte. Tabellen werden hier nicht aufgeführt, da diese auch ohne OID-Spalte wiederhergestellt werden können. Dies erzeugt nur eine Warnung. Verwenden aber von den Tabellen abhängige Objekte (Views, Constraints, Funktionen, Indizes) die OID-Spalte, so muss diese entfernt oder durch eine alternative Spalte ersetzt werden. Die Tabellen geben einen Überblick über die betreffenden Objekte. Die Abfragen zu den Tabellen finden Sie auch in diesem Repository.

Migration testen

Zum Testen der Migration gibt es im kvwmap-server Repository den Service pg15migration. Dieser kann mit dcm create serivce pg15migration kvwmap_prod eingerichtet werden. Bei der Einrichtung wird nach dem Passwort für den User postgres auf dem alten Cluster gefragt. Ebenfalls werden Pfade zur .pgpass und zum DumpVerzeichnis des alten Clusters abgefragt. Im alten Cluster bietet es sich an einen Ordner /dumps im Container zu mounten und den hostseitigen Pfad bei der Einrichtung des pg15migrationServices bereitzustellen. So kann das dump aus dem alten Cluster und restore ins neue Testcluster automatisiert erfolgen.

In den dump-Ordner des alten Clusters kann die ./scripte/dump.sh aus dem Verzeichnis des Testclusters kopiert werden. In diesem Script sind evtl. die zu dumpenden DBs und User anzupassen. Bei Schemen mit vielen Daten kann pg_dump um --schema-only erweitert werden.

Über ./export-import.sh im Ordner neues Clusters kann die Testmigration gestartet werden. Aus dem alten Cluster werden alle in dump.sh definierten DBs im Custom-Format gedumpt und ins neue Testcluster eingespielt. Dabei werden für jede DB 2 Logdateien (stdout, stderr) im Verzeichnis ./dumps/logs erzeugt. Diese geben Aufschluss über mögliche Fehler.

Postgis

Neben dem Ersetzen von OIDs kann es durch die Postgis-Extension zu weiteren Problemen kommen. Insbesondere wenn die Extension nicht über CREATE EXTENION postgis; sondern über die SQL-Scripte installiert wurde. In diesem Fall landen die Postgis-Funktionen als Referenz auf die externen Bibliotheken im Dump. Beim restore kann die Referenz zur Bibliothek nicht aufgelöst werden, da sich die Versionsnummer im Pfad geändert hat. Hier hilft ein Custom-Format dump und das Wiederherstellen über postgis_restore.pl in eine neue Datenbank in der die Postgis-Extenion installiert sowie das postgis legacy.sql eingespielt wurde. Dieser Prozess wurde mit dem pg15migration-Service automatisiert. In der ./import-dumps.sh des Testclusters ist der Aufruf docker exec -it "$CONTAINER" bash -c /scripts/restore.sh durch docker exec -it "$CONTAINER" bash -c /scripts/restore-legacy.sh zu ersetzen.

API Doc

Automatisierte Dokumentation der Klassen und dessen Funktionen aus Kommentaren im Quelltext

Ich habe mal einen ersten Versuch unternommen mit PHPDoc eine Referenzdokumentation zu allen in kvwmap vorhandenen Klassen zu erstellen. Das Resultat liefer schon alle Klassen und dazugehörigen Funktionen und Parameter, aber ist noch weitestgehend ohne zusätzliche Beschreibung. Die Dokumentation im Quellcode kann aber nach und nach so angepasst und erweitert werden, dass daraus eine passable Dokumentation der Klassen und ihrer Funktionen wird. Für die Funktion loadMap habe ich das mal beispielhaft gemacht. Es bedarf wirklich nur ein paar formatierter Zeilen Kommentar, die so aussehen:

/**
* Laden der Daten für das Map-Objekt aus Variablen, der Datenbank und/oder einer Map-Datei.
* 
* Diese Funktion ließt die Werte, die notwendig sind um die Karte zu konfigurieren. Die Quellen werden in Abhängigkeit vom Parameter $loadMapSource aus Variablen, aus einer Datenbank oder aus einem MapFile
* 
* Reihenfolge: Übersichtssatz - Kommentar - Tags.
* 
* @param  string	$loadMapSource Art der Quelle, aus der die Werte für das Map-Objekt gelesen werden sollen
*                 Mögliche Werte zur Zeit:
*                 Post: Werte werden aus Variablen gelesen, die über Post mitgeschickt wurden
*                        Dabei werden einige defaultmäßig zu setzende Parameter aus dem angegebenen MapFile gelesen.
*                 File: Die Werte für das Map-Objekt werden aus einer Map-Datei gelesen
*                 DataBase: Dies ist der Standardfall. Die Werte für das Map-Objekt werden aus der Datenbank gelesen.
* @return boolean	liefert derzeit immer true zurück.
* @see    db_mapObj(), $map
*/

Die Kommentare finden sich dann direkt in der Dokumentation wieder.

Eine Dokumentation wie die Kommentare geschrieben werden müssen und wie die Dokumentation erstellt wird findet sich hier.

Sicherung

zur Sicherung stellt die GDI Service das github-Repo [4] zur Verfügung. Dies bietet alle notwendigen Scripte um eine Standard-kvwmap-server Installation zu sichern. Für erweiterte Installationen ist die Konfiguration der Sicherungswerkzeuge entsprechend anzupassen.

Gesichert werden müssen mindesten

  • Datenverzeichns /home/gisadmin/networks mit Borg
  • PostgreSQL mit pgBackRest
  • mysql/mariadb mit mariabackup

Batchjob

Im Standard gibt es eine /etc/cron.d/gdi_sicherung mit folgendem Inhalt

 SHELL=/bin/bash
 PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
 00 22 * * * root runjob.py /etc/backup/jobs.json borg

Der Batchjob startet die Ablaufsteuerung runjob.py mit den Jobdefinitionen und dem zu startenden Job (hier borg).

Ablaufsteuerung

Im Rahmen einer Sicherung werden die in /etc/backup/jobs.json definierten Programme nacheinander aufgerufen. Der Aufruf erfolgt durch runjob.py /etc/backup/jobs.json borg. Dem runjob-Script wird die Definition der abzuarbeitenden Jobs und der Name des Startjobs übergeben. In der Definition jobs.json wird auch das Workspace-Verzeichnis definiert. Dieses Verzeichnis steht allen aufgerufenen Jobs im Environment zu Verfügung. runjob.py schreibt in dieses Verzeichnis das Log joblog.json in dem StdOut, StdErr sowie die Exitcodes der aufgerufenen Programme dokumentiert werden.

Konfiguration

Alles an Konfiguration liegt unter /etc/backup.

  • jobs.json
    • Definition der abzuarbeitenden Programme für eine Sicherung
    • Workspace-Verzeichnis: Arbeitsverzeichnis für die aktuelle Sicherung. Das Verzeichnis steht allen aufgerufenen Programmen im environment zur Verfügung. runjob.py schreibt hier die joblog.json rein in der alle Ausgaben (stderr, stdout) und die Exitcodes der ausgeführten Programme gelogt werden.

Eine Job-Definition hat die Form

       {
           "name":"postgresql"
           ,"command":["pgbackrest.sh", "kvwmap_prod_pgsql15", "incr"]
           ,"next-job":"mariadb"
           ,"start-job-on-success":"somejob1"
           ,"start-job-on-error";"somejob2"
       },

Sie besteht aus einem Namen und dem auszuführenden Kommando. Optional können folgende Schlüssel übergeben werden:

  • next-job
    • Name des Jobs der im Anschluss ausgeführt werden soll
  • start-job-on-success
    • Name des Jobs der bei Erfolg (exitcode=0) ausgeführt werden soll. Existiert ein "next-job" so wird dieser im Anschluss an start-job-on-success ausgeführt.
  • start-job-on-error
    • Names des Jobs der bei Fehler (exitcode!=0) ausgeführt werden soll. xistiert ein "next-job" so wird dieser im Anschluss an start-job-on-error ausgeführt.

Auf diese Weise können Jobs miteinander verkettet werden. Die Jobs werden als FIFO-Queue abgearbeitet.

Dateisicherung mit Borg

offizielle Borg-Dokumentation

Borg ist ein cleveres Sicherungswerkzeug mit einigen praktischen Features. Jede Sicherung erfolgt in das gleiche Repository. Borg zerteilt eine Datei beim Speichern in kleine Teile, sogenannte Chunks, und speichert diese Chunks in einem Repository. Wird nun eine ähnliche oder veränderte Datei erneut gesichert, wird nur der Teil gespeichert der sich verändert hat. Die Deduplikation von Daten resultiert in schlanken täglichen Sicherungen. Ein weiteres praktisches Features ist das löschen von alten Sicherungen nach festgelegten Werten. Im Standard behalten wir die letzten 7 Tage, die letzten 2 Wochensicherungen und eine Monatssicherung. Alles andere wird von Borg automatisch gelöscht.

Konfiguration

Beispielaufruf von Borg in der /etc/backup/jobs.lst. Übernimmt die GDI-Service Wartung und Sicherung des Servers, wird diese Konfiguration automatisch geschrieben und darf nicht händisch angepasst werden.

borg create --compression auto,lzma,7 --one-file-system --stats --exclude-caches --patterns-from /etc/backup/file.patterns /home/gisadmin/Sicherungen/borgrepo::{hostname}-{now:%Y-%m-%d-%H%M%S}

borg prune --list -v --keep-within=14d --keep-weekly=4 --keep-monthly=3 /home/gisadmin/Sicherungen/borgrepo

borg compact --cleanup-commits --progress /home/gisadmin/Sicherungen/borgrepo

Aufruf + Log

Der Aufruf der jobs.lst erfolgt über cmdlogger.py /etc/backup/jobs.lst. Das Logging der letzten Ausführung kann mit cmdlogger-latest.py /etc/backup/jobs.lst ermittelt werden.

Sicherung auflisten

Alle verfügbaren Sicherungen können mit folgendem Befehl ausgelistet werden

$ borg list /home/gisadmin/Sicherungen/borgrepo/

Sicherung einsehen, zurückspielen

Borg bietet verschiedene Möglichkeiten auf Sicherungen zuzugreifen. Die einfachste ist das mounten einer Sicherung. Dazu legen wir uns einen Mountpoint an und mounten die gewünschte Sicherung anschließend mit Borg in dieses Verzeichnis:

$ mkdir /home/gisadmin/Sicherungen/borgmount
$ borg mount /home/gisadmin/Sicherungen/borgrepo/::dev-2023-05-11-122157 /home/gisadmin/Sicherungen/borgmount/

Die Sicherung ist nun unter /home/gisadmin/Sicherungen/borgmount/ verfügbar und kann bequem durchsucht werden.

Um mit Borg auf eine bestimmte Sicherung zuzugreifen ist die Syntax wie im Beispiel "PfadZumRepository::BezeichnungDerSicherung".

Ein gemountetes Repository kann nicht gesichert werden! Vor dem Sichern muss also

 $ borg umount /home/gisadmin/Sicherungen/borgmount

ausgeführt werden.

pgBackRest

Zur Sicherung des gesamten PostgreSQL-Clusters wird ab Postgres v15 pgbackrest verwendet. In unserem Docker-Image pkorduan/postgis:15-3.3 ist pgBackRest inkludiert. pgbackrest macht eine physikalische Sicherung des Clusters, es werden die Datendateien direkt gespeichert. Somit sind inkrementelle Sicherungen möglich. Zudem werden alle WAL-Dateien vom Postgres-Cluster in das pgBackRest-Repository gepusht. Somit ist ein restore zu einem beliebigen Zeitpunkt möglich.

Aufruf

Beispielaufruf von pgBackRest in einer jobs.json

       {
           "name":"postgresql"
           ,"command":["pgbackrest.sh", "kvwmap_prod_pgsql", "full"]
       },

Das erste Argument des Scriptes entspricht der Bezeichnung des Containers. Das zweite Argument ist full oder incr, je nach gewünschter Sicherungsart.

Konfiguration

Da pgBackRest direkt im Container läuft, liegt dort auch die Standardkonfiguration unter /etc/pgbackrest/conf.d/pgbackrest.local.conf. Die wichtigsten Einstellungen in der Konfiguration betreffen die Retention, das Verwerfen alter Sicherungen. Soll hier vom Standard (30 differenzielle Sicherungen, 2 Vollsicherungen) abgewichen werden, sollte eine entsprechende Datei von außen in den Container eingebunden werden.

Wiederherstellen

Grundlage: Beim restore wird ein gesamtes Cluster wiederhergestellt. In den meisten Anwendungsfällen sollen jedoch nur einzelne Schemen, Tabellen oder einzelne Datensätze wiederhergestellt werden. Zu diesem Zweck wird einer Service pgsqlrestore erstellt. Dieser stellt einmal das Restore-Cluster mit den wiederhergestellten Daten sowie die Werkzeuge zur Wiederherstellung bereit.

$ dcm create service pgsqlrestore kvwmap_prod
$ cd /home/gisadmin/networks/kvwmap_prod/services/pgsqlrestore

Prüfen Sie ob die Symlinks backup und config auf das produktive Cluster zeigen.

Auflisten der verfügbaren Sicherungen mit

$ docker exec kvwmap_prod_pgsql pgbackrest info

Die Ausgabe enthält Details zu den Sicherungen, Beispiel

$        incr backup: 20230901-220002F_20230914-220002I
$            timestamp start/stop: 2023-09-14 22:00:02 / 2023-09-14 22:00:28
$            wal start/stop: 00000001000000080000000F / 00000001000000080000000F
$            database size: 17.2GB, database backup size: 90.4MB
$            repo1: backup set size: 2.8GB, backup size: 15.9MB
$            backup reference list: 20230901-220002F, 20230901-220002F_20230902-220002I, 20230901-220002F_20230903-220002I, 20230901-220002F_20230904-220001I, 20230901-220002F_20230905-220002I, 20230901-220002F_20230906-220002I, 20230901-220002F_20230907-220002I, 20230901-220002F_20230908-220001I, 20230901-220002F_20230909-220001I, 20230901-220002F_20230910-220002I, 20230901-220002F_20230911-220002I, 20230901-220002F_20230912-220001I, 20230901-220002F_20230913-220002I

20230901-220002F_20230914-220002I ist das Label der Sicherung. Soll diese Sicherung wiederherstellt werden verwenden Sie

& ./restore.sh 20230901-220002F_20230914-220002I

Aus der Sicherung des produktiven Clusters werden die Datendateien für das Restore-Cluster nach /home/gisadmin/networks/kvwmap_prod/services/pgsqlrestore/data geschrieben. Die restore.sh ist so gestaltet, dass das Restore-Cluster im Anschluss gestartet werden kann und und keine weiteren WAL-Dateien aus dem Archiv einspielt werden. Der Stand des Restore-Clusters entspricht somit ca. dem Stopp-Zeitpunkt der Sicherung. Für eine detaillierte Wiederherstellung über LSNs, XIDs oder andere Wiederherstellungsziele siehe offizielle pgBackRest Dokumentation.

Ist restore.sh durchgelaufen kann das Cluster mit

$ dcm up pgsqlrestore kvwmap_prod

gestartet werden. Was mit den Daten im Restore-Cluster geschieht ist nicht Bestandteil dieser Dokumentation. Es können einzelne Tabellen, Schemen, DBs mit pg_dump exportiert werden um sie in das produktive Cluster zu importieren. Es kann auch das gesamte Datenverzeichnis mit cp oder rsync des produktiven Clusters durch das des Recovery-Clusters ersetzt werden.

CronJobs

Mit kvwmap lassen sich CronJobs erzeugen und verwalten. Da verwendet man den Anwendungsfall

index.php?go=cronjobs_anzeigen

Es wird angeraten dazu einen Menüpunkt unter Administration anzulegen, siehe Menüpunkt Anlegen. In der Liste der in kvwmap angelegten CronJobs wird die Bezeichung, die Zeit wann die Jobs ausgeführt werden sowie die Beschreibung angezeigt.

Anzeige der Cronjobs.png

Mit dem Button + Neuer Job wird ein Formular zum Anlegen eines neuen CronJobs geöffnet. In der Liste der angelegten CronJobs gelangt man über das Stift-Symbole gelangt man zum Ändern der Cronjobs.

CronJobs-Editieren.png

Folgende Einträge können festgelegt werden:

  • Bezeichnung: Dies kann beliebig sein, sollte sich jedoch von den anderen unterscheiden. Dient der Anzeige und Identifikation des Jobs
  • Beschreibung: Diese kann frei gewählt werden und dient der genaueren Beschreibung des Jobs. Was macht der Job und wann.
  • Zeit: Hier muss die für Cron gültige Zeichenkette angegeben werden, die festlegt wann und wie oft der Job ausgeführt wird. Siehe The time and date fields for cron
  • Datenbankname: Wenn das Feld leer gelassen wird, wird der Datenbankname von der Stelle in der die CronJobs angelegt werden genommen. Wenn dort nichts angegeben ist von der GUI. Den Eintrag braucht man nur, wenn auch ein SQL-Statement angegeben ist
  • SQL-Anfrage: Das SQL was ausgeführt werden soll. Es sind derzeit nur Anfragen auf Postgres möglich.
  • Shell Befehlszeile: Wenn kein SQL angegeben ist, kann hier ein Befehl angegeben werden, der als CronJob ausgeführt wird.

Mit dem Speichern Button wird ein vorhandener Job in der Tabelle cron_jobs aktualisiert oder mit dem Button Anlegen ein neuer Eintrag angelegt.

Damit die Änderungen wirksam werden, muss man mindestens ein mal unter der Liste der CronJobs den Button Crontab Schreiben ausführen. Dabei werden aber nur die CronJobs aus der Liste übernommen, die vorn ein Häkchen in der CheckBox haben. Bei neu angelegten Jobs muss das Häkchen extra gesetzt werden.

CronJobs-Schreiben.png

Anschließend wird die Liste der Cronjobs angezeigt wie sie für Cron aufbereitet wurde.

Liste der Cronjobs.png

Die erzeugten CronJobs werden wie folgt in den Crontab des Nutzers gisadmin geladen und ausgeführt:

  • Beim Starten des Web-Containers wird die /home/gisadmin/etc/web/env_and_volumes gelesen
  • Darin wird die Datei /home/gisadmin/etc/web/kvwmap_hourly nach /etc/cron.hourly/load_gisadmin_cron_file geladen und damit das Script ein mal pro Stunde ausgeführt
-v $USER_DIR/etc/web/kvwmap_hourly:/etc/cron.hourly/load_gisadmin_cron_file
  • In kvwmap_hourly kann natürlich noch mehr stehen, aber bezüglich der Cronjobs von kvwmap steht da, dass die Datei /var/www/cron/crontab_gisadmin falls sie existiert in den Crontab vom Nutzer gisadmin aufgenommen werden soll. Das ist genau die Datei, die mit dem Button Crontab Schreiben erzeugt wird.
  • Ist die Crontab-Datei geladen werden die darin aufgeführten Cron-Befehle ausgeführt.
  • Wenn SQL-Befehle ausgeführt werden sollen, muss für die angegebene Datenbank und den Nutzer kvwmap ein Eintrag in der Datei /home/gisadmin/.pgpass im Web-Container vorhanden sein. Der Eintrag erfolgt in folgender Form:
pgsql:5432:kvwmapsp:kvwmap:passwort
  • Die Datei muss den Status 600 haben. Am Besten man linkt die .pgpass aus /home/gisadmin/etc/postgresql/.pgpass in das gisadmin Verzeichnis in der env_and_volumes des Web-Containers.
-v $USER_DIR/etc/postgresql/.pgpass:/home/gisadmin/.pgpass
  • Die CronJobs werden als Nutzer gisadmin ausgeführt, demzufolge müssen auch Lese- und Schreibrechte für Befehle im CronJob oder Scripten beachtet werden.

Jede Änderung eines CronJobs wird also erst spätestens nach einer Stunde wirksam.

FTP Server

API Daten

Liste der Parameter zur Abfrage und Bearbeitung von Daten. Begriffe in spitzen Klammern sind als variabel zu betrachten. Die Liste ist nicht vollständig und wird nach Bedarf erweitert.

Geodaten (PostGIS Datenbank)

Parameter werden beim Aufruf der Controller-Funktion entweder direkt als Parameter der Funktion übergeben oder in einem assoziativem Array $GUI->formvars. Beispiel

$GUI->formvars['selected_layer_id']=10;
$GUI->GenerischeSuche();

Im Beispiel wird die Controller-Funktion zum Suchen mit dem Parameter selected_layer_id aufgerufen.

Abfrage in der Karte

Case:

  • go = Sachdaten

Parameter:

  • INPUT_COORD
  • rectminx, rectminy, rectmaxx, rectmaxy
  • querypolygon

(je nach Abfragevariante) Controller:

  • $GUI->queryMap() => SachdatenAnzeige($rect)

View:

  • je nach Layertyp z.B. sachdatenanzeige.php
  • in sachdatenanzeige.php wird generic_layer_editor[_2].php oder das im Layer definierte Template geladen.

Sachdatensuche

Case:

  • go = Layer-Suche

Parameter:

  • selected_layer_id = <Id des Layers in dem gesucht werden soll>

Controller:

  • $GUI->GenerischeSuche()

View:

  • layouts/snippets/generic_search.php
  • layouts/snippets/generic_search_mask.php

Beispiel: index.php?go=Layer-Suche&selected_layer_id=49

Sachdatenanzeige

Case:

  • go = Layer-Suche_Suchen

Parameter:

  • selected_layer_id = <Id des Layers in dem gesucht wird>
  • value_<Attributname> = <Wert des Attributes mit dem Namen Attributname, nach dem gesucht wird z.B. id>
  • operator_<Attributname> = <Operator, der den Wert mit dem Attribut verbindet

Controller:

  • $GUI->GenerischeSuche_Suchen()

View:

  • layouts/snippets/sachdatenanzeige.php
  • layouts/snippets/sachdatenanzeige_embedded
  • layouts/snippets/embedded_subformPK.php

Beispiel: index.php?go=Layer-Suche_Suchen&selected_layer_id=49&value_name=Naturschutzgebiete&operator_name==

Neuen Datensatz Anlegen (Eingabeformular)

Case:

  • go = neuer_Layer_Datensatz

Controller:

  • $GUI->neuer_Layer_Datensatz()

View: generic_layer_editor_2.php oder eine in used_layer gesetzte Template-Datei.

Neuen Datensatz Speichern

Case:

  • go = neuer_Layer_Datensatz_speichern

Controller:

  • $GUI->neuer_Layer_Datensatz_speichern()

Nach einem Validierungsfehler weiter mit

  • $GUI->neuer_Layer_Datensatz()

Nach dem Speichern je nach Parameter weiter_erfassen weiter mit

  • $GUI->neuer_Layer_Datensatz(), zum Eingabeformular oder
  • $GUI->GenerischeSuche_Suchen(), zur Sachdatenanzeige

Geometriedaten Speichern (Update)

Punktdaten Speichern

Case:

  • go = PointEditor_Senden

Parameter:

  • selected_layer_id = ID des zu editierenden Layers
  • loc_x = Rechtswert des einzutragenden Punktes im SRS des Layers
  • loc_y = Hochwert des einzutragenden Punktes im SRS des Layers
  • layer_tablename = Tabelle des Layers in die die Geometrie gespeichert werden soll.
  • layer_columnname = Name der Spalte in Tabelle des Layers in die die Geometrie gespeichert werden soll.
  • dimension = 3 Wenn es sich um eine 3D Punktgeometrie in PostGIS handelt.
  • oid = Die oid des Datensatzes dessen Punktgeometrie geändert werden soll.

Controller:

  • $GUI->PointEditor_Senden() darin $pointeditor->eintragenPunkt()

Polygondaten Speichern

Case:

  • go = PolygonEditor_Senden

Parameter:

  • selected_layer_id: ID des zu editierenden Layers
  • newpathwkt: Geometry im WKT Format

Controller:

  • $GUI->PolygonEditor_Senden() darin $polygoneditor->eintragenFlaeche()

Sachdaten Speichern (Update)

Case:

  • go = Sachdaten_speichern

Parameter:

  • changed_<layer_id>_<oid> = 1 ...... gibt an, dass der Datensatz geändert worden ist
  • form_field_names = <layer_id>;<attribut_name>;<table_name>;<oid>;<formtyp>;<nullable>;<datentyp><saveable> ..... die Auflistung welche Formularfeldnamen beteiligt sind; weitere sind durch das Pipe Zeichen | getrennt
  • <layer_id>;<attribut_name>;<table_name>;<oid>;<formtyp>;<nullable>;<datentyp><saveable> = <Wert> ..... die Formularfeldnamen mit ihren Werten

Controller:

  • $GUI->sachdaten_speichern()

Beispiel für Layer_ID=1769, Objekt-ID=12345, Tabellenname=fh_erfassung:

index.php?

go=Sachdaten_speichern&

changed_1769_12345=1&

form_field_names=1769;buchende_stellen;fh_erfassung;12345;Text;1;_int4;1&

1769;buchende_stellen;fh_erfassung;12345;Text;1;_int4;1=[12,42]

Dokument Löschen (in Sachdatenanzeige)

Case:

  • go = Dokument_Loeschen

Parameter:

  • document_attributename = <layer_id>;<attribut_name>;<table_name>;<oid>;Dokument;1;varchar

Controller:

  • $GUI->sachdaten_speichern()

Datensatz Löschen (in Sachdatenanzeige)

Case:

  • go = Layer_Datensaetze_Loeschen

Parameter:

  • chosen_layer_id = <layer_id>
  • check;<main_table_name>;<alias_name>;<oid> = "on"
  • checkbox_names_<layer_id> = "check;<main_table_name>;<alias_name>;<oid>"|...

optional:

  • mime_type = 'json'
  • format = 'json_result'
  • output = 'false'

Controller:

  • $GUI->layer_Datensaetze_loeschen()

Zoom zu einer Koordinate

Case:

  • go = zoom2coord

Parameter

  • INPUT_COORD Die Koordinaten getrennt durch Komma im Koordinatensystem des Parameter epsg_code
  • epsg_code (optional) Das Koordinatensystem in dem die Koordinaten angegeben sind. Unterscheidet sich das System von dem in dem der Nutzer gerade angemeldet ist, werden sie in dieses System transformiert. Wenn sie nicht angegeben sind, wird angenommen, dass die Koordinaten im Koordinatensystem angegeben sind, die der aktuelle Nutzer gerade zur Anzeige eingestellt hat. Sind die Koordinaten in Grad Minuten Sekunden Schreibweise werden diese in Dezimalgrad umgerechnet. Die Schreibweise dafür ist (54° 13.23' 5.4567).
  • name Eine Bezeichnung, die als Suchergebnis in der Legende erscheint, (optional)

Controller

  • $GUI->zoom2coord()

Beispiel:

  • index.php?go=zoom2coord&INPUT_COORD=32433010,5896996&epsg_code=4647&name=Fundort

Zoom zu einem Rechteck

Case

  • go=zoom2coord

Parameter

  • INPUT_COORD Die durch Komma getrennten Koordinaten der linken unteren und rechten oberen Ecke getrennt durch Semikolon im Koordinatensystem des Parameter epsg_code (minx,miny;maxx,maxy)
  • epsg_code (optional) Das Koordinatensystem in dem die Koordinaten angegeben sind. Unterscheidet sich das System von dem in dem der Nutzer gerade angemeldet ist, werden sie in dieses System transformiert. Wenn sie nicht angegeben sind, wird angenommen, dass die Koordinaten im Koordinatensystem angegeben sind, die der aktuelle Nutzer gerade zur Anzeige eingestellt hat. Sind die Koordinaten in Grad Minuten Sekunden Schreibweise werden diese in Dezimalgrad umgerechnet. Die Schreibweise dafür ist (54° 13.23' 5.4567).

Controller

  • $GUI->zoom2coord()

Beispiel

  • index.php?go=zoom2coord&INPUT_COORD=32433010,5896996;32433210,5897196&epsg_code=4647

Zoom zu einem Datensatz eines Layers

Parameter

  • layer_id Die ID des Layers in dem sich der Datensatz befindet.
  • layer_columnname Der Name des Attributs in dem die Geometrie ist auf die gezoomt werden soll.
  • oid Die ID des Datensatzes aus der Spalte, die in der Layerdefinition als oid-Spalte definiert ist.

Controller

  • $GUI->zoomto_dataset()

Beispiel

  • index.php?go=zoomto_dataset&layer_id=19&layer_columnname=the_geom&oid=54485

Zoom zu einem gespeicherten Kartenkommentar

Case

  • go=Kartenkommentar_Zoom

Parameter

  • storetime Zeitstempel des gespeicherten Kartenkommentars im Format "YYYY-MM-DD HH-MM-SS"
  • user_id (optional) ID des Nutzers der den Kartenkommentar gespeichert hat. Ist der Parameter=NULL wird mit der id des aktuell angemeldeten Nutzers gesucht.

Controller

  • $GUI->zoomToStoredMapExtent($storetime, $user_id)

Beispiel

  • index.php?go=Kartenkommentar_Zoom&storetime=2020-10-06 17:02:50&user_id=1

Layerauswahl Laden

Case

  • go=Layerauswahl_Laden

Parameter

  • id Die id der zuvor gespeicherten Layerauswahl
  • from_default_user (optional) Wenn dieser Parameter nicht leer ist, wird die id vom Default-Nutzer der Stelle genommen, sonst die vom aktuell angemeldeten.

Controller

  • $GUI->layerCommentLoad()

Beispiel

  • index.php?go=Layerauswahl_Laden&id=4

Kartenkonfiguration (MySQL Datenbank)

Layer Anlegen

Case

  • go=Layereditor
  • go_plus=Als%20neuen%20Layer%20eintragen

Parameter

  • id
  • Name
  • alias
  • und alle weiteren Parameter des Layers

Controller

  • $GUI->LayerAnlegen()

Layer Bearbeiten

Case

  • go=Layereditor_Speichern

Parameter

  • selected_layer_id = <Id des Layers der geändert werden soll>
  • id
  • Name
  • alias
  • und alle weiteren Parameter der Layer (Es müssen immer alle Parameter angegeben werden. Nur einzelne bedeutet nicht, dass nur diese einzelnen geändert werden.)

Controller

  • $GUI->LayerAendern()

Layer Löschen

Case

  • go=Layer_Löschen

Parameter

  • selected_layer_id = <Id des Layers der gelöscht werden soll>

Controller

  • $GUI->LayerLoeschen und GUI->LayerAnzeigen

Beispiel

  • index.php?go=Layer_Löschen&selected_layer_id=49

Attributeditor

Öffnet den Attributeditor und wenn selected_layer_id angegeben ist für den ausgewählten Layer. Case

  • go=Attributeditor (Identische mit go=Layereditor_erweiterte Einstellungen)

Parameter

  • selected_layer_id = <Id des Layers dessen Attribute angezeigt werden sollen>

Controller

  • $GUI->Attributeditor()

View

  • layouts/snippets/attribut_editor.php

Beispiel

  • index.php?go=Attributeditor&selected_layer_id=782

Style und Labeleditor

Öffnet den Editor zum Bearbeiten von Styles und Labels von Klassen der Layer und wenn selected_layer_id angegeben ist für den ausgewählten Layer. Case

  • go=Style_Label_Editor

Parameter

  • selected_layer_id = <Id des Layers dessen Styles und Labels angezeigt werden sollen>

Controller

  • $GUI->StyleLabelEditor()

View

  • layouts/snippets/style_label_editor.php

Beispiel

  • index.php?go=Style_Label_Editor&selected_layer_id=105

Menüverwaltung

Öffnet die Liste der Menüpunkte. Case

  • go=Menues_Anzeigen

Controller

  • $GUI->MenuesAnzeigen

View

  • layout/snippets/menuedaten.php

Benutzung von kvwmap

Stelle Wählen

siehe Nutzer-Dokumentation

Drucken in PDF

Um in einer Stelle in PDF drucken zu können, muss der Administrator vorher einen Menüpunkt sowie einen oder mehrere zur Auswahl stehende Kartendruck-Layouts eingerichtet haben. Das Erstellen der Kartendruck-Layouts erfolgt im Kartendruck-Layouteditor (go=Druckrahmen). Jedes Kartendruck-Layout kann in beliebig vielen Stellen verwendet werden.

Der Druck erfolgt über die Druckausschnittswahl (go=Druckausschnittswahl). Hier ist zunächst der aktuelle Kartenausschnitt mit den üblichen Navigationswerkzeugen zu sehen. Über die Themenauswahl können auch hier Themen ein- oder ausgeschaltet werden. Zusätzlich stehen ein Eingabefeld zur Angabe des gewünschten Druckmaßstabes und ein Auswahlfeld zur Auswahl des gewünschten Kartendruck-Layouts zur Verfügung. Es kann auch der aktuelle Kartenmaßstab am Bildschirm als Druckmaßstab gewählt werden, dafür gibt es eine Schaltfläche Kartenmaßstab übernehmen. In der Karte kann der gewünschte Druckausschnitt gewählt werden, der in das PDF exportiert werden soll. Dafür gibt es die Schaltfläche Druckausschnitt setzen. Der Druckausschnitt wird per Klick in die Karte gesetzt. Der Klick bestimmt den Mittelpunkt des Druckausschnitts. Wiederholte Klicks verschieben den Druckausschnitt. Ist der Kartenausschnitt zu klein bzw. zu groß, muss der Druckmaßstab entsprechend angepasst werden.

Unterhalb der Karte kann ein Drehwinkel für den Druckausschnitt eingegeben werden. Außerdem können Lage und Größe des aktuell gesetzten Druckausschnitts (nicht aber die gerade angeschalteten Themen oder das gerade gewählte Kartendruck-Layout) gespeichert werden.

Hat der Druckausschnitt das richtige Kartendruck-Layout, die gewünschte Position und die gewünschte Größe, kann das PDF durch Klick auf Drucken direkt erzeugt und anschließend gespeichert oder ausgedruckt werden.

Beim Klick auf Vorschau gelangt man zu einer Druck-Voransicht, die das spätere PDF-Dokument, d.h. den Kartenausschnitt plus das gewählte Kartendruck-Layout, am Bildschirm anzeigt. Hier kann man beispielsweise überprüfen, ob alle benötigten Kartenelemente zu erkennen sind. Sind im Kartendruck-Layouteditor für dieses Kartendruck-Layout variable Freitexte erlaubt werden, kann der Bearbeiter einen oder mehrere sog. Freitexte beliebig positionieren, beliebig mit Text füllen und beliebig in Größe und Form ändern.

Ist die Druckvorschau nicht zufriedenstellend, gelangt man durch Klick auf 'zurück' wieder zur Druckausschnittswahl und kann die Einstellungen anpassen. Ist die Vorschau in Ordnung, kann man durch Klick auf Drucken das PDF erzeugen.

Es ist möglich, den Druck zu kacheln, das heißt, Druckausschnitte exakt neben- bzw. untereinander zu positionieren. Hat man einen PDF-Ausdruck via Drucken erstellt, kehrt man über zurück zum Druckausschnitt zur Auswahl der Druckausschnitts zurück. Der Druckausschnitt ist in der Karte noch positioniert. Wenn man mit dem Cursor über eine der 4 Kanten des Druckausschnitts fährt, erscheint ein kleines Dreieck. Ein Klick auf dieses Dreieck verschiebt den Druckausschnitt so, dass der neue Ausschnitt an dieser Kante exakt neben bzw. unter oder über dem vorherigen Ausschnitt positioniert wird.

Metadaten

Eingabe

Zur Erfassung von Metadaten wird zunächst der entsprechende Menüpunkt ausgewählt. Zur Einbindung des Menüpunktes siehe Menüverwaltung. Der Linke auf diesen Anwendungsfall lautet index.php?go=Metadateneingabe.

Das Eingabeformular für die Metadaten enthält gemäß ISO 19119 für Servicemetadaten einige Pflichtangaben und einige optionale. Die Pflichtangaben sind durch * gekennzeichnet, siehe Bild:Metadateneingabe.png. Je nachdem was man beschreiben möchte wählt man die Art der Metadaten aus. Die Id des Metadatensatzes wird vorgegeben. Vorgegeben werden auch die Auswahlmöglichkeiten für die Kategorie und Schlagwörter. Wenn die Listen angepasst werden sollen, muss dies im Snippets "metadateneingabeformular.php" bzw. in der Tabelle md_keywords durch einen Administrator erfolgen.

Um das Umschließende Rechteck zu ermitteln kann man in der Karte ein Rechteckaufziehen und den Button "Box aus Karte" wählen. Die Koordinaten werden in die Textfelder übernommen.

Einige Metadaten gelten nur für Services, Datensätze oder Applikationen und müssen nur bei Bedarf ausgefüllt werden.

Nach dem Senden des Metadatendokumentes wird geprüft ob alle Pflichtfelder ausgefüllt wurden. Wenn die Speicherung erfolgte, werden die Angaben für eine nächste Eingabe übernommen. Das entsprechende Auswahlfeld neben dem Zurücksenden Button sorgt dafür, dass nach dem Senden mehr Infos zu Metadaten angezeigt werden, z.B. die Bezeichnungen der Metadatenelemente im Standard oder sonsotige Hinweise.

Alle eingegebenen Daten werden in die Tabelle md_metadata gespeichert. Die Zuordnung zwischen den Schlagwörtern und dem Metadatendokument erfolgt über die Tabelle md_keywords2metadata.

Suche

Nach Metadaten kann entweder über ein spezielles Suchfenster gesucht werden oder über die normale Sachdatenabfrage im Kartenfenster. Bei letzerer Variante muss jedoch ein Layer für die Metadatenboxanzeige angelegt und der Stelle zugewiesen worden sein, siehe Abschnitt Layer.

Für das Suchen über das Suchfenster nutzt man den Menüpunkt "Suchen" Unterpunkt "Metadaten". Wenn dieser noch nicht eingerichtet ist, muss das vorher durch einen Administrator erfolgen. Der Link auf den Anwendungsfall lautet:index.php?go=Metadaten_Auswaehlen, siehe Abschnitt: Menü. Das Suchformular ist einfach gehalten. Es kann nach dem Was, Wo, Wer und Wann gesucht werden. Die Suche wird in den entsprechenden Metadatenelementen räumlich, thematisch und/oder zeitlich vorgenommen. Zur räumlichen Auswahl kann auch hier wieder ein Rechteck in der Karte gezeichnet werden und mit "Box aus Karte" in die Formularfelder übernommen werden, siehe Bild:Metadatensuche.png.

Das Suchergebnis besteht aus einer Trefferliste mit verkürzten Informationen zu dem Metadatensatz, siehe Bild:Metadatenergebnis.png. Ein Link führt auf die Detailanzeige, siehe Bild:Metadatendetailansicht.png und ein Link zur Bearbeitung des Datensatzes, wie im Eingabeformular.

Anzeige

Die Anzeige der Metadaten erfolgt nach der Suche über das spezielle Suchformular oder nach der Sachdatenabfrage über die Karte. Da wie bei allen Layern das Template für die Sachdatenanzeige frei gewählt werden kann, ist es möglich, dass ein Administrator auch ein anderes Layout für die Anzeige der Metadaten wählt, als standardmäßig vom GLE erzeugt wird. Bei Metadaten ist es z.B. genau das selbe Template zu verwenden, wie es auch für die Trefferlistenanzeige verwendet wird. Dazu ist das Template "Metadaten.php" in den stellenbezogenen Layereigenschaften einzutragen.

Layer aus Mapdatei laden

Über die Funktion "Layer aus Mapdatei laden" (go-Variable: layerfrommapfile) hat man die Möglichkeit Mapdateien einzulesen und die darin enthaltenen Layer-, Klassen-, Styles- und Labels in die MySQL-DB zu speichern.

Layerfrommapfile.jpg

Man kann entweder eine einzelne Mapdatei hochladen oder eine gezippte Verzeichnisstruktur, in der die Fonts, Symbole usw. enthalten sind. Läd man eine Zip-Datei hoch, stehen alle in diesem Archiv vorhandenen Mapdateien für den Einlesevorgang zur Auswahl. Beim Einlesen der Mapdateien ist darauf zu achten, dass die Pfadangaben für das Fontset und das Symbolset in der Mapdatei stimmen. Ansonsten funktioniert der Einlesevorgang nämlich nicht.

Nachdem die ausgewählte Mapdatei eingelesen wurde, werden alle in ihr enthaltenen Layer nach Gruppen geordnet untereinander aufgelistet. Die Layer, die in der Mapdatei keiner Gruppe zugeordnet wurden, werden der Gruppe "Gruppe1" zugeordnet. Hinter jedem Layer gibt es eine Checkbox, über die man festlegen kann, ob der jeweilige Layer in die Datenbank gespeichert werden soll. Zusätzlich kann hier noch ausgewählt werden, ob das Font- und Symbolset um die zusätzlichen Fonts bzw. Symbole erweitert werden soll. Bei Auswahl der Fontseterweiterung werden außerdem noch die neuen Fonts in den Fontordner kopiert. Hierbei ist jedoch darauf zu achten, dass keine vorhandenen Symbole oder Fonts überschrieben werden. Daher empfiehlt es sich, diese beiden Anpassungen von Hand zu machen.

Nach Auswahl der gewünschten Layer klickt man auf "Layer hinzufügen" und die entsprechenden Layer werden in die Datenbank geschrieben. Nach erfolgter Speicherung der Layer wird ausgegeben, wieviele Gruppen, Layer, Klassen, Styles und Labels in die Datenbank eingefügt wurden.

ALKIS-Änderung

Zur Aktualisierung von ALKIS-Daten wird die ogr-Bibliothek verwendet.

Entsprechende Scripte zum Einlesen sind im Plugin alkis im Unterordner tools enthalten.

WMS-Konformität

Kvwmap kann auf zwei Arten als WMS konformer MapServer eingesetzt werden.

über Mapfile per CGI

Dazu produziert kvwmap „Mapfiles“ mit entsprechenden Metadaten (siehe MapServer WMS Server HOWTO).

Den Speicherort für Mapdateien stellen Sie über die Konstante WMS_MAPFILE_Path ein.

Wenn Sie eine WMS konforme Map-Datei erstellen wollen, klicken auf den Menüpunkt WMS-Export und geben dort den Namen der Datei (z.B. wms_test.map) an. In dieser Datei wird dann der zuletzt angezeigte Zustand der kvwmap Kartenansicht abgelegt und ist für die Nutzung in einem Web Map Service nutzbar. Die Map-Datei enthält alle Metadaten, die für den getCapabilities Request erforderlich sind.

Die Map-Datei sollte in einem WWW-Verzeichnis stehen, z.B. /meinwwwroot/WMS. Dieses Verzeichnis muss wwwrun gehören.

Auf diese Map-Datei kann dann wie folgt zugegriffen werden.

getCapabilities-Request

http...://www.myserver.de/cgi-bin/mapserv?map=/mywwwroot/WMS/wms_test.map
&request=getcapabilities&service=wms&version=1.1.0

In dem vom MapServer geliefertem XML-Dokument sind die verfügbaren Layer aufgelistet. Diese können dann im getMap-Request zur Ansicht gebracht werden.

getMap-Request

http...://www.myserver.de/cgi-bin/mapserv?map=/mywwwroot/WMS/wms_test.map&service=wms
&request=getmap&version=1.1.0&layers=Landkreis,Gemeinde,Gemarkung,LSG& Height=500&width=500

über kvwmap mit go=OWS

Dazu wird direkt kvwmap aufgerufen mit dem Anwendungsfall go=OWS. Genau wie beim normalen Aufruf der Anwendung muß sich der Nutzer auch hier beim ersten Mal authentifizieren. Dann stehen alle Layer des Nutzers in der aktuellen (letzten) Stelle als WMS zur Verfügung. Hinter go=OWS kann auch der Benutername, das Passwort und die Stelle angegeben werden um den Dialog für die Anmeldung zu umgehen. Die Onlineresource eines kvwmap OWS-Request sieht also etwa wie folgt aus:

https...://meinserver.de/kvwmap/index.php?go=OWS&login_name=derName&passwort=dasPasswort&Stelle_ID=dieStellenId&

Hinter diesen Parametern können dann alle WMS konformen Anfrageparameter angehängt werden, für alle Requestarten.

Im Beispiel ist ein getCapabilities Aufruf dargestellt.

https...://meinserver.de/kvwmap/index.php?go=OWS&login_name=derName&passwort=dasPasswort&Stelle_ID=dieStellenId&Request=GetCapabilities&Service=WMS

Existiert eine Stelle nicht oder jemand versucht auf eine falsche Stelle zuzugreifen, für die keine Berechtigung vorliegt wird folgende Exception zurückgeliefert:

OWSServiceException.png

Für die Bereitstellung von Layern / Features in der Stelle, die im Dienst genutzt wird gelten folgende Bedingungen

  • Die Layerdefinitionen müssen den gleichen EPSG-Code haben wie die Stelle
  • Der Layername darf keine Leerzeichen oder Umlaute beinhalten, es sei denn es gibt einen Aliasnamen und die Verwendung der Aliasnamen ist in der Stelle eingestellt
  • Aliasnamen dürfen keine Leerzeichen oder Umlaute beinhalten wenn die Verwendung der Aliasnamen in der Stelle eingestellt ist.
  • Bei WFS muss ein Attribut ogc_fid in der data-Definition definiert sein

ESRI-Shape Import

Der Import von Shape Dateien in die PostGIS Datenbank wird mit dem Anwendungsfall: go=SHP_Import gestartet.

Oberfläche zum Hochladen der Shape Dateien

Die zur Shape-Datei gehörenden Dateien (shp, shx und dbf und optional prj) müssen als ZIP-Datei gepackt auf den Server hochgeladen werden. Anschließend können die Einstellungen für den Import vorgenommen werden.

Einstellungen zum Import von Shape Dateien

Zunächst muss angegeben werden, in welches Schema und in welche Tabelle die Daten importiert werden sollen. Wenn eine prj-Datei vorhanden ist, wird versucht, das Koordinatenreferenzsystem aus ihr zu ermitteln. Ansonsten muss er von Hand eingetragen werden.

Außerdem kann ausgewählt werden, ob die Daten in eine neue Tabelle eingefügt werden, eine vorhandene Tabelle überschrieben werden soll oder die Daten an eine vorhandene Tabelle angehängt werden sollen.

Die Zuordnung zwischen den Attributen in der dbf-Tabelle und der Tabelle in der Datenbank kann folgendermaßen erfolgen. Das Entfernen des Häkchens aus der Checkbox bedeutet, dass das Attribut nicht übernommen wird. Wenn ein Attribut einen anderen Namen in der DB-Tabelle bekommen soll oder schon hat, kann der dieser hier angegeben werden.

Fehlermeldungen

Wenn die Parameter format=json, format=json_result, mime_type=json oder content_type=application_json bei einer Anfrage angegeben werden, wird eine Fehlermeldung im JSON-Format { "success" : false, "msg" : "Fehlermeldung" } mit dem HTML-Header Content-Type: application/json ausgegeben statt mit einer HTML-Fehlermeldung und HTML-Response-Code 500.

siehe auch Nutzer-Dokumentation

SQL-Fehler

Das Textfeld in dem die SQL-Statements ausgegeben werden hat die Klasse sql-statement und kann mit einem eigenen Style überschrieben werden. Darüber läßt sich z.B. die Höhe des Textfeldes individuell anpassen.

.sql-statement {
 ...
 height: 25em;
}

Weitere Hilfe

Unter der Rubrik Foren in der Menüleiste links finden Sie weitere Hilfe. Unter anderem befindet sich dort ein Bug-Report, eine Liste mit HowTo und eine allgemeine Fragen-Liste zu kvwmap.

Viele Einträge sind von Nutzern selber gemacht worden. Scheuen Sie sich also nicht hier im Wiki auch zur Dokumentation von kvwmap beizutragen.