geocoder.php 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. <?php
  2. class GeocoderBehavior extends ModelBehavior {
  3. /**
  4. * Contain settings indexed by model name.
  5. *
  6. * @var array
  7. * @access private
  8. */
  9. var $__settings = array();
  10. var $log = true; // log successfull results to geocode.log (errors will be logged to error.log in either case)
  11. /*
  12. accuracy:
  13. 0 Unbekannter Ort. (Seit 2.59)
  14. 1 Land. (Seit 2.59)
  15. 2 Bundesland/Bundesstaat, Provinz, Präfektur usw. (Seit 2.59)
  16. 3 Bezirk, Gemeinde usw. (Seit 2.59)
  17. 4 Ortschaft (Stadt, Dorf). (Seit 2.59)
  18. 5 Postleitzahl (PLZ). (Seit 2.59)
  19. 6 Straße. (Seit 2.59)
  20. 7 Kreuzung. (Seit 2.59)
  21. 8 Adresse. (Seit 2.59)
  22. */
  23. /**
  24. * Initiate behavior for the model using specified settings. Available settings:
  25. *
  26. * - label: (array | string, optional) set to the field name that contains the
  27. * string from where to generate the slug, or a set of field names to
  28. * concatenate for generating the slug. DEFAULTS TO: title
  29. *
  30. * - real: (boolean, optional) if set to true then field names defined in
  31. * label must exist in the database table. DEFAULTS TO: true
  32. *
  33. * - accuracy: see above
  34. *
  35. * @param object $Model Model using the behaviour
  36. * @param array $settings Settings to override for model.
  37. * @access public
  38. */
  39. function setup(&$Model, $settings = array()) {
  40. $default = array('real' => true, 'address' => array('street','zip','city'), 'lat'=>'lat','lng'=>'lng','formatted_address' => null, 'min_accuracy' => 4, 'allow_inconclusive' => false, 'host' => 'us', 'language' => 'de', 'region'=> '', 'bounds' => '', 'overwrite' => false);
  41. if (!isset($this->__settings[$Model->alias])) {
  42. $this->__settings[$Model->alias] = $default;
  43. }
  44. $this->__settings[$Model->alias] = array_merge($this->__settings[$Model->alias], ife(is_array($settings), $settings, array()));
  45. }
  46. /**
  47. * Run before a model is saved, used to set up slug for model.
  48. *
  49. * @param object $Model Model about to be saved.
  50. * @return boolean true if save should proceed, false otherwise
  51. * @access public
  52. */
  53. function beforeSave(&$Model) {
  54. $return = parent::beforeSave($Model);
  55. // Make address fields an array
  56. if (!is_array($this->__settings[$Model->alias]['address'])) {
  57. $addressfields = array($this->__settings[$Model->alias]['address']);
  58. } else {
  59. $addressfields = $this->__settings[$Model->alias]['address'];
  60. }
  61. $addressfields = array_unique($addressfields);
  62. // Make sure all address fields are available
  63. if ($this->__settings[$Model->alias]['real']) {
  64. foreach($addressfields as $field) {
  65. if (!$Model->hasField($field)) {
  66. return $return;
  67. }
  68. }
  69. }
  70. $adressdata = array();
  71. foreach($addressfields as $field) {
  72. if (!empty($Model->data[$Model->alias][$field])) {
  73. $adressdata[] = ife(!empty($label), ' ', '') . $Model->data[$Model->alias][$field];
  74. }
  75. }
  76. // See if we should request a geocode
  77. if ((!$this->__settings[$Model->alias]['real'] || ($Model->hasField($this->__settings[$Model->alias]['lat']) && $Model->hasField($this->__settings[$Model->alias]['lng']))) && ($this->__settings[$Model->alias]['overwrite'] || (empty($Model->data[$Model->alias][$this->__settings[$Model->alias]['lat']]) || ($Model->data[$Model->alias][$this->__settings[$Model->alias]['lat']]==0 && $Model->data[$Model->alias][$this->__settings[$Model->alias]['lat']]==0)))) {
  78. $geocode = $this->__geocode($adressdata, $this->__settings[$Model->alias]);
  79. // Now set the geocode as part of the model data to be saved, making sure that
  80. // we are on the white list of fields to be saved
  81. //pr ($Model->whitelist); die();
  82. if (!empty($Model->whitelist) && (!in_array($this->__settings[$Model->alias]['lat'], $Model->whitelist) || !in_array($this->__settings[$Model->alias]['lng'], $Model->whitelist))) {
  83. /** HACK to prevent 0 inserts if not wanted! just use whitelist now to narrow fields down - 2009-03-18 ms */
  84. //$Model->whitelist[] = $this->__settings[$Model->alias]['lat'];
  85. //$Model->whitelist[] = $this->__settings[$Model->alias]['lng'];
  86. return $return;
  87. }
  88. # if both are 0, thats not valid, otherwise continue
  89. if (!empty($geocode['lat']) || !empty($geocode['lng'])) { /** HACK to prevent 0 inserts of incorrect runs - 2009-04-07 ms */
  90. $Model->data[$Model->alias][$this->__settings[$Model->alias]['lat']] = $geocode['lat'];
  91. $Model->data[$Model->alias][$this->__settings[$Model->alias]['lng']] = $geocode['lng'];
  92. } else {
  93. if (isset($Model->data[$Model->alias][$this->__settings[$Model->alias]['lat']])) {
  94. unset($Model->data[$Model->alias][$this->__settings[$Model->alias]['lat']]);
  95. }
  96. if (isset($Model->data[$Model->alias][$this->__settings[$Model->alias]['lng']])) {
  97. unset($Model->data[$Model->alias][$this->__settings[$Model->alias]['lng']]);
  98. }
  99. }
  100. if(!empty($this->__settings[$Model->alias]['formatted_address'])){
  101. $Model->data[$Model->alias][$this->__settings[$Model->alias]['formatted_address']] = $geocode['formatted_address'];
  102. } else {
  103. if (isset($Model->data[$Model->alias][$this->__settings[$Model->alias]['formatted_address']])) {
  104. unset($Model->data[$Model->alias][$this->__settings[$Model->alias]['formatted_address']]);
  105. }
  106. }
  107. if (!empty($geocode['inconclusive'])) {
  108. $Model->data[$Model->alias]['inconclusive'] = $geocode['inconclusive'];
  109. $Model->data[$Model->alias]['results'] = $geocode['results'];
  110. }
  111. # correct country id if neccessary
  112. if (in_array('country_name', $this->__settings[$Model->alias]['address'])) {
  113. if (!empty($geocode['country']) && in_array($geocode['country'], ($countries = Country::addressList()))) {
  114. $countries = array_shift(array_keys($countries, $geocode['country']));
  115. $Model->data[$Model->alias]['country'] = $countries;
  116. } else {
  117. $Model->data[$Model->alias]['country'] = 0;
  118. }
  119. }
  120. }
  121. return $return;
  122. }
  123. function __geocode($addressfields, $options = array()) {
  124. $address = implode(' ', $addressfields);
  125. App::import('Lib', 'Tools.GeocodeLib');
  126. $this->Geocode = new GeocodeLib(array('min_accuracy'=>$options['min_accuracy'], 'allow_inconclusive'=>$options['allow_inconclusive'], 'host'=>$options['host']));
  127. $settings = array('language'=>$options['language']);
  128. if (!$this->Geocode->geocode($address, $settings)) {
  129. return array('lat'=>0,'lng'=>0,'official_address'=>'');
  130. }
  131. $res = $this->Geocode->getResult();
  132. if (isset($res[0])) {
  133. $res = $res[0];
  134. }
  135. //TODO: rename to formatted_address
  136. # hack
  137. $res['official_address'] = $res['formatted_address'];
  138. return $res;
  139. }
  140. }
  141. ?>