PageRenderTime 116ms CodeModel.GetById 45ms RepoModel.GetById 7ms app.codeStats 1ms

/class.xmodmap.inc

https://github.com/jcplat/console-seolan
PHP | 1229 lines | 1059 code | 30 blank | 140 comment | 175 complexity | 480be8dd2bb96280afb49a91f1380da8 MD5 | raw file
Possible License(s): LGPL-2.0, LGPL-2.1, GPL-3.0, Apache-2.0, BSD-3-Clause
  1. <?php
  2. /**
  3. module geocodage et 'cartographie'
  4. l'EF contient les paramètres de gestion des EF utilisant des points geographiques
  5. fonction d'aide a la saisie via la carte
  6. fonctions de geocodage
  7. fonctions de restitution google map
  8. */
  9. define('EARTHRAY',6378.137);
  10. class XModMap extends XModTable{
  11. static $defaultSRS = 'MAPSRS:EPSG4326';
  12. var $googleGeoCodeUrl = 'http://maps.google.fr/maps/geo?';
  13. var $googleGeoCodeEncoding = 'UTF-8 ? a voir ';
  14. /* la pertinence d'une adresse */
  15. var $googleGeoAccuracy = array('0'=>array(0, 'Unknown location.'),
  16. '1'=>array(1, 'Country level accuracy'),
  17. '2'=>array(2, 'Region (state, province, prefecture, etc.) level accuracy'),
  18. '3'=>array(3, 'Sub-region (county, municipality, etc.) level accuracy.e'),
  19. '4'=>array(4, 'Town (city, village) level accuracy'),
  20. '5'=>array(5, 'Post code (zip code) level accuracy'),
  21. '6'=>array(6, 'Street level accuracy'),
  22. '7'=>array(7, 'Intersection level accuracy'),
  23. '8'=>array(8, 'Address level accuracy'),
  24. '9'=>array(9, 'Permise level accuracy')
  25. );
  26. /* les status http geocodage google */
  27. var $googleGeoStatus = array('200'=>array(200, 'G_GEO_SUCCESS (200)', 'No errors occurred; the address was successfully parsed and its geocode has been returned. (Since 2.55)'),
  28. '400'=>array(400, 'G_GEO_BAD_REQUEST (400)', 'A directions request could not be successfully parsed. (Since 2.81)'),
  29. '500'=>array(500, 'G_GEO_SERVER_ERROR (500)', 'A geocoding or directions request could not be successfully processed, yet the exact reason for the failure is not known. (Since 2.55)'),
  30. '601'=>array(601, 'G_GEO_MISSING_QUERY (601)', 'The HTTP q parameter was either missing or had no value. For geocoding requests, this means that an empty address was specified as input. For directions requests, this means that no query was specified in the input. (Since 2.81)'),
  31. '602'=>array(602, 'GEO_UNKNOWN_ADDRESS (602)', 'No corresponding geographic location could be found for the specified address. This may be due to the fact that the address is relatively new, or it may be incorrect. (Since 2.55)'),
  32. '603'=>array(603, 'G_GEO_UNAVAILABLE_ADDRESS (603)', 'The geocode for the given address or the route for the given directions query cannot be returned due to legal or contractual reasons. (Since 2.55)'),
  33. '604'=>array(604, 'G_GEO_UNKNOWN_DIRECTIONS (604)', 'The GDirections object could not compute directions between the points mentioned in the query. This is usually because there is no route available between the two points, or because we do not have data for routing in that region. (Since 2.81)'),
  34. '610'=>array(610, 'G_GEO_BAD_KEY (610)', 'The given key is either invalid or does not match the domain for which it was given. (Since 2.55)'),
  35. '620'=>array(620, 'G_GEO_TOO_MANY_QUERIES (620)', '')
  36. );
  37. function __contruct($ar=NULL){
  38. parent::__construct($ar);
  39. XLabels::loadLabels('xmodmap');
  40. }
  41. /// securite des fonctions accessibles par le web
  42. function secGroups($function, $group=NULL) {
  43. $g=array();
  44. $g['preConvertCoords']=array('ro', 'rw', 'rwv', 'admin');
  45. $g['procConvertCoords']=array('ro', 'rw', 'rwv', 'admin');
  46. $g['convertCoords']=array('none', 'ro', 'rw', 'rwv', 'admin');
  47. $g['geoSearch']=array('ro', 'rw','rwv','admin');
  48. $g['simpleLayerKML']=array('none', 'list', 'ro', 'rw', 'rwv', 'admin');
  49. $g['rawLayer']=array('none', 'list', 'ro', 'rw', 'rwv', 'admin');
  50. $g['geoCodeAuto']=array('admin');
  51. $g['procStat']=array('ro', 'rw', 'rwv', 'admin');
  52. $g['simpleMap'] = array('none', 'list', 'ro', 'rw', 'rwv', 'admin');
  53. $g['simpleMap2'] = array('none', 'list', 'ro', 'rw', 'rwv', 'admin');
  54. $g['xPoiList'] = array('ro', 'rw', 'rwv', 'admin');
  55. $g['xDisplayMarker'] = array('none', 'ro', 'rw', 'rwv', 'admin');
  56. if(isset($g[$function])) {
  57. if(!empty($group)) return in_array($group, $g[$function]);
  58. return $g[$function];
  59. }
  60. return parent::secGroups($function,$group);
  61. }
  62. // paramètres pour une carte simple
  63. //
  64. function simpleMap($ar){
  65. $p = new XParam($ar, array());
  66. $tpl = $p->get('tplentry');
  67. $nocache = $p->get('nocache');
  68. if (isset($nocache)){
  69. $nocache = '&nocache='.$nocache;
  70. }
  71. $layeroid = $p->get('layeroid'); // peut être un tableau ?
  72. if (!is_array($layeroid)){
  73. $layeroid = array($layeroid);
  74. }
  75. $jslayeroid = '[';
  76. $sep = '';
  77. foreach($layeroid as $il=>$oidl){
  78. $jslayeroid .= $sep.'\''.$oidl.'\'';
  79. if ($sep == '')
  80. $sep = ',';
  81. }
  82. $jslayeroid .= ']';
  83. $modmap = $this->xset->rdisplay($layeroid[0]);
  84. $jsstyles = '';
  85. if ($loadstyles){
  86. $styles = array();
  87. if (isset($modmap['oricon1']->raw)){
  88. $styles[$modmap['oid']] = array('icon'=>array('size'=>$modmap['oricon1']->getImageSize('fullwidth').'X'.$modmap['oricon1']->getImageSize('fullheight'),
  89. 'url'=>$fullself.$modmap['oricon1']->url.'?foo=.png')
  90. );
  91. if ($modmap['orshad1']->html){
  92. $styles[$modmap['oid']]['shadow'] = array('size'=>$modmap['orshad1']->getImageSize('fullwidth').'X'.$modmap['orshad1']->getImageSize('fullheight'),
  93. 'url'=>$fullself.$modmap['orshad1']->url.'?foo=.png');
  94. }
  95. }
  96. for($is=1; $is < count($layeroid); $is++){
  97. $modmapi = $this->xset->rdisplay($layeroid[$is]);
  98. if (isset($modmapi['oricon1']->raw)){
  99. $styles[$modmapi['oid']] = array('icon'=>array('size'=>$modmapi['oricon1']->getImageSize('fullwidth').'X'.$modmapi['oricon1']->getImageSize('fullheight'),
  100. 'url'=>$fullself.$modmapi['oricon1']->url.'?foo=.png')
  101. );
  102. if ($modmapi['orshad1']->html){
  103. $styles[$modmapi['oid']]['shadow'] = array('size'=>$modmapi['orshad1']->getImageSize('fullwidth').'X'.$modmapi['orshad1']->getImageSize('fullheight'),
  104. 'url'=>$fullself.$modmapi['orshad']->url.'?foo=.png');
  105. }
  106. }
  107. }
  108. $jsstyles .="styles:["; $sep = '';
  109. foreach($styles as $sid=>$style){
  110. $jsstyles .= "\n{$sep}{id:'{$sid}', icon:{url:'{$style['icon']['url']}', size:'{$style['icon']['size']}'}";
  111. $sep = ',';
  112. if (isset($style['shadow'])){
  113. $jsstyles .= ", shadow:{url:'{$style['shadow']['url']}', size:'{$style['shadow']['size']}'}";
  114. }
  115. $jsstyles .= "}";
  116. }
  117. $jsstyles .="],";
  118. }
  119. list($initialLat, $initialLng) = explode(';', $modmap['oelatlng']->raw);
  120. $initialZoom = $modmap['oezoom']->raw;
  121. if (empty($modmap['orcicon']->url)){
  122. $clusterIco = TZR_SHARE_URL.'xmodmap/cluster.png';
  123. $clusterIcoShadow = TZR_SHARE_URL.'xmodmap/cluster_shadow.png';
  124. $clusterIcoSize = 'width : 30, height : 51';
  125. } else {
  126. $clusterIco = $modmap['orcicon']->url.'?foo=.png';
  127. $clusterIcoSize = "width : {$modmap['orcicon']->getImageSize('fullwidth')}, height : {$modmap['orcicon']->getImageSize('fullheight')}";
  128. if (!empty($modmap['orshad']->url)){
  129. $clusterIcoShadow = $modmap['orshad']->url;
  130. }else{
  131. $clusterIcoShadow = '';
  132. }
  133. }
  134. $glang = $this->getGLang();
  135. $fullself = $GLOBALS['TZR_SESSION_MANAGER']::complete_self(true, true);
  136. $kmlurl = "{$fullself}&moid={$this->_moid}&function=simpleLayerKML{$nocache}&kml=0&_silent=1";
  137. $js = '<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;hl='.$glang.'&amp;oe=utf-8&amp;key='.$this->key.'" language="javascript" type="text/javascript"></script>';
  138. $js .= '<script src="/tzr/templates/xmodmap/Clusterer2.js" type="text/javascript"></script>';
  139. $js .= '<script src="/tzr/templates/xmodmap/mapmanager.js" type="text/javascript"></script>';
  140. $js .= "<script type=\"text/javascript\">
  141. mapmngt.setOptions({defaultlayeroid:'{$layeroid[0]}',layeroids:{$jslayeroid},
  142. initialLat:{$initialLat},
  143. initialLng:{$initialLng},
  144. initialZoom:{$initialZoom},
  145. gridSize:20,
  146. kmlurl:'{$kmlurl}',
  147. clusterIco:{url:'{$clusterIco}', {$clusterIcoSize}},
  148. clusterIcoShadow:{url:'{$clusterIcoShadow}',width:56, height:51}
  149. });
  150. </script>";
  151. $res = array('js'=>$js,
  152. 'key'=>$this->key,
  153. 'kmlurl'=>$kmlurl,
  154. 'onload'=>'pageLoad()',
  155. 'onunload'=>'GUnload()');
  156. return XShell::toScreen1($tpl, $res);
  157. }
  158. // paramètres pour une carte simple
  159. //
  160. function simpleMap2($ar){
  161. $p = new XParam($ar, array('loadstyles'=>0));
  162. $tpl = $p->get('tplentry');
  163. $nocache = $p->get('nocache');
  164. $loadstyles = $p->get('loadstyles');
  165. if (isset($nocache)){
  166. $nocache = '&nocache='.$nocache;
  167. }
  168. $layeroid = $p->get('layeroid'); // peut être un tableau ?
  169. if (!is_array($layeroid)){
  170. $layeroid = array($layeroid);
  171. }
  172. $jslayeroid = '[';
  173. $sep = '';
  174. foreach($layeroid as $il=>$oidl){
  175. $jslayeroid .= $sep.'\''.$oidl.'\'';
  176. if ($sep == '')
  177. $sep = ',';
  178. }
  179. $jslayeroid .= ']';
  180. $modmap = $this->xset->rdisplay($layeroid[0]);
  181. // on lit les informations de styles
  182. if ($loadstyles){
  183. $styles = array();
  184. if (isset($modmap['oricon1']->raw)){
  185. $styles[$modmap['oid']] = array('icon'=>array('size'=>$modmap['oricon1']->getImageSize('fullwidth').'X'.$modmap['oricon1']->getImageSize('fullheight'),
  186. 'url'=>$fullself.$modmap['oricon1']->url.'?foo=.png')
  187. );
  188. if ($modmap['orshad1']->html){
  189. $styles[$modmap['oid']]['shadow'] = array('size'=>$modmap['orshad1']->getImageSize('fullwidth').'X'.$modmap['orshad1']->getImageSize('fullheight'),
  190. 'url'=>$fullself.$modmap['orshad1']->url.'?foo=.png');
  191. }
  192. }
  193. for($is=1; $is < count($layeroid); $is++){
  194. $modmapi = $this->xset->rdisplay($layeroid[$is]);
  195. if (isset($modmapi['oricon1']->raw)){
  196. $styles[$modmapi['oid']] = array('icon'=>array('size'=>$modmapi['oricon1']->getImageSize('fullwidth').'X'.$modmapi['oricon1']->getImageSize('fullheight'),
  197. 'url'=>$fullself.$modmapi['oricon1']->url.'?foo=.png')
  198. );
  199. if ($modmapi['orshad1']->html){
  200. $styles[$modmapi['oid']]['shadow'] = array('size'=>$modmapi['orshad1']->getImageSize('fullwidth').'X'.$modmapi['orshad1']->getImageSize('fullheight'),
  201. 'url'=>$fullself.$modmapi['orshad']->url.'?foo=.png');
  202. }
  203. }
  204. }
  205. $jsstyles .="styles:["; $sep = '';
  206. foreach($styles as $sid=>$style){
  207. $jsstyles .= "\n{$sep}{id:'{$sid}', icon:{url:'{$style['icon']['url']}', size:'{$style['icon']['size']}'}";
  208. $sep = ',';
  209. if (isset($style['shadow'])){
  210. $jsstyles .= ", shadow:{url:'{$style['shadow']['url']}', size:'{$style['shadow']['size']}'}";
  211. }
  212. $jsstyles .= "}";
  213. }
  214. $jsstyles .="],";
  215. }
  216. list($initialLat, $initialLng) = explode(';', $modmap['oelatlng']->raw);
  217. $initialZoom = $modmap['oezoom']->raw;
  218. if (empty($modmap['orcicon']->url)){
  219. $clusterIco = TZR_SHARE_URL.'xmodmap/cluster.png';
  220. $clusterIcoShadow = TZR_SHARE_URL.'xmodmap/cluster_shadow.png';
  221. $clusterIcoSize = 'width : 30, height : 51';
  222. } else {
  223. $clusterIco = $modmap['orcicon']->url.'?foo=.png';
  224. $clusterIcoSize = "width : {$modmap['orcicon']->getImageSize('fullwidth')}, height : {$modmap['orcicon']->getImageSize('fullheight')}";
  225. if (!empty($modmap['orshad']->url)){
  226. $clusterIcoShadow = $modmap['orshad']->url;
  227. }else{
  228. $clusterIcoShadow = '';//TZR_SHARE_URL.'xmodmap/cluster_shadow.png';
  229. }
  230. }
  231. $glang = $this->getGLang();
  232. $fullself = $GLOBALS['TZR_SESSION_MANAGER']::complete_self(true, true);
  233. $kmlurl = "{$fullself}&moid={$this->_moid}&function=simpleLayerKML{$nocache}&kml=1";
  234. $layerurl = "{$fullself}&moid={$this->_moid}&function=rawLayer&_silent=1&placestemplate=xmodmap/markerlist.xml{$nocache}";
  235. $displayurl = "{$fullself}&moid={$this->_moid}&function=xDisplayMarker{$nocache}";
  236. $js = '<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;hl='.$glang.'&amp;oe=utf-8&amp;key='.$this->key.'" language="javascript" type="text/javascript"></script>';
  237. $js .= '<script src="/tzr/templates/xmodmap/Clusterer2.js" type="text/javascript"></script>';
  238. $js .= '<script src="/tzr/templates/xmodmap/mapmanager2.js" type="text/javascript"></script>';
  239. $js .= "<script type=\"text/javascript\">
  240. mapmngt.setOptions(
  241. {defaultlayeroid:'{$layeroid[0]}',layeroids:{$jslayeroid},
  242. {$jsstyles}
  243. initialLat:{$initialLat},
  244. initialLng:{$initialLng},
  245. initialZoom:{$initialZoom},
  246. gridSize:20,
  247. infoWindowWidth:200,
  248. infoWindowHeight:200,
  249. minMarkersPerCluster:5,
  250. maxVisibleMarkers:1,
  251. defaultMaxLinesPerInfoBox:5,
  252. maxLinesPerInfoBox:5,
  253. displayurl:'{$displayurl}',
  254. kmlurl:'{$kmlurl}',
  255. layerurl:'{$layerurl}',
  256. clusterAction:'zoom', // zoom | pop
  257. clusterIco:{url:'{$clusterIco}', {$clusterIcoSize}},
  258. clusterIcoShadow:{url:'{$clusterIcoShadow}',width:56, height:51}
  259. });
  260. </script>";
  261. $res = array('js'=>$js,
  262. 'key'=>$this->key,
  263. 'kmlurl'=>$kmlurl,
  264. 'onload'=>'pageLoad()',
  265. 'onunload'=>'GUnload()');
  266. return XShell::toScreen1($tpl, $res);
  267. }
  268. // lecture d'un point d'une carte
  269. //
  270. function xDisplayMarker($ar){
  271. $p = new XParam($ar, array('tplentry'=>'br', 'markertemplate'=>'xmodmap/displaymarker.xml'));;
  272. $layeroid = $p->get('layeroid');
  273. $oid = $p->get('oid');
  274. $template = $p->get('markertemplate');
  275. $tpl = $p->get('tplentry');
  276. $modmap = $this->xset->rdisplay($layeroid);
  277. if (!is_array($modmap)){
  278. XLogs::critical(get_class($this), get_class($this)."::simpleLayerKML layer not found {$layeroid}");
  279. die('Could not find layeroid '.$layeroid);
  280. }
  281. $mod = XModule::objectFactory($modmap['ormoid']->raw);
  282. if (!empty($modmap['orfilter']->raw)){
  283. $select = $mod->xset->select_query().' and '.$modmap['orfilter']->raw;
  284. } else {
  285. $select = $mod->xset->select_query();
  286. }
  287. if (!is_array($oid)){
  288. $select .= ' and '.$mod->table.'.KOID = \''.$oid.'\'';
  289. } else {
  290. foreach($oid as $foo=>&$aoid){
  291. $aoid = '\''.$aoid.'\'';
  292. }
  293. $select .= ' and '.$mod->table.'.KOID in (' . implode(",", $oid) . ')';
  294. }
  295. $br = $mod->browse(array('_options'=>array(),
  296. 'tplentry'=>TZR_RETURN_DATA,
  297. 'selectedfields'=>'all',
  298. 'first'=>0,
  299. 'select'=>$select,
  300. 'pagesize'=>9999));
  301. $places = array();
  302. $fname = $modmap['ofname']->raw;
  303. foreach($br['lines_oid'] as $i=>$lineoid){
  304. $coords = $br['lines_o'.$fname][$i]->raw;
  305. list($lat, $lng, $type, $acc, $upd) = explode(';', $coords);
  306. $aplace = $this->getPlace($i, $mod, $br, $modmap);
  307. if (!empty($lat) && !empty($lng)){
  308. $aplace['valid'] = true;
  309. } else {
  310. $aplace['valid'] = false;
  311. }
  312. $places[] = array('oid'=>$lineoid,
  313. 'latlng'=>$lng.','.$lat,
  314. 'name'=>$aplace['name'],
  315. 'valid'=>$aplace['valid'],
  316. 'description'=>$aplace['descr']);
  317. unset($aplace);
  318. }
  319. $ret = array('places'=>$places,
  320. 'browse'=>$br,
  321. 'modmap'=>$modmap);
  322. $xt = new XTemplate('file://'.TZR_SHARE_DIR.$template);
  323. if (file_exists(TZR_SHARE_DIR.$template)){
  324. $xt = new XTemplate('file://'.TZR_SHARE_DIR.$template);
  325. } else if (file_exists($GLOBALS['TEMPLATES_DIR'].$template)){
  326. $xt = new XTemplate('file://'.$GLOBALS['TEMPLATES_DIR'].$template);
  327. } else {
  328. echo('-');
  329. exit(0);
  330. }
  331. $labels=&$GLOBALS['XSHELL']->labels->get_labels(array('selectors'=>array('global'),'local'=>true));
  332. $xt->set_glob(array('labels'=>&$labels));
  333. $r3=array();
  334. // avoir vide ... die($tpl);
  335. $tpldata['br']=$ret;
  336. $content=$xt->parse($tpldata,$r3,NULL);
  337. header('Content-type: text/xml');
  338. header('Content-disposition: inline');
  339. echo($content);
  340. exit(0);
  341. }
  342. // initialisation des propriétés
  343. // -> ! table est _MODMAP
  344. //
  345. public function initOptions() {
  346. parent::initOptions();
  347. $alabel = XLabels::getSysLabel('xmodmap.modulename');
  348. $this->_options->setOpt(XLabels::getSysLabel('xmodmap','key'), 'key', 'text', NULL,NULL,$alabel);
  349. $this->_options->setOpt(XLabels::getSysLabel('xmodmap','geocodeurl'), 'geocodeurl', 'text', NULL,NULL,$alabel);
  350. }
  351. protected function _actionlist(&$my) {
  352. parent::_actionlist($my);
  353. $myclass=get_class($this);
  354. $moid=$this->_moid;
  355. $myoid=@$_REQUEST['oid'];
  356. $user = &XUser::get_user();
  357. if (XShell::_function() == 'edit' || XShell::_function() == 'display'){
  358. $o1=new XModuleAction($this,'procStat', XLabels::getSysLabel('xmodmap','statistics'),
  359. 'class='.$myclass.'&amp;moid='.$moid.'&_function=procStat&template=xmodmap/statistics.html&tplentry=br&oid='.$myoid);
  360. $o1->homepageable=$o1->quicklinkable=$o1->menuable=true;
  361. $o1->group='edit';
  362. $my['procstats']=$o1;
  363. }
  364. if (XShell::_function() == 'procStat'){
  365. $br=&XShell::from_screen('br');
  366. $o1=new XModuleAction($this,'display',XLabels::getSysLabel('general','display','text'),
  367. 'class='.$myclass.'&amp;moid='.$moid.
  368. '&_function=display&template=xmodtable/view.html&tplentry=br&oid='.$myoid);
  369. $o1->homepageable=$o1->quicklinkable=$o1->menuable=true;
  370. $o1->setToolbar('general','display');
  371. $my['display'] = $o1;
  372. }
  373. if (defined('TZR_GDAL_PATH') && file_exists(TZR_GDAL_PATH.'gdaltransform')){
  374. $o1=new XModuleAction($this,'convertCoords', 'Convertions',
  375. 'class='.$myclass.'&amp;moid='.$moid.'&_function=preConvertCoords&template=xmodmap/convert.html&tplentry=br');
  376. $o1->homepageable=$o1->quicklinkable=$o1->menuable=true;
  377. $o1->group='more';
  378. $my['convert']=$o1;
  379. }
  380. }
  381. // liste de points selon certains critères
  382. //
  383. function xPoiList($ar){
  384. $p = new XParam($ar, array());
  385. XLogs::notice(get_class($this), get_class($this)."::xPoiList");
  386. $layeroid = $p->get('layeroid');
  387. $query = $p->get('query');
  388. $value = $p->get('value');
  389. $modmap = $this->xset->rdisplay($layeroid);
  390. $mod = XModule::objectFactory($modmap['ormoid']->raw);
  391. switch($query){
  392. case 'manual':
  393. $select = $mod->xset->select_query(array('cond'=>array($modmap['ofname']->raw=>array('like', '%;%;M;%;%'))));
  394. $select2 = str_replace($mod->xset->table.'.*', $mod->xset->table.'.KOID ', $select);
  395. break;
  396. case 'auto':
  397. $select = $mod->xset->select_query(array('cond'=>array($modmap['ofname']->raw=>array('like', '%;%;A;%;%'))));
  398. $select2 = str_replace($mod->xset->table.'.*', $mod->xset->table.'.KOID ', $select);
  399. break;
  400. case 'accuracy':
  401. $select = $mod->xset->select_query(array('cond'=>array($modmap['ofname']->raw=>array('like', '%;%;A;'.$value.';%'))));
  402. $select2 = str_replace($mod->xset->table.'.*', $mod->xset->table.'.KOID ', $select);
  403. break;
  404. break;
  405. }
  406. if (!empty($modmap['orfilter']->raw)){
  407. $select2 .= ' and '.$modmap['orfilter']->raw;
  408. }
  409. XLogs::notice(get_class($this), get_class($this)."::xPoiList $select2");
  410. $rs = selectQuery($select2);
  411. $ret = array();
  412. while($ors = $rs->fetch()){
  413. $ret[] = $ors['KOID'];
  414. }
  415. die(json_encode($ret));
  416. }
  417. // statistiques sur le geocodage
  418. //
  419. function procStat($ar){
  420. $p = new XParam($ar, array());
  421. $tpl = $p->get('tplentry');
  422. $layeroid = $p->get('oid');
  423. $stats = array('total'=>0, 'empty'=>0, 'types'=>array('A'=>0, 'M'=>0), 'accuracy'=>array());
  424. $modmap = $this->xset->rdisplay($layeroid);
  425. // total
  426. if (empty($modmap['ormoid']->raw)){
  427. $xset = XDataSource::objectFactoryHelper8('BCLASS=XDSTable&SPECS='.$modmap['oftable']->raw);
  428. $select = $xset->select_query();
  429. } else {
  430. $mod = XModule::objectFactory($modmap['ormoid']->raw);
  431. $xset = $mod->xset;
  432. if (!empty($modmap['orfilter']->raw)){
  433. $select = $mod->xset->select_query().' and '.$modmap['orfilter']->raw;
  434. } else {
  435. $select = $mod->xset->select_query();
  436. }
  437. }
  438. $select2 = str_replace($xset->getTable().'.*', 'ifnull(count(*), 0) as count', $select);
  439. $rs = selectQuery($select2);
  440. $ors = $rs->fetch();
  441. $stats['total'] = $ors['count'];
  442. $accuraciesLevels = XLabels::getSysLabel('xmodmap', 'accuracieslevels');
  443. foreach($accuraciesLevels as $ac=>$al){
  444. $stats['accuracy'][$ac] = array('label'=>$al, 'count'=>0);
  445. }
  446. // par type, accuracy, un peu brutal ...
  447. $fname = $modmap['ofname']->raw;
  448. $select2 = str_replace($xset->getTable().'.*', $xset->getTable().'.'.$fname.' as rawcoords', $select);
  449. $rs = selectQuery($select2);
  450. while($rs && $ors=$rs->fetch()){
  451. if (empty($ors['rawcoords'])){
  452. $stats['empty']+=1;
  453. } else {
  454. list($lat, $lng, $type, $accuracy, $upd) = XGeodesicCoordinatesDef::explode($ors['rawcoords']);
  455. if (empty($lat) || empty($lng)){
  456. $stats['empty']+=1;
  457. }
  458. if ($type == 'M'){
  459. $stats['types']['M']+=1;
  460. } else {
  461. if (empty($accuracy)){
  462. $accuracy = 'N/A';
  463. }
  464. $stats['types']['A']+=1;
  465. if (!isset($stats['accuracy'][$accuracy])){
  466. $stats['accuracy'][$accuracy] = array('label'=>$this->accuracyLabel($accuracy), 'count'=>0);
  467. }
  468. $stats['accuracy'][$accuracy]['count']+=1;
  469. }
  470. }
  471. }
  472. // fin pour le moment
  473. $res = array();
  474. $res['modmap'] = $modmap;
  475. $res['statistics'] = $stats;
  476. XShell::toScreen1($tpl, $res);
  477. }
  478. // generation d'une couche en KML
  479. // -> icone des marker de la couche
  480. // -> champ titre de la couche
  481. // -> champs de description
  482. //
  483. function simpleLayerKML($ar){
  484. $p = new XParam($ar, array('tplentry'=>'br', 'kml'=>0));
  485. $tpl = $p->get('tplentry');
  486. $layeroid = $p->get('layeroid');
  487. $template = $p->get('template');
  488. $kml = $p->get('kml');
  489. // lecture de la description de la carte
  490. $modmap = $this->xset->rdisplay($layeroid);
  491. if (!is_array($modmap)){
  492. XLogs::critical(get_class($this), get_class($this)."::simpleLayerKML layer not found {$layeroid}");
  493. return array('Could not find layeroid '.$layeroid);
  494. }
  495. // browse sur le module associé avec la clause where specifiée
  496. //
  497. $mod = XModule::objectFactory($modmap['ormoid']->raw);
  498. if (!empty($modmap['orfilter']->raw)){
  499. $select = $mod->xset->select_query().' and '.$modmap['orfilter']->raw;
  500. } else {
  501. $select = '';
  502. }
  503. $br = $mod->browse(array('_options'=>array(),
  504. 'tplentry'=>TZR_RETURN_DATA,
  505. 'selectedfields'=>'all',
  506. 'first'=>0,
  507. 'select'=>$select,
  508. 'pagesize'=>9999));
  509. $places = array();
  510. $fname = $modmap['ofname']->raw;
  511. foreach($br['lines_oid'] as $i=>$lineoid){
  512. $coords = $br['lines_o'.$fname][$i]->raw;
  513. list($lat, $lng, $type, $acc, $upd) = explode(';', $coords);
  514. $aplace = $this->getPlace($i, $mod, $br, $modmap);
  515. if (!empty($lat) && !empty($lng)){
  516. $aplace['valid'] = true;
  517. } else {
  518. $aplace['valid'] = false;
  519. }
  520. $places[] = array('oid'=>$lineoid,
  521. 'latlng'=>$lng.','.$lat,
  522. 'name'=>$aplace['name'],
  523. 'valid'=>$aplace['valid'],
  524. 'description'=>$aplace['descr']);
  525. unset($aplace);
  526. }
  527. $ret = array('places'=>$places,
  528. 'browse'=>$br,
  529. 'modmap'=>$modmap);
  530. if (!empty($kml)){
  531. $xt = new XTemplate('file://'.TZR_SHARE_DIR.'xmodmap/simplekml.xml');
  532. $r3=array();
  533. $tpldata['br']=$ret;
  534. $content=$xt->parse($tpldata,$r3,NULL);
  535. $filename = cleanFileName($modmap['name'].'.kml');
  536. header('Content-Name: '.$filename);
  537. header('Content-type: application/vnd.google-earth.kml+xml');
  538. header('Content-disposition: attachment; filename='.$filename);
  539. echo($content);
  540. exit(0);
  541. } else if ($tpl == TZR_RETURN_DATA){
  542. return $ret;
  543. } else if (empty($template)){
  544. // on genere le kml avec xmodmap/simplelayerkml.xml
  545. $xt = new XTemplate('file://'.TZR_SHARE_DIR.'xmodmap/simplelayerkml.xml');
  546. $r3=array();
  547. $tpldata['br']=$ret;
  548. $content=$xt->parse($tpldata,$r3,NULL);
  549. header('Content-type: text/xml');
  550. header('Content-disposition: inline');
  551. echo($content);
  552. exit(0);
  553. } else {
  554. XShell::toScreen1('br', $ret);
  555. }
  556. }
  557. // generation d'une couche en tzr kml
  558. // -> icone des marker de la couche
  559. // -> champ titre de la couche
  560. // -> options
  561. //
  562. function rawLayer($ar){
  563. $p = new XParam($ar, array('tplentry'=>'br'));
  564. $tpl = $p->get('tplentry');
  565. $layeroid = $p->get('layeroid');
  566. $placestemplate = $p->get('placestemplate');
  567. // lecture de la description de la carte
  568. $modmap = $this->xset->rdisplay($layeroid);
  569. if (!is_array($modmap)){
  570. XLogs::critical(get_class($this), get_class($this)."::simpleLayerKML layer not found {$layeroid}");
  571. return array(
  572. 'places'=>NULL,
  573. 'modmap'=>NULL
  574. );
  575. }
  576. // select sur le module associé avec la clause where specifiée
  577. //
  578. if (empty($modmap['ormoid']->raw)){
  579. XLogs::critical(get_class($this), '::rawLayer empty display module, layeroid : '.$layeroid);
  580. return array(
  581. 'places'=>NULL,
  582. 'modmap'=>NULL
  583. );
  584. }
  585. $mod = XModule::objectFactory($modmap['ormoid']->raw);
  586. if (!empty($modmap['orfilter']->raw)){
  587. $select = $mod->xset->select_query().' and '.$modmap['orfilter']->raw;
  588. } else {
  589. $select = $mod->xset->select_query();
  590. }
  591. $places = array();
  592. $fname = $modmap['ofname']->raw;
  593. $ftitle = $modmap['ortitlef']->raw;
  594. $lrs = selectQuery($select);
  595. $i = 0;
  596. while($lrs && $lors = $lrs->fetch()){
  597. $coords = $lors[$fname];
  598. list($lat, $lng, $type, $acc, $upd) = explode(';', $coords);
  599. if (!empty($lat) && !empty($lng)){
  600. $valid = true;
  601. } else {
  602. $valid = false;
  603. }
  604. $places[] = array('oid'=>$lors['KOID'],
  605. 'latlng'=>$lng.','.$lat,
  606. 'name'=>$lors[$ftitle],
  607. 'valid'=>$valid,
  608. 'ors'=>$lors
  609. );
  610. unset($lors);
  611. }
  612. $ret = array(
  613. 'places'=>$places,
  614. 'modmap'=>$modmap
  615. );
  616. if (!empty($placestemplate)){
  617. // on genere le kml avec xmodmap/simplelayerkml.xml
  618. $xt = new XTemplate('file://'.TZR_SHARE_DIR.$placestemplate);
  619. $r3=array();
  620. $tpldata['br']=$ret;
  621. $content=$xt->parse($tpldata,$r3,NULL);
  622. header('Content-type: text/xml');
  623. header('Content-disposition: inline');
  624. echo($content);
  625. exit(0);
  626. } else if ($tpl == TZR_RETURN_DATA){
  627. return $ret;
  628. } else {
  629. // on genere le kml avec xmodmap/simplelayerkml.xml
  630. $xt = new XTemplate('file://'.TZR_SHARE_DIR.'xmodmap/simplelayerkml.xml');
  631. $r3=array();
  632. $tpldata['br']=$ret;
  633. $content=$xt->parse($tpldata,$r3,NULL);
  634. header('Content-type: text/xml');
  635. header('Content-disposition: inline');
  636. echo($content);
  637. exit(0);
  638. }
  639. }
  640. // retourne le nom et la description d'un point
  641. // -> par defaut
  642. //
  643. protected function &getPlace($i, &$mod, &$br, &$modmap){
  644. // titre
  645. $title = $br['lines_o'.$modmap['ortitlef']->raw][$i]->html;
  646. $desc = '';
  647. $df = explode(' ', $modmap['ordescrf']->raw);
  648. $iurl = $GLOBALS['TZR_SESSION_MANAGER']::makeDomainName();
  649. foreach($df as $foo=>$fn){
  650. $o = $br['lines_o'.$fn][$i];
  651. $v = trim($o->html);
  652. if (!empty($v)){
  653. if ($o->fielddef->ftype == 'XImageDef'){
  654. $desc .= "<br><img src='{$iurl}{$o->resizer}&geometry=X100%3E'/>";
  655. }else{
  656. $desc .= $v.'<br>';
  657. }
  658. }
  659. }
  660. // description
  661. return array('name'=>$title,
  662. 'descr'=>$desc
  663. );
  664. }
  665. //enregistrement d'une valeur
  666. //-> verifier les champs
  667. //-> mettre a jour le champ
  668. //
  669. function procEdit($ar){
  670. $p = new XParam($ar, array());
  671. $ftable = $p->get('ftable');
  672. $fname = $p->get('fname');
  673. $fgcaddr = $p->get('fgcaddr');
  674. $fgccntr = $p->get('fgccntr');
  675. $fgctown = $p->get('fgctown');
  676. $fgcauto_HID = $p->get('fgcauto_HID');
  677. // si module, trouver la table
  678. // verifier que fname, fgcaddr (liste), fgccntr et fgctown existent bien pour la table
  679. // mettre a jour les informations dans le champs ftable fname (si il est du bon type)
  680. $xset = XDataSource::objectFactoryHelper8('BCLASS=XDSTable&SPECS='.$ftable);
  681. $fd = $xset->getField($fname);
  682. if ($fd->ftype != 'XGeodesicCoordinatesDef'){
  683. XLogs::critical(get_class($this), get_class($this)."procEdit error $fname not XGeodesic type");
  684. return; // message etc ...
  685. }
  686. // vérifier les champs passes
  687. if (!$xset->fieldExists($fname)){
  688. XLogs::critical(get_class($this), get_class($this)."procEdit error $fname not exists");
  689. return; // message etc ...
  690. }
  691. if (isset($fgcauto_HID['val'])){
  692. if((!empty($fgccntr) && !$xset->fieldExists($fgccntr))||
  693. (!empty($fgctown) && !$xset->fieldExists($fgctown))){
  694. XLogs::critical(get_class($this), get_class($this)."procEdit error some fields do not exists in table");
  695. return; // message etc
  696. }
  697. // les champs addresse
  698. $fsaddr = explode(' ', $fgcaddr);
  699. foreach($fsaddr as $foo=>$faddr){
  700. if (!empty($faddr)){
  701. if (!$xset->fieldExists($faddr)){
  702. XLogs::critical(get_class($this), get_class($this)."procEdit error ");
  703. return; // message etc ...
  704. }
  705. }
  706. }
  707. }
  708. // procEdit
  709. parent::procEdit($ar);
  710. // mettre a jour les options du champ avec l'oid de ce module map
  711. $xseta=XDataSource::objectFactoryHelper8('BCLASS=XDSTable&SPECS='.$ftable);
  712. $xseta->procEditField(array('field'=>$fname, 'tplentry'=>TZR_RETURN_DATA, '_todo'=>'save', 'options'=>array('gmoid'=>$this->_moid)));
  713. }
  714. // retourne une url pour ouvrir une page de visualisation
  715. //
  716. function getGeoViewUrl($ar){
  717. $p = new XParam($ar, array());
  718. $table = $p->get('table');
  719. $fieldname = $p->get('fieldname');
  720. $moid = $this->_moid;
  721. $templates = 'googlesearch.html';
  722. return $GLOBALS['TZR_SESSION_MANAGER']::complete_self(true, true)."skip=1&moid={$moid}&class=XModMap&table={$table}&field={$fieldname}&provider=google&function=geoSearch&template=xmodmap/geosearch.html&readonly=readonly&tplentry=br";
  723. }
  724. // retourne une url pour ouvrir une page de recherche pour ce champ
  725. //
  726. function getGeoSearchUrl($ar){
  727. $p = new XParam($ar, array());
  728. $table = $p->get('table');
  729. $fieldname = $p->get('fieldname');
  730. $moid = $this->_moid;
  731. $templates = 'googlesearch.html';
  732. return $GLOBALS['TZR_SESSION_MANAGER']::complete_self(true, true)."skip=1&&moid={$moid}&class=XModMap&table={$table}&field={$fieldname}&provider=google&function=geoSearch&template=xmodmap/geosearch.html&tplentry=br";
  733. }
  734. // recherche une entree pour cette table et ce champ
  735. // -> si plusieurs couches, on suppose que la fonc en edition est commune
  736. //
  737. function &getFieldSetup($ar){
  738. $p = new XParam($ar, array());
  739. $ftable = $p->get('ftable');
  740. $fieldname = $p->get('fname');
  741. $rs = selectQuery("select * from {$this->table} where fname='{$fieldname}' and ftable='{$ftable}'");
  742. if ($ors = $rs->fetch()){
  743. list ($lat, $lng) = explode(';', $ors['elatlng']);
  744. $ors['elat']=$lat;
  745. $ors['elng']=$lng;
  746. $ors['autogc']=($ors['fgcauto']==2)?false:true;
  747. $ors['layerscount'] = $rs->rowCount();
  748. $ors['minaccuracy'] = 4;
  749. return $ors;
  750. } else {
  751. // XShell print2log ....
  752. return array();
  753. }
  754. }
  755. function geoSearch($ar){
  756. $p = new XParam($ar, array('tplentry'=>'br'));
  757. $tpl = $p->get('tplentry');
  758. $fs = $this->getFieldSetup($ar);
  759. $ar['fs'] = $fs;
  760. // affichage des couches (?)
  761. $provider = $p->get('provider');
  762. if ($provider == 'google')
  763. $res = $this->googleSearch($ar);
  764. else
  765. $res = NULL;
  766. $res['fs'] = $fs;
  767. return XShell::toScreen1($tpl, $res);
  768. }
  769. // affiche uen carte de recherche pour la table et le champ donne
  770. // -> google ici
  771. //
  772. function googleSearch($ar){
  773. $p = new XParam($ar, array('tplentry'=>'br'));
  774. $fs = $p->get('fs');
  775. $tpl = $p->get('tplentry');
  776. $ftable = $p->get('ftable');
  777. $fname = $p->get('fname');
  778. $fid = $p->get('fid');
  779. $flatlng = $p->get('flatlng');
  780. $flatlng = trim($flatlng);
  781. $foptions = $p->get('foptions');
  782. $readonly = $p->get('readonly');
  783. $oid = $p->get('oid');
  784. // recherche des infos table/champ dans l'EF
  785. // $fs = $this->getFieldSetupEdit($ar);
  786. // position initiale reçue sinon defaut
  787. if (!empty($flatlng) && $flatlng!=';'){
  788. list($plat, $plng) = explode(';', $flatlng);
  789. $mlat = $fs['elat'];
  790. $mlng = $fs['elng'];
  791. $newpoint = false;
  792. } elseif (!empty($oid)) {
  793. /* to do editer l'occurence ? */
  794. } else {
  795. $plat = $mlat = $fs['elat'];
  796. $plng = $mlng = $fs['elng'];
  797. $newpoint = true;
  798. }
  799. // lire le champ ? ... la cle etc
  800. $res = array('google'=>array('key'=>$this->key),
  801. 'map'=>array('zoom'=>$fs['ezoom'],
  802. 'readonly'=>$readonly,
  803. 'lng'=>$mlat,
  804. 'lat'=>$mlng),
  805. 'point'=>array('newpoint'=>$newpoint,
  806. 'lat'=>$plat,
  807. 'lng'=>$plng,
  808. 'ftable'=>$ftable,
  809. 'fid'=>$fid,
  810. 'fname'=>$fname,
  811. 'foptions'=>$foptions
  812. ),
  813. 'maplabels'=>array('normalview'=>XLabels::getSysLabel('xmodmap','normalview', 'text'),
  814. 'physicalview'=>XLabels::getSysLabel('xmodmap','physicalview', 'text'),
  815. 'satelliteview'=>XLabels::getSysLabel('xmodmap','sattelitview', 'text'),
  816. 'hybridview'=>XLabels::getSysLabel('xmodmap','hybridview', 'text'),
  817. 'search'=>XLabels::getSysLabel('general', 'query', 'text'),
  818. 'validate'=>XLabels::getSysLabel('general', 'save', 'text'),
  819. 'quit'=>XLabels::getSysLabel('general', 'close', 'text'),
  820. 'notfound'=>XLabels::getSysLabel('xmodmap', 'unknownaddress', 'text'),
  821. 'centerview'=>XLabels::getSysLabel('xmodmap', 'centerview', 'text')
  822. )
  823. );
  824. return $res;
  825. }
  826. // deamon
  827. // -> faire le geocodage auto
  828. protected function _daemon($period='any') {
  829. return true;
  830. }
  831. // traitement des geocodages automatiques
  832. // -> pour chaque carte, si geocodeauto, faire les recherches
  833. //
  834. function geoCodeAuto($ar){
  835. $p = new XParam($ar, array());
  836. $done = array();
  837. $cr ="";
  838. XLogs::notice(get_class($this),get_class($this)."::geoCodeAuto start");
  839. $rs = selectQuery("select ftable, fname, KOID from {$this->table} where fgcauto=1");
  840. $cr .= "{$rs->rowCount()} map(s) to scan";
  841. XLogs::update('geocoding', NULL, 'start '.$cr);
  842. while($rs && $ors = $rs->fetch()){
  843. if (!isset($done[$ors['ftable'].$ors['fname']])){
  844. $cr = "scanning : {$ors['ftable']} {$ors['fname']}\n";
  845. $done[$ors['ftable'].$ors['fname']] = array();
  846. $modmap = $this->xset->rdisplay($ors['KOID']);
  847. $r = $this->geoCodeXSet($modmap);
  848. $cr .= "\t rows : {$r['nt']} querie(s) : {$r['nq']} omitted : {$r['nqn']}\n";
  849. XLogs::update('geocoding', NULL, $cr);
  850. }
  851. }
  852. XLogs::notice(get_class($this),get_class($this)."::geoCodeAuto end");
  853. // compte rendu ?
  854. XLogs::update('geocoding', NULL, 'end');
  855. }
  856. // traitement de geocodage d'une table donnee
  857. // -> si fiche modifiee, refaire le geocodage
  858. //
  859. function geoCodeXSet($modmap){
  860. // Cas ou l'on passe directement un oid
  861. if(!is_array($modmap)) $modmap=$this->xset->rdisplay($modmap);
  862. $nq = 0; $nqn = 0;
  863. $fname = $modmap['ofname']->raw;
  864. $ftable = $modmap['oftable']->raw;
  865. XLogs::notice(get_class($this),get_class($this)."::geoCodeAutoXSet start");
  866. $xset = XDataSource::objectFactoryHelper8('BCLASS=XDSTable&SPECS='.$ftable);
  867. $rs = selectQuery($xset->select_query(array()));
  868. $tests = 0;
  869. $delay = 0;
  870. while($rs && ($ors = $rs->fetch())){
  871. $pending = true;
  872. while($pending){
  873. $foo = array();
  874. $ofc = $xset->getField($fname);
  875. $fv = $ofc->edit($ors[$fname], $foo);
  876. if($fv->type == 'A' && ($fv->accuracy == '' || $fv->accuracy == 'N/A' || empty($fv->upd) || $ors['UPD'] > $fv->upd ||
  877. $modmap['oUPD']->raw > $fv->upd)){
  878. $gar = array();
  879. $addressfields = explode(' ', $modmap['ofgcaddr']->raw);
  880. foreach($addressfields as $foo=>$afn){
  881. $afv = trim($ors[$afn]);
  882. if (!empty($afv))
  883. $gar['address'][] = array('value'=>$afv, 'retry'=>true, 'default'=>NULL);
  884. }
  885. $gar['city'] = array('value'=>$ors[$modmap['ofgctown']->raw], 'retry'=>true, 'default'=>NULL);
  886. $gar['zipcode'] = array('value'=>$ors[$modmap['ofgczipc']->raw], 'retry'=>false, 'default'=>NULL);
  887. $gar['country'] = array('value'=>$ors[$modmap['ofgccntr']->raw], 'retry'=>false, 'default'=>NULL);
  888. $nq += 1;
  889. $rg = $this->googleGeoCode($gar, 0, $ors['KOID']);
  890. list ($ok, $mess, $accuracy, $coords, $maddress, $retry, $query) = $rg;
  891. XLogs::notice(get_class($this).get_class($this)."::googleGeoCode $ok $mess $retry $query");
  892. $tests += 1;
  893. if ($ok){
  894. $pending = false;
  895. $fres = array('latlng'=>$coords[1].';'.$coords[0],
  896. 'autogc'=>1,
  897. 'accuracy'=>$accuracy);
  898. $xset->procEdit(array('_options'=>array('local'=>true),
  899. 'tplentry'=>TZR_RETURN_DATA,
  900. $fname=>$fres,
  901. 'oid'=>$ors['KOID']));
  902. } else if ($mess == 'too many query'){
  903. $delay += 100000; // pending reste a true
  904. XLogs::notice(get_class($this),get_class($this)."::geoCodeAutoXSet delaying $delay $nq");
  905. XLogs::update('geocoding', NULL, "incr delaying $delay $nq");
  906. }else{
  907. $pending =false;
  908. $fres = array('latlng'=>'',
  909. 'autogc'=>1,
  910. 'accuracy'=>0);
  911. $xset->procEdit(array('_options'=>array('local'=>true),
  912. 'tplentry'=>TZR_RETURN_DATA,
  913. $fname=>$fres,
  914. 'oid'=>$ors['KOID']));
  915. }
  916. } else {
  917. XLogs::notice(get_class($this),get_class($this)."::geCodeXSet up to date ".$ors['KOID']);
  918. $nqn += 1;
  919. $pending = false;
  920. $delay = 0;
  921. }
  922. usleep($delay);
  923. XLogs::notice('XModMap', "geoCodeXSet query $nq ommitted $nqn of {$rs->rowCount()}");
  924. }
  925. }
  926. XLogs::notice(get_class($this),get_class($this)."::geoCodeAutoXSet end");
  927. return array('nq'=>$nq, 'nqn'=>$nqn, 'nt'=>$rs->rowCount());
  928. }
  929. // requete geocodage google
  930. //
  931. function googleGeoCode($addressFields, $retry=0, $oid=NULL /*pour trace*/){
  932. $q = '';
  933. foreach($addressFields['address'] as $foo=>$fd){
  934. $this->googleAppendtoQuery($fd, $q, ' ');
  935. }
  936. $otherfields = array('zipcode', 'city', 'country');
  937. foreach($otherfields as $foo=>$fn){
  938. if (!empty($addressFields[$fn])){
  939. $this->googleAppendtoQuery($addressFields[$fn], $q, ',');
  940. }
  941. }
  942. XLogs::notice(get_class($this), get_class($this)."::googleGeoCode $retry $oid start, query : $q");
  943. $url = $this->geocodeurl.'key='.$this->key.'&output=kml&q='.urlencode($q);
  944. $gres = file_get_contents($url, NULL);
  945. if ($this->googleGeoCodeEncoding != 'UTF-8')
  946. $gres = utf8_encode($gres);
  947. $r = $this->decodeGoogleGeocodeXml($gres);
  948. list($ok, $mess, $accuracy, $coordinates, $matchedaddress) = $r;
  949. if (!$ok){
  950. $na = count($addressFields['address']);
  951. if ($na >= 1 && $mess != 'too many query'){
  952. array_shift($addressFields['address']);
  953. return $this->googleGeocode($addressFields, $retry+1, $oid);
  954. }
  955. } else {
  956. array_push($r, $retry, $q);
  957. }
  958. XLogs::notice(get_class($this).get_class($this)."::googleGeoCode $retry $oid end");
  959. return $r;
  960. }
  961. /// formatage d'une requete google geocodage
  962. function googleAppendToQuery($fd, &$q, $sep=''){
  963. $f = (object)$fd;
  964. $fv = '';
  965. if (empty($f->value) && !empty($f->default))
  966. $fv = $f->default;
  967. else
  968. $fv = $f->value;
  969. if (!empty($fv)){
  970. $fv = preg_replace('/,/', '', $fv);
  971. if (empty($q))
  972. $q = $fv;
  973. else
  974. $q .= $sep.$fv;
  975. }
  976. }
  977. /// decode une reponse geocode xml/kml
  978. function decodeGoogleGeocodeXml(&$xml){
  979. $d = new DOMDocument();
  980. $d->loadXML($xml); // ?
  981. $xq = new DOMXPath($d);
  982. $kmlns = 'http://earth.google.com/kml/2.0';
  983. $oasins = 'urn:oasis:names:tc:ciq:xsdschema:xAL:2.0';
  984. $xq->registerNameSpace('kml', $kmlns);
  985. $xq->registerNameSpace('oasi', $oasins);
  986. $r1 = $xq->query('/kml:kml/kml:Response/kml:Status/kml:code/text()');
  987. if ($r1->length != 1){
  988. return array(false, 'unable to decode google response');
  989. }
  990. $status = $r1->item(0)->wholeText;
  991. if (isset($this->googleGeoStatus[$status])){
  992. switch($status){
  993. case 200:
  994. // check multiples responses and accuracy
  995. $r2 = $xq->query('/kml:kml/kml:Response/kml:Placemark');
  996. if ($r2->length == 0){
  997. return array(false, 'unable to decode google response : address');
  998. }
  999. if ($r2->length == 1){
  1000. $place = $r2->item(0);
  1001. $r3 = $xq->query('oasi:AddressDetails', $place);
  1002. $accuracy = $r3->item(0)->getAttributeNode('Accuracy')->value;
  1003. // check accuracy ...
  1004. if (!isset($this->googleGeoAccuracy[$accuracy])){
  1005. return array(false, 'unknown accuracy '.$accuracy);
  1006. }
  1007. if ($accuracy == 0){
  1008. return array(false, 'null accuracy ');
  1009. }
  1010. unset($r3);
  1011. $r4 = $xq->query('kml:Point/kml:coordinates/text()', $place);
  1012. if ($r4->length == 0){
  1013. return array(false, 'unable to decode google response Point coordinates');
  1014. }
  1015. $raw = $r4->item(0)->wholeText;
  1016. list($lat, $lng) = explode(',', $raw);
  1017. unset($r4);
  1018. // read the exact address found
  1019. $r5 = $xq->query('kml:address/text()', $place);
  1020. $maddress = $r5->item(0)->wholeText;
  1021. $ret = array(true, 'exact match', $accuracy, array($lat, $lng), $maddress);
  1022. } else {
  1023. // multiple responses
  1024. $ret = array(false, 'multiple matches');
  1025. }
  1026. unset($r2);
  1027. return $ret;
  1028. break;
  1029. case 400:
  1030. case 601:
  1031. return array(false, 'invalid query');
  1032. break;
  1033. case 602:
  1034. case 603:
  1035. return array(false, 'unknow adress/unavailable address');
  1036. break;
  1037. case 610:
  1038. return array(false, 'invalid key');
  1039. break;
  1040. case 620:
  1041. return array(false, 'too many query');
  1042. break;
  1043. default:
  1044. return array(false, 'unknow google status'.$status);
  1045. break;
  1046. }
  1047. }else{
  1048. return array(false, 'unknown google status '.$status);
  1049. }
  1050. }
  1051. private function accuracyLabel($accuracy){
  1052. if (!isset($this->googleGeoAccuracy[$accuracy]))
  1053. return '***';
  1054. return $this->googleGeoAccuracy[$accuracy][1];
  1055. }
  1056. /// Retourne les bornes d'une zone autour d'un point à une distance donnee sous forme de tableau ou de requete
  1057. /// form : circle => cercle de rayon $d / in => carre interieur du cercle de rayon $d / out => carre exterieur du cercle de rayon $d
  1058. static function getZoneCoord($lt,$lg,$d,$form='circle',$field=NULL){
  1059. if($form=='circle'){
  1060. if(empty($field)) return NULL;
  1061. return " where $d >= (acos(cos(radians($lt))*cos(radians($lg))*cos(radians(SUBSTRING_INDEX($field,';',1)))*cos(radians(SUBSTRING_INDEX(SUBSTRING_INDEX($field,';',2),';',-1))) + cos(radians($lt))*sin(radians($lg))*cos(radians(SUBSTRING_INDEX($field,';',1)))*sin(radians(SUBSTRING_INDEX(SUBSTRING_INDEX($field,';',2),';',-1))) + sin(radians($lt))*sin(radians(SUBSTRING_INDEX($field,';',1)))) * ".EARTHRAY.")";
  1062. }
  1063. if($form=='in') $d=sqrt(2*pow($d,2));
  1064. $top=$lt+($d*360)/(2*pi()*EARTHRAY);
  1065. $bot=$lt-($d*360)/(2*pi()*EARTHRAY);
  1066. $left=$lg-($d*360)/(cos(deg2rad($lt))*2*pi()*EARTHRAY);
  1067. $right=$lg+($d*360)/(cos(deg2rad($lt))*2*pi()*EARTHRAY);
  1068. if(!empty($field)){
  1069. return " where SUBSTRING_INDEX($field,';',1)>$bot and SUBSTRING_INDEX($field,';',1)<$top ".
  1070. "and SUBSTRING_INDEX(SUBSTRING_INDEX($field,';',2),';',-1)>$left and SUBSTRING_INDEX(SUBSTRING_INDEX($field,';',2),';',-1)<$right";
  1071. }else{
  1072. return array('top'=>$top,'bot'=>$bot,'left'=>$left,'right'=>$right);
  1073. }
  1074. }
  1075. private function getGLang(){
  1076. $ulang = XShell::getLangUser();
  1077. if($ulang == 'FR')
  1078. $glang = 'fr';
  1079. else if ($ulang == 'IT')
  1080. $glang = 'it';
  1081. else
  1082. $glang = 'en';
  1083. }
  1084. /**
  1085. * fonction de transformations
  1086. * \param String $fromSyst : code du système d'origine
  1087. * \param String $fromSyst : code du système destination
  1088. * \param array $data :
  1089. * - in : fichier à traiter
  1090. * - out : fichier en sortie
  1091. * \note
  1092. * voir http://spatialreference.org/
  1093. *'EPSG:32600' : 'UTM WGS84 North, 32601 -> zone 1, ...',
  1094. *'EPSG:32700' : 'UTM WGS84 South, 32701 -> zone 1, ...',
  1095. *'EPSG:4326' : 'WGS84',
  1096. *'EPSG:6171' : 'RGF93', // à vérifier
  1097. *'EPSG:2154' : 'Lambert 93',
  1098. *'EPSG:27561' : 'Lambert carto Nord',
  1099. *'EPSG:27562' : 'Lambert carto Centre',
  1100. *'EPSG:2154' : 'Lambert carto Sud',
  1101. *'EPSG:27564' : 'Lambert carto Corse',
  1102. *'EPSG:27571' : 'Lambert zone I',
  1103. *'EPSG:27572' : 'Lambert zone II',idem zone 2 etendu
  1104. *'EPSG:27573' : 'Lambert zone III',
  1105. *'EPSG:27574' : 'Lambert zone IV'
  1106. */
  1107. public static function convertFile($fromSyst, $toSyst, $in, $out){
  1108. XLogs::notice(get_class(), '::convertFile : gdaltransform -s_srs '.$fromSyst.' -t_srs '.$toSyst.' < '.$in.' > '.$out);
  1109. system(TZR_GDAL_PATH.'gdaltransform -s_srs '.$fromSyst.' -t_srs '.$toSyst.' < '.$in.' > '.$out);
  1110. }
  1111. /**
  1112. * \note
  1113. * idem convertFile mais à partir d'un tableau de lignes x y (z)
  1114. */
  1115. public static function convertArray($fromSyst, $toSyst, $in){
  1116. $infilename = TZR_TMP_DIR.uniqid('xmodmapconversion_in');
  1117. $outfilename = TZR_TMP_DIR.uniqid('xmodmapconversion_out');
  1118. $fp = fopen($infilename, 'w');
  1119. foreach($in as $coordline){
  1120. fwrite($fp, $coordline."\n");
  1121. }
  1122. fclose($fp);
  1123. self::convertFile($fromSyst, $toSyst, $infilename, $outfilename);
  1124. $res = explode("\n", trim(file_get_contents($outfilename)));
  1125. unlink($infilename);
  1126. unlink($outfilename);
  1127. return $res;
  1128. }
  1129. /**
  1130. * conversion d'une liste de coordonnées
  1131. */
  1132. function convertCoords($ar){
  1133. $p = new XParam($ar, array('insrs'=>self::$defaultSRS, 'mode'=>'ajax'));
  1134. $coords = $p->get('coords');
  1135. $insrs = $p->get('insrs');
  1136. $tosrs = $p->get('tosrs');
  1137. $tpl = $p->get('tplentry');
  1138. $mode = $p->get('mode');
  1139. if (!is_array($coords)){
  1140. $coords = array($coords);
  1141. }
  1142. // lecture des systèmes
  1143. $fromOrs = selectQuery('select * from MAPSRS where lang="FR" and KOID = "'.$insrs.'"')->fetch();
  1144. $toOrs = selectQuery('select * from MAPSRS where lang="FR" and KOID = "'.$tosrs.'"')->fetch();
  1145. // conversion
  1146. $res = self::convertArray($fromOrs['epsgcode'], $toOrs['epsgcode'], $coords);
  1147. $res2 = array();
  1148. // mise en forme
  1149. foreach($res as $ares){
  1150. list($x, $y) = explode(' ', $ares);
  1151. if (!empty($toOrs['dformat'])){
  1152. $res2[] = str_replace(array('%_x', '%_y'), array(sprintf('%d', $x), sprintf('%d',$y)), $toOrs['dformat']);
  1153. } else {
  1154. $res2[] = $x.' '.$y;
  1155. }
  1156. }
  1157. if ($mode == 'ajax'){
  1158. die(json_encode($res2));
  1159. }
  1160. return XShell::toScreen1($tpl, $res2);
  1161. }
  1162. /**
  1163. * convertions depuis l'admin
  1164. */
  1165. function preConvertCoords($ar){
  1166. // liste des systèmes configurés
  1167. $ds = XDataSource::objectFactoryHelper8('BCLASS=XDSTable&SPECS=MAPSRS');
  1168. $ds->browse(array('tplentry'=>'br1', 'pagesize'=>9999, 'order'=>'title asc'));
  1169. }
  1170. function procConvertCoords($ar){
  1171. $p = new XParam($ar, array());
  1172. $fromSrs = $p->get('insrs');
  1173. $toSrs = $p->get('tosrs');
  1174. $incoords = trim($p->get('incoords'));
  1175. if (empty($incoords) && (!isset($_FILES['infile']['tmp_name']) || !file_exists($_FILES['infile']['tmp_name']))){
  1176. XShell::setNext($GLOBALS['TZR_SESSION_MANAGER']::complete_self().'&moid='.$this->_moid.'&function=preConvertCoords&template=xmodmap/convert.html&tplentry=br');
  1177. XShell::setNextData('message', '...');
  1178. return;
  1179. }
  1180. if (!empty($incoords)){
  1181. // convertion des coordonnées saisies
  1182. $ar['coords'] = explode('\n', $incoords);
  1183. $ar['mode'] = 'ret';
  1184. $ar['tplentry'] = TZR_RETURN_DATA;
  1185. $res = $this->convertCoords($ar);
  1186. setSessionVar('message', '<pre>'.implode("\n", $res)."\n".implode("\n", $ar['coords']).'</pre>');
  1187. } else {
  1188. // lecture des systèmes
  1189. $fromOrs = selectQuery('select * from MAPSRS where lang="FR" and KOID = "'.$fromSrs.'"')->fetch();
  1190. $toOrs = selectQuery('select * from MAPSRS where lang="FR" and KOID = "'.$toSrs.'"')->fetch();
  1191. // convertion du fichier
  1192. $outfilename = TZR_TMP_DIR.uniqid('xmodmapconversion_out');
  1193. self::convertFile($fromOrs['epsgcode'], $toOrs['epsgcode'], $_FILES['infile']['tmp_name'], $outfilename);
  1194. XShell::setNextFile($outfilename, 'converted_'.$_FILES['infile']['name'], 'text/csv');
  1195. }
  1196. XShell::setNext($GLOBALS['TZR_SESSION_MANAGER']::complete_self().'&moid='.$this->_moid.'&function=preConvertCoords&template=xmodmap/convert.html&tplentry=br');
  1197. }
  1198. }
  1199. ?>