Hilfe beim schreiben von Werten in Custom Fields
am 15.07.2014 - 17:17 Uhr in
Hi Drupalcommunity,
Ich habe eine Aufgabenstellung, die mich momentan länger beschäftigt, weil mir der tiefere Einblick und Verständnis des Drupal 7 API fehlt und die Dokumentation mir noch einige Fragen offen lässt.
Ich habe das Modul Geolocation und dazu nutze ich ip_geolocation. Ich finde das für den Endbenutzer sehr simpel und perfekt um entsprechend Map Einträge schnell vorzunehmen ohne viele Angaben machen zu müssen.
Leider speichert dieses Modul nur latitude und longitude. Ich dachte mir, nimmst Du halt noch das location Modul um dann die werte per Rules zu übertragen, aber rules darf auf das Geolocation Field nicht zugreifen(es wird auch garnicht trotz "scope" versuche nicht eingeblendet, lediglich zugriff auf location field ging, aber kein Schreibrecht).
Nun ja, ich habe jetzt ein Modul angefangen zu schreiben, dass die long und lat werte aus spot content in $lat und $lon speichert und danach mit einem PHP Google APi3 Skript entsprechend das Adress Array besorgt.
Jetzt würde ich aber gerne folgendes Problem lösen:
Mit den Addressdaten würde ich nun gern im gleichen Content die Location Felddaten ausfüllen. Mir ist noch schleierhaft wie ich in Felder schreiben darf. Alternativ hatte ich überlegt den langen PHP code einfach in rules reinzuwürgen, aber da rules kein Schreibrecht hat location felder mit daten auszufüllen wird diese Lösung auch nicht funktionieren.
Mein Ziel ist sozusagen die location Felddaten zu verstecken und nur für die proximity Suche bzw. detailierte inhaltssuche per views einzubinden(falls man sich fragt warum ich die Daten nochmal umwandel für die verwendung). Der Aufwand eine eigene "such" funktion zu schreiben scheint mir schwerer zu sein als einfach die Daten im Location Modul auszufüllen um sie dann dort zu verwenden.
Trigger wäre sozusagen wenn ein neuer Content Typ "Map" erstellt wird, dann soll vor dem speichern Location mit dem Abgleich über Google dank der eingegeben lat und long werte überschrieben werden.
Also was ich suche ist sozusagen ein Trigger wie bei Rules vorm endgültigen Speichern des inhalts möchte ich nun die Werte per Hand entsprechend eintragen.
Ausser jemand hat einen netten Trick das ganze auch per Rules oder anderen Modulen eleganter zu lösen. Zielsetzung ist die simple Eingabe wie mit Geolocation und anschliessend flexible Gestaltung der View dank location modul. Ich möchte also eigentlich nur die daten von einem Feld ins andere übertragen und die ganzen Angaben zu den Adressfeldern werden dann über die API ausgelesen.
Hoffe ich drücke mich verständlich genug aus :D
Vielen Dank!
- Anmelden oder Registrieren um Kommentare zu schreiben
Ich habe jetzt ehrlich gesagt
am 15.07.2014 - 19:03 Uhr
Ich habe jetzt ehrlich gesagt nicht verstanden was Du da macen willst.
Aber sollte jetzt Deine abschliessenden Frage sein:
Also was ich suche ist sozusagen ein Trigger wie bei Rules vorm endgültigen Speichern des inhalts möchte ich nun die Werte per Hand entsprechend eintragen.
so macht man das entweder mit hook_node_update oder hook_node_insert.
Wenn Du also einen Inhalt neu anlegst, so greift insert. Wenn Du ihn updatest ...
Aber obige Erklärung ist mir zu diffus. Vielleicht erläuterts Du mal genauer was Du machen möchtest.
Hi, Also das mit dem Hook
am 15.07.2014 - 19:44 Uhr
Hi,
Also das mit dem Hook werde ich dann später im Büro nochmal austesten.
Ich versuche mal das inhaltlich etwas weniger diffus zu erklären.
Also wir haben einen Content Type "Map"
Dort ist ein Feld angelegt vom Typ geocoder mit dem Namen "Spot". Spot speichert dank des Aufbaus des Moduls "nur" longitude und latitude der position auf der Googlemap. Eine Adresse kann beim erstellen des Inhaltstyps eingegeben werden wie bei Google, aber gespeichert wird nur (abgekürzt) lon und lat als Datensatz.
Zusätzlich zu Spot habe ich ein Feld vom Typ location(vom location Modul) names "Address" angelegt um dort restliche Daten eintragen zu können wie Ort, PLZ, Strasse usw., weil wie erwähnt das obere Modul solche Daten nicht speichert.
Jetzt könnte man sagen für die Ausgabe reicht das "geocoder" Modul wenn man eine Template File anfertigt die einfach per php und der google api sich die Daten von Ort, PLZ usw. einfach aus den lat und lon wert übergibt und ausgibt.
Ich möchte aber nun eine Suchmaske anfertigen womit der Benutzer selbst nach plz oder Ort usw. suchen kann, nur geht das mit dem location Modul.
Also was will ich genau? Ich möchte mit dem hook_node_insert mit meinen eigenen PHP google api Codes die Adressdaten aus "spot" in das "location" Feld "Address" eintragen.
Vielleicht kenne ich die Flexibilität dieser Module nicht so gut und könnte das anders machen, aber mit Rules z.B. kann man auf die Felder trotz "entity has field" nicht auflisten und somit nicht zugreifen.
Folgendes habe ich
am 15.07.2014 - 22:43 Uhr
Folgendes habe ich verstanden:
Es werden von wem auch immer Adressdaten erfasst.Diese Daten liegen bis dato nur als lat-long vor??? Diese Daten liegen als Adresse vor, werden aber nicht als Adresse abgespeichert?
Ich habe mal irgendwann vor 2-3 Jahren eine Seite gebaut, in der mithilfe des location Moduls eine Umgebungssuche gebaut wurde. Ich kann mich dran erinnern dass man die Adresse normal eingegeben hat und dann mit der Google api die lat-long per Webservice abgegriffen und gespeichert wurde.
Wenn ich dann die Suche bemüht habe, konnte ich mir in maps die Treffer anzeigen lassen. Ging meines Wissens nach alles über location.
Wenn bei Location eine
am 15.07.2014 - 22:47 Uhr
Wenn bei Location eine Adresse angegeben wurde, wird diese auch geocodiert, sprich, in lat/lon umgerechnet und gespeichert.
Wenn du diese trotzdem mit den Werten aus dem "spot"-feld überschreiben willst (ich weiß nicht ob es dann keine Probleme mit Location gibt), kannst Du das z.B. mit "Computed Field" machen .... das ist ein Node-Field in welches Du PHP-Code angeben kannst. Damit kannst Du z.B. on-the-fly die Werte aus "Spot" lesen und Location übergeben (und vieles mehr).
https://www.drupal.org/project/computed_field
Drupal rockt!!!
Hi,Also für das bessere
am 16.07.2014 - 12:42 Uhr
Hi,
Also für das bessere Verständnis meiner Aufgabe:
das location modul ist als Feld im Content Type Map vorhanden ist aber per template ausgeblendet beim erstellen von inhalten. Diese Feld wird nicht vom User ausgefüllt. Das einzige Feld um eine Adresse anzugeben ist über geolocation Modul. Man hat wie bei google eine Zeile die man flexibel alles wie bei google einträgt, auf suchen clickt, das ergebnis auf der map unten sieht und dann bei bedarf den pin verschiebt und die anschrift im suchfeld wird dynamisch aktualisiert. Finde für den Endnutzer die beste eingabe schnittstelle. Auf wunsch kann er die ip geolocation funktion laufen lassen per click.
Ich möchte eigentlich nachdem der user einen map inhalt erstellt hat einfach die lat und lon werte die das modul nun aufgenommen hat einfach ins location übertragen und zusätzlich per google api php code entsprechend die felder danach ausfüllen.
Das "computed Fields" habe ich glatt vergessen als möglichen Lösungsweg, damit liese sich bestimmt meine Problematik lösen. Ist nur die Frage ob per modul oder über das Feld.
Erstmal muss der Code sitzen und funktionieren, dann bleibt ja immernoch die Entscheidung ob nun per Computed Fields oder per Modul. Scheint so, dass ich mit den Frontend Methoden nicht weiter komme, sondern hier definitiv unter die Haube gehen muss :D
UPDATE:
So, habe die Lösung meines Problems als Modul realisiert. Es gibt noch ein Wenig feinschliff der noch final kommt, aber die Funktionsweise davon ist perfekt.
Falls wer so etwas ähnliches anstrebt oder code zeilen gebrauchen hier mal der Code vom Modul(achtet nur bei der Verwendung darauf auf die richtigen Feldnamen zu beziehen und Content Types), dpm funktion kann ausgeklammert werden, hatte es nur um mir die genauen Felder rauszukriegen und ob meine Funktion stimmt, auch save node darf hier nicht angewandt werden!:
<?php
/*
* Given longitude and latitude, return the address using The Google Geocoding API V3
*
*/
function Get_Address_From_Google_Maps($lat, $lon) {
$url = "http://maps.googleapis.com/maps/api/geocode/json?latlng=$lat,$lon&sensor=false&language=de";
// Make the HTTP request
$data = @file_get_contents($url);
// Parse the json response
$jsondata = json_decode($data,true);
// If the json data is invalid, return empty array
if (!check_status($jsondata)) return array();
$address = array(
'country' => google_getCountry($jsondata),
'province' => google_getProvince($jsondata),
'city' => google_getCity($jsondata),
'street' => google_getStreet($jsondata),
'postal_code' => google_getPostalCode($jsondata),
'country_code' => google_getCountryCode($jsondata),
'formatted_address' => google_getAddress($jsondata),
);
return $address;
}
/*
* Check if the json data from Google Geo is valid
*/
function check_status($jsondata) {
if ($jsondata["status"] == "OK") return true;
return false;
}
/*
* Given Google Geocode json, return the value in the specified element of the array
*/
function google_getCountry($jsondata) {
return Find_Long_Name_Given_Type("country", $jsondata["results"][0]["address_components"]);
}
function google_getProvince($jsondata) {
return Find_Long_Name_Given_Type("administrative_area_level_1", $jsondata["results"][0]["address_components"], true);
}
function google_getCity($jsondata) {
return Find_Long_Name_Given_Type("locality", $jsondata["results"][0]["address_components"]);
}
function google_getStreet($jsondata) {
return Find_Long_Name_Given_Type("street_number", $jsondata["results"][0]["address_components"]) . ' ' . Find_Long_Name_Given_Type("route", $jsondata["results"][0]["address_components"]);
}
function google_getPostalCode($jsondata) {
return Find_Long_Name_Given_Type("postal_code", $jsondata["results"][0]["address_components"]);
}
function google_getCountryCode($jsondata) {
return Find_Long_Name_Given_Type("country", $jsondata["results"][0]["address_components"], true);
}
function google_getAddress($jsondata) {
return $jsondata["results"][0]["formatted_address"];
}
/*
* Searching in Google Geo json, return the long name given the type.
* (If short_name is true, return short name)
*/
function Find_Long_Name_Given_Type($type, $array, $short_name = false) {
foreach( $array as $value) {
if (in_array($type, $value["types"])) {
if ($short_name)
return $value["short_name"];
return $value["long_name"];
}
}
}
function mapnode_node_presave($node) {
if ($node->type == 'spot') {
$lat = $node->field_einstieg['und'][0]['lat'];
$lon = $node->field_einstieg['und'][0]['lng'];
$latlonconvert = Get_Address_From_Google_Maps($lat, $lon);
dpm($node); //(1)
$node->field_einstieg2['und'][0]['name'] = $node->title;
$node->field_einstieg2['und'][0]['street'] = $latlonconvert['street'];
$node->field_einstieg2['und'][0]['city'] = $latlonconvert['city'];
$node->field_einstieg2['und'][0]['postal_code'] = $latlonconvert['postal_code'];
dpm($node); //(2)
//node_save($node);
}
}
?>