Address.class.php 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. <?php
  2. /**
  3. * Define a address.
  4. * @author Valentin CARRUESCO
  5. * @category Plugin
  6. * @license MIT
  7. */
  8. class Address extends Entity{
  9. public $id,$uid,$scope,$label,$type,$street,$complement,$city,$zip,$country,$state;
  10. const INVOICE = 'invoice';
  11. const SHIPPING = 'shipping';
  12. const MAIN = 'global';
  13. public $entityLabel = 'Adresse';
  14. public $fields = array(
  15. 'id' => array('label'=>'Identifiant','type'=>'key'),
  16. 'uid' => array('label'=>'Identifiant de l\'Entité liée','type'=>'integer'),
  17. 'scope' => array('label'=>'Périmetre de l\'entité liée','type'=>'text'),
  18. 'label' => array('label'=>'Libellé','type'=>'text'),
  19. 'type' => array('label'=>'Type','type'=>'text'),
  20. 'street' => array('label'=>'Rue','type'=>'text'),
  21. 'complement' => array('label'=>'Complément d\'adresse','type'=>'text'),
  22. 'city' => array('label'=>'Ville','type'=>'text'),
  23. 'zip' => array('label'=>'Code postal','type'=>'text'),
  24. 'country' => array('label'=>'Pays','type'=>'text'),
  25. 'state' => array('label'=>'Etat','type'=>'text')
  26. );
  27. public $indexes = array('uid','scope');
  28. public function mapUrl(){
  29. $encoded = urlencode($this->street).', '.urlencode($this->zip).' '.urlencode($this->city);
  30. return 'https://www.google.com/maps/place/'.$encoded;
  31. }
  32. //Surchage de toArray pour prendre en compte le fullName régulierement utilisé en toArray
  33. public function toArray($decoded=false) {
  34. $fields = parent::toArray($decoded);
  35. $fields['fullName'] = $this->fullName();
  36. if($decoded){
  37. $fields['fullName'] = html_entity_decode($fields['fullName']);
  38. }
  39. return $fields;
  40. }
  41. /**
  42. * Permet de récupérer un tableau de
  43. * données liées à l'adresse via l'API Here
  44. *
  45. * Détail des paramètres possibles : https://developer.here.com/documentation/geocoder/dev_guide/topics/resource-geocode.html
  46. * Types de réponses : https://developer.here.com/documentation/geocoder/dev_guide/topics/resource-type-response-geocode.html
  47. * Voir utilisation live ici : https://developer.here.com/documentation/examples/rest/geocoder/latitude-longitude-no-attributes
  48. *
  49. * @param $responseAttributes : Définit les attributs de réponse à récupérer, séparés par virgule (ps,mq,mt,mc,pr par défaut)
  50. * Listes des possibilités:
  51. * - ps = performedSearch
  52. * - mq = matchQuality
  53. * - mt = matchType
  54. * - mc = matchCode
  55. * - pr = parsedRequest
  56. * - none = aucun attribut
  57. *
  58. * @param $locationAttributes : Définit les attributs de réponse à récupérer, séparés par virgule
  59. * Listes des possibilités:
  60. * - ar = address
  61. * - mr = mapReference
  62. * - mv = mapView
  63. * - dt = addresseDetails
  64. * - sd = streetDetails
  65. * - ad = additionalData
  66. * - ai = adminIds
  67. * - li = linkInfo
  68. * - in = adminInfo
  69. * - none = aucun attribut
  70. */
  71. public function infos($responseAttributes='ps,mq,mt,mc,pr', $locationAttributes='ar,mr,mv,dt,sd,ad,ai,li,in', $maxResults=null){
  72. global $myUser, $conf;
  73. if(!$myUser->connected()) throw new Exception("Vous devez être connecté",401);
  74. $results = array();
  75. $appUrl = $conf->get('maps_api_geocode_url');
  76. $appId = $conf->get('maps_api_id');
  77. $appKey = $conf->get('maps_api_key');
  78. //On ne throw pas d'exception pour ne pas bloquer l'utilisation
  79. if(empty($appUrl) || empty($appId) || empty($appKey)) {
  80. Log::put('Erreur de paramétrage des configurations de l\'API. URL Geocode: '.$appUrl.', API ID: '.$appId.', Taille clé privée API: '.strlen($appKey) ,'Location API');
  81. return $results;
  82. }
  83. //Attributs response
  84. $responseAttr = explode(',', $responseAttributes);
  85. foreach($responseAttr as $i => $attr) {
  86. if(!in_array($attr, array('ps','mq','mt','mc','pr','none'))) {
  87. unset($responseAttr[$i]);
  88. continue;
  89. }
  90. }
  91. $responseAttributes = implode(',', $responseAttr);
  92. if(empty($responseAttributes)) $responseAttributes = 'ps,mq,mt,mc,pr';
  93. //Attributs location
  94. $locationAttr = explode(',', $responseAttributes);
  95. foreach($locationAttr as $i => $attr) {
  96. if(!in_array($attr, array('ar','mr','mv','dt','sd','ad','ai','li','in','none'))) {
  97. unset($locationAttr[$i]);
  98. continue;
  99. }
  100. }
  101. $locationAttributes = implode(',', $locationAttr);
  102. if(empty($locationAttributes)) $locationAttributes = 'ar,mr,mv,dt,sd,ad,ai,li,in';
  103. $params = array(
  104. 'searchtext' => $this->street.(!empty($this->complement)?$this->complement:'').', '.$this->zip.' '.$this->city,
  105. 'app_id' => $appId,
  106. 'app_code' => $appKey,
  107. 'responseattributes' => $responseAttributes,
  108. 'locationattributes' => $locationAttributes,
  109. );
  110. if(isset($maxResults) && is_numeric($maxResults)) $params['maxresults'] = $maxResults;
  111. $curlOpt = array(
  112. CURLOPT_URL => sprintf("%s?%s", $appUrl, http_build_query($params)),
  113. CURLOPT_HTTPHEADER => array(
  114. 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0',
  115. 'Content-Type: application/json',
  116. ),
  117. CURLOPT_RETURNTRANSFER => 1,
  118. CURLOPT_HTTPAUTH => CURLAUTH_ANY,
  119. CURLOPT_SSL_VERIFYPEER => false,
  120. CURLOPT_SSL_VERIFYHOST => false,
  121. );
  122. $ch = curl_init();
  123. curl_setopt_array($ch, $curlOpt);
  124. $response = curl_exec($ch);
  125. if($response === false){
  126. Log::put("Erreur de récupération cURL : ".curl_error($ch),'Location API');
  127. return $results;
  128. }
  129. $results = json_decode($response);
  130. //Check si le retour n'est pas une erreur
  131. if(!isset($results->Response)){
  132. Log::put(mb_strtoupper('['.$results->type.']').' '.$results->subtype.': '.$results->Details,'Location API');
  133. return array();
  134. }
  135. //Contrôle sur la structure de l'objet de retour
  136. if(!isset($results->Response->View)){
  137. Log::put("La structure de retour de l'API Here a été modifiée. Se référer à la documentation pour modifier la structure en conséquence",'Location API');
  138. return array();
  139. }
  140. if(empty($results->Response->View)){
  141. Log::put("Aucun résultat trouvé pour la récupération des infos de l'adresse : ".$this->toText(),'Location API');
  142. $results = $results->Response->View;
  143. return $results;
  144. }
  145. if(!isset($results->Response->View[0]->Result)){
  146. Log::put("La structure de retour de l'API Here a été modifiée. Se référer à la documentation pour modifier la structure en conséquence",'Location API');
  147. return array();
  148. }
  149. Log::put("Récupération des informations de l'adresse : ".$this->toText(),'Location API');
  150. return $results->Response->View[0]->Result;
  151. // $infos = curl_getinfo($ch);
  152. // curl_close($ch);
  153. }
  154. //Permet de récupérer les coordonnées géographiques
  155. //d'une adresse en fonction de son libellé
  156. public function locationCoordinates(){
  157. //Récupération des informations en scopant sur Lat. + Long.
  158. $infos = $this->infos('none', 'none', 1);
  159. $coordinates = array(
  160. 'latitude' => 0,
  161. 'longitude' => 0,
  162. );
  163. if(empty($infos) || !isset($infos[0]->Location->DisplayPosition)) return $coordinates;
  164. $coordinates['latitude'] = $infos[0]->Location->DisplayPosition->Latitude;
  165. $coordinates['longitude'] = $infos[0]->Location->DisplayPosition->Longitude;
  166. return $coordinates;
  167. }
  168. //Retourne l'adresse sur une seule ligne
  169. //au format : street, complement, zip city country
  170. public function fullName(){
  171. $fullname = '';
  172. if(!empty($this->street)) $fullname .= $this->street;
  173. if(!empty($this->complement)) $fullname .= ', '.$this->complement;
  174. if($fullname!='') $fullname .= ', ';
  175. if(!empty($this->zip)) $fullname .= $this->zip;
  176. if(!empty($this->city)) $fullname .= ' '.$this->city;
  177. if(!empty($this->country)) $fullname .= ', '.$this->country;
  178. return $fullname;
  179. }
  180. //remplis un composant location à partir des infos de la classe courante
  181. public function toDataAttributes($plainText=true){
  182. $array = array();
  183. $plain = '';
  184. foreach (array('street','complement','city','zip','country') as $key) {
  185. $array[$key] = $this->$key;
  186. $plain .= ' data-'.$key.' = "'.(empty($this->$key) ? '' : $this->$key).'"';
  187. }
  188. return !$plainText ? $array : $plain;
  189. }
  190. public function getCoordinates(){
  191. return self::coordinates($this->fullName());
  192. }
  193. //Récupere des latitudes/ longitudes à partir d'une adresse
  194. public static function coordinates($address){
  195. $response = file_get_contents('https://api-adresse.data.gouv.fr/search/?q='.urlencode($address));
  196. $response = json_decode($response,true);
  197. if(!$response) $response = array();
  198. if(isset($response['features']) && isset($response['features'][0]) && isset($response['features'][0]['geometry']) && isset($response['features'][0]['geometry']['coordinates']))
  199. return array('latitude'=>$response['features'][0]['geometry']['coordinates'][0],'longitude'=>$response['features'][0]['geometry']['coordinates'][1]);
  200. }
  201. public static function types($key=null){
  202. $types = array(
  203. self::MAIN => array(
  204. 'label' => "Adresse générale",
  205. 'icon' => "fas fa-map-marker-alt",
  206. 'color' => "#4dabf7",
  207. ),
  208. self::INVOICE => array(
  209. 'label' => "Adresse de facturation",
  210. 'icon' => "fas fa-receipt",
  211. 'color' => "#4dabf7",
  212. ),
  213. self::SHIPPING => array(
  214. 'label' => "Adresse de livraison",
  215. 'icon' => "fas fa-shipping-fast",
  216. 'color' => "#4dabf7",
  217. )
  218. );
  219. Plugin::callHook('address_types', array(&$types));
  220. if(!isset($key)) return $types;
  221. return isset($types[$key]) ? $types[$key] : array('label'=>'non définit','icon'=>'','color'=>'');
  222. }
  223. }
  224. ?>