NCCOOS Trac Projects: Top | Web | Platforms | Processing | Viz | Sprints | Sandbox | (Wind)

root/Chameleon/trunk/Chameleon/query_utils.php

Revision 13 (checked in by jcleary, 17 years ago)

Latest Chameleon code checkout from previous repository

Line 
1 <?php
2 /**
3  * Common query utility functions
4  *
5  * @project     Chameleon
6  * @revision    $Id: query_utils.php,v 1.1 2004/11/26 20:03:28 pspencer Exp $
7  * @purpose     common utility functions used to query data
8  * @author      Paul Spencer (pspencer@dmsolutions.ca)
9  * @copyright
10  * <b>Copyright (c) 2002, DM Solutions Group Inc.</b>
11  * Permission is hereby granted, free of charge, to any person obtaining a
12  * copy of this software and associated documentation files (the "Software"),
13  * to deal in the Software without restriction, including without limitation
14  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15  * and/or sell copies of the Software, and to permit persons to whom the
16  * Software is furnished to do so, subject to the following conditions:
17  *
18  * The above copyright notice and this permission notice shall be included
19  * in all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
24  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27  * DEALINGS IN THE SOFTWARE.
28  */
29
30 include_once( COMMON."wrapper/map_query.php" );
31 include_once( COMMON."xml_utils/XMLObject.php" );
32 include_once( COMMON."/phpwms/dbf.php");
33
34 /**
35  * execute a query on the given map session object at the given location or rectangle.  If a rectangular
36  * query is requested, it will only work on local layers.  WMS layers can only be queried by point.
37  *
38  * @param oMapSession object the map session object to query
39  * @param nMinX int the x coord of the query point, or the left edge of the query region
40  * @param nMinY int the y coord of the query point, or the top edge of the query region
41  * @param nMaxX int optional, if > nMinX it is the right edge of the query region
42  * @param nMaxY int optional, if > nMinY it is the bottom edge of the query region
43  * @return array an array of values returned by the query.  For every queryable layer in
44  *         the map file, the array will have a key for that layer's index ( suitable for
45  *         use with $oMap->getLayer ) and either a string 'no results' or an array of
46  *         results for that layer.  Index is sequential from 0, contents is another array
47  *         containing key->value pairs for attribute->value from the query results
48  */
49  
50 function executeQuery( $oMapSession, $nMinX, $nMinY, $nMaxX = -1, $nMaxY = -1)
51 {
52     //this could take a while for WMS results
53     set_time_limit( 120 );
54
55     // create a new map query object
56     $oMapQuery = new MapQuery( $oMapSession );
57
58     // initalize vars
59     $aszWMSResults = array();
60     
61     // loop through all layers and add to list of layers to query
62     // NOTE:  Layers will only have results generated for them if they
63     // have a "template" value set.  The template value does not have
64     // to be valid, it could be as simple as "ttt".
65     $aszLayers = array();
66     $aszTitles = array();
67     $oMap = $oMapSession->oMap;
68     $nCount = $oMap->numlayers;
69     for ( $i=0; $i<$nCount; $i++ )
70     {
71         // get layer name
72         $oLayer = $oMap->getLayer( $i );
73
74         $bQueryable = false;
75         if ($oLayer->status == MS_ON || $oLayer->status == MS_DEFAULT)
76         {
77             if ($oLayer->template != "")
78             {
79                 $bQueryable = true;
80             }
81             else
82             {
83                 for( $j=0; $j < $oLayer->numclasses; $j++)
84                 {
85                     $oClass = $oLayer->getClass($j);
86                     if ($oClass->template != "")
87                     {
88                         $bQueryable = true;
89                         break;
90                     }
91                 }
92             }
93         }
94
95         // only add if on
96         if ( $bQueryable )
97         {
98             array_push( $aszLayers, $oLayer->name );
99         }
100     }
101
102     $aResults = array();
103     // Check if there's any queryable layers
104     if(count($aszLayers) >= 1)
105     {
106         // commit
107         $oMapQuery->setQueryLayersByName( $aszLayers );
108
109         // execute query
110         $oResultSet = $oMapQuery->executePointQuery( $nMinX, $nMinY );
111         
112         // Check if there's any result
113         if($oResultSet)
114         {
115             $nCount = $oResultSet->nNumResults;
116         
117             for ( $i=0; $i<$nCount; $i++ )
118             {
119                 // process each result set
120                 $aRows = $oResultSet->getResultSet( $i );
121                 $oLayer = $oMapSession->oMap->getLayerByName( $aszLayers[$i] );
122                     
123                 /*
124                  * THIS IS FOR LOCAL LAYER RESULTS
125                  */
126                 // check if single or multiple results were returned
127                 if ( is_array( $aRows ) )
128                 {
129                     $aResults[$oLayer->index] = $aRows;
130                 }
131                 else
132                 {
133                     // check if no results on local layer
134                     if ( strcasecmp(substr( $aRows, 0, 26 ), "no results found for layer" ) != 0 )
135                     {
136                         /*
137                          * THIS IS FOR WMS RESULTS
138                          */
139                         $aResults[$oLayer->index] = processWMSGetFeatureInfo( $aRows );
140                         
141                     }
142                 }
143             }
144         }
145     }
146     return $aResults;       
147 }
148
149 function processWMSGetFeatureInfo( $szURL )
150 {
151     $aResults = array();
152    //try to determine the appropriate format to use based on the server
153     if ( stristr( $szURL, "cubeserv" ) !== false ) //CubeWerx servers
154     {
155         $szFormat = "application/x-cubestor-gml.1";
156         $szURL = setURLQueryParam( $szURL, "INFO_FORMAT", $szFormat );
157     }
158     elseif (stristr( $szURL, "interceptor") !== false ) // possibly a CTIS server
159     {
160         $szFormat = "application/x-cubestor-gml.1";
161         $szURL = setURLQueryParam( $szURL, "INFO_FORMAT", $szFormat );
162     }
163     else //possibly a mapserver server
164     {
165         $szFormat = "application/vnd.ogc.gml";
166         $szURL = setURLQueryParam( $szURL, "INFO_FORMAT", $szFormat );
167     }
168     $aszRawFile = "";
169     $nResult = getFeatureInfoResults( $szURL, $aszRawFile );
170     if ($nResult == -1)
171     {
172         return $aResults; //failed to open the url at all
173
174     }
175     elseif ($nResult == 0) //unsupported format, try text/html
176     {
177         //echo "unsupported format ($szFormat)";
178         $szFormat = "text/html";
179         $szURL = setInfoFormatURL( $szURL, $szFormat );
180         $nResult = getFeatureInfoResults( $szURL, $aszRawFile );
181
182         if ($nResult != 1) //if text/html fails, return an error
183             return $aResults;
184     }
185     //we got a result in szFormat.  Process accordingly.
186     if (strcasecmp( $szFormat, "MIME" ) == || strcasecmp( $szFormat, "text/html" ) == 0)
187     {
188         $aResults = implode( "", $aszRawFile);
189     }
190     elseif (strcasecmp( $szFormat, "application/x-cubestor-gml.1" ) == 0//cubestor gml
191     {
192         $szResult = "";
193         $szXMLDoc = implode( "", $aszRawFile );
194         if ($szXMLDoc != "")
195         {
196             $oXMLObj = new XMLObject( $szXMLDoc );
197             foreach( $oXMLObj->children as $oResult )
198             {
199                 if (strcasecmp( $oResult->name, "FeatureCollection" ) == 0 )
200                     $aResults = processCubeWerxGML( $oResult );
201             }
202         }
203     }
204     elseif( strcasecmp( $szFormat, "application/vnd.ogc.gml" ) == 0 //mapserver gml
205     {
206         $szResult = "";
207         $szXMLDoc = implode( "", $aszRawFile);
208         if ($szXMLDoc != "")
209         {
210             $oXMLObj = new XMLObject( $szXMLDoc );
211             foreach( $oXMLObj->children as $oResult )
212             {
213                 if (strcasecmp( $oResult->name, "msGMLOutput" ) == 0 )
214                     $aResults = processMapServerGML( $oResult );
215             }
216         }
217     }
218     return $aResults;
219 }
220
221 function getFeatureInfoResults($szURL, &$aszRawFile)
222 {
223     global $oMLT;
224   //echo $szURL;
225
226     $aszRawFile = @file( $szURL );
227
228     if ($aszRawFile === false) // failed to open the URL entirely
229         return -1;
230     else
231     {
232         $szXMLDoc = trim(implode( "", $aszRawFile));
233
234         //if the doc string is empty, fail.
235         if ($szXMLDoc == "")
236         {
237             //echo "failing on empty doc string<BR>";
238             return 0;
239         }
240
241         //test if it is an xml document
242         if (stristr($szXMLDoc, "<?xml") === false)
243         {
244             //its not XML, that's okay.
245             //echo "not an XML doc<BR>";
246             return 1;
247         }
248
249         //try to parse it as XML
250         $oXMLObj = new XMLObject( $szXMLDoc );
251
252         //no children in base object means there where no XML tags in the doc,
253         if (count( $oXMLObj->children ) == 0)
254         {
255             // No children, that can happen.
256             //echo "zero children<BR>";
257             return 1;
258         }
259         if (strcasecmp($oXMLObj->children[0]->name, "ServiceException") == 0)
260         {
261             //a WMS Service Exception, return -1.
262             $oXMLObj->dumpObject();
263             //echo "service exception<BR>";
264             return -1;
265         }
266
267         //otherwise the document may be okay
268         return 1;
269     }
270 }
271
272 //generic function to set a single value in a URL query string
273 //and return the whole URL back again.
274 function setURLQueryParam( $szURL, $szValue, $szParam )
275 {
276     global $oMLT;
277
278     $aszParts = parse_url( $szURL );
279     parse_str( $aszParts["query"], $aszQuery );
280     $aszQuery[$szValue] = $szParam;
281     $szQuery = "";
282     $szSep = "";
283     foreach( $aszQuery as $key => $value )
284     {
285         $szQuery .= $szSep.$key."=".urlencode( $value );
286         $szSep = "&";
287     }
288     $aszParts["query"] = $szQuery;
289     return glue_url( $aszParts );
290 }
291
292 //generic function to glue a URL back together after it has been parsed by
293 //parse_url (taken from http://www.php.net/parse_url with some modifications)
294 function glue_url($parsed)
295 {
296     if (! is_array($parsed))
297         return false;
298     $uri = (isset($parsed['scheme'])) ? $parsed['scheme'].':'.((strtolower($parsed['scheme']) == 'mailto') ? '':'//'): '';
299     $uri .= (isset($parsed['user'])) ? $parsed['user'].($parsed['pass']? ':'.$parsed['pass']:'').'@':'';
300     $uri .= (isset($parsed['host'])) ? $parsed['host'] : '';
301     $uri .= (isset($parsed['port'])) ? ':'.$parsed['port'] : '';
302     $uri .= (isset($parsed['path'])) ? $parsed['path'] : '';
303     $uri .= (isset($parsed['query'])) ? '?'.$parsed['query'] : '';
304     $uri .= (isset($parsed['fragment'])) ? '#'.$parsed['fragment'] : '';
305     return $uri;
306 }
307
308 //process CubeWerx GML output from a GetFeatureInfo and return formatted
309 //results
310 function processCubeWerxGML( $oXMLObj )
311 {
312     $aResults = array();
313     
314     foreach($oXMLObj->children as $oMember)
315     {
316         if (strcasecmp($oMember->name, "featureMember") != 0)
317             continue;
318
319         $nFeatureMembers ++;
320
321         $nFeatures  = 0;
322         foreach( $oMember->children as $oFeature )
323         {
324             if (strcasecmp($oFeature->name, "feature" ) != 0)
325                 continue;
326
327             $aSingleResult = array();
328             
329             foreach( $oFeature->children as $oProperty )
330             {
331                 if (strcasecmp($oProperty->name, "property") != 0)
332                     continue;
333
334                 $szTypeName = trim((isset($oProperty->typename)) ?
335                               $oProperty->typename : trim($oMLT->get("6", "missing typename")));
336                 $szValue = trim((isset($oProperty->value)) ? $oProperty->value : trim($oMLT->get("9", "no value")) );
337                 
338                 $aSingleResult[$szTypeName] = $szValue;
339             }
340             $aResults[] = $aSingleResult;
341         }
342     }
343     return $aResults;
344 }
345
346
347 //process MapServer GML output from a GetFeatureInfo and return formatted
348 //results
349 function processMapServerGML( $oXMLObj )
350 {
351     $aResults = array();
352     foreach($oXMLObj->children as $oLayer)
353     {
354         $aSingleResult = array();
355         foreach( $oLayer->children as $oFeature )
356         {
357             foreach( $oFeature->children as $oProperty )
358             {
359                 $szAttributeName = trim($oProperty->name);
360                 $szValue = trim($oProperty->value);
361                 $aSingleResult[$szAttributeName] = $szValue;
362             }
363         }
364         $aResults[] = $aSingleResult;
365     }
366     return $aResults;
367 }
368 ?>
Note: See TracBrowser for help on using the browser.