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

root/Chameleon/trunk/Chameleon/LayerAttributes.php

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

Latest Chameleon code checkout from previous repository

Line 
1 <?php
2 /**
3 * Layer Attributes utility functions
4 *
5 * @project     GeoInnovations 2002
6 * @revision    $Id: LayerAttributes.php,v 1.14 2004/06/08 19:08:20 pspencer Exp $
7 * @purpose     Generic functions for accessing layer attributes
8 * @author      Jason Fournier (dev@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 $bFoundAttributes = false;
31
32 /*
33    This file provides functions for finding layer attributes from a MapScript
34    layer object that is either local, WFS, or WMS with associated WFS.
35   
36    Processing Logic:
37  
38    Based on layer connection type and layer type.  Only works if layer type
39    is one of:
40   
41    MS_LAYER_POINT
42    MS_LAYER_LINE
43    MS_LAYER_POLYGON
44   
45    We find attributes by doing a layer->open() and getting the first shapeObj
46    then looking at the shapeObj's values array.
47   
48    Special case for WMS and WFS connection types, we can get the information from
49    the WFS server (in the WMS case, we try a DescribeLayer request to find out
50    about associated WFS)
51
52    layer types
53
54    MS_LAYER_POINT
55    MS_LAYER_LINE
56    MS_LAYER_POLYGON
57    MS_LAYER_RASTER
58    MS_LAYER_ANNOTATION
59    MS_LAYER_QUERY
60    MS_LAYER_CIRCLE
61    MS_LAYER_GRATICULE
62
63    connection types
64   
65    MS_INLINE
66    MS_SHAPEFILE
67    MS_TILED_SHAPEFILE
68    MS_SDE
69    MS_OGR
70    MS_TILED_OGR
71    MS_POSTGIS
72    MS_WMS
73    MS_ORACLESPATIAL
74    MS_WFS
75    MS_GRATICULE
76    MS_MYGIS
77  */
78
79 function GetLayerAttributes( $oLayer )
80 {
81     $aszAttributes = array();
82     
83     if (//$oLayer->type == MS_LAYER_RASTER &&
84         $oLayer->connectiontype == MS_WMS)
85     {
86         //get the layer name from metadata if possible to avoid the problems
87         //with context layers being renamed
88         $szLayerName = $oLayer->getMetaData( "wms_name" );
89         if ($szLayerName == "")
90             $szLayerName = $oLayer->name;
91             
92         // get WFS the connection string
93         //$szWFSConnection = getWFSConnection( $oLayer->connection, $szLayerName );
94         $aszInfo = getWFSConnection( $oLayer->connection, $szLayerName );
95         //$aszInfo['typename'] = $oLayer->getMetaData( "wfs_typename" ); // added by JC
96         $szWFSConnection = $aszInfo['wfs'];
97     //$szWFSConnection = $oLayer->getMetaData( "wfs_connection" ); //addd by JC
98         
99         $szWFSTypeName = "";
100         $sep = '';
101         // loop and build typename
102         foreach( $aszInfo['typename'] as $szTypeName )
103         {
104             $szWFSTypeName .= $sep.$szTypeName;
105             $sep = ',';
106         }
107           
108         // check for false (meaning no associated WFS)
109         if ( $szWFSConnection != "" )
110         {
111             $szWFSConnection = fixWFSURL( $szWFSConnection, $szWFSTypeName );
112
113             // get the attribute types
114             $aszAttributes['name'] = $oLayer->name;
115             $aszAttributes['index'] = $oLayer->index;
116             $aszAttributes['onlineresource'] = $szWFSConnection;
117             $aszAttributes['minx'] = "";
118             $aszAttributes['miny'] = "";
119             $aszAttributes['maxx'] = "";
120             $aszAttributes['maxy'] = "";
121             $aszAttributes['fields'] = getAttributeTypes( $szWFSConnection.
122                         'request=describefeaturetype', $szLayerName );
123         }
124     }
125     elseif ($oLayer->type == MS_LAYER_POINT ||
126         $oLayer->type == MS_LAYER_LINE ||
127         $oLayer->type == MS_LAYER_POLYGON )
128     {
129     
130         // process according to layer type
131         switch( $oLayer->connectiontype )
132         {
133             case MS_WFS:
134                 //get the layer name from metadata if possible to avoid the problems
135                 //with context layers being renamed
136                 $szLayerName = $oLayer->getMetaData( "wms_name" );
137                 if ($szLayerName == "")
138                     $szLayerName = $oLayer->name;
139                     
140                 // record the connection string
141                 $szWFSConnection = $oLayer->connection;
142                 
143                 // check the the WFS online resource contains the necessary params
144                 $szWFSConnection = fixWFSURL( $szWFSConnection, $szLayerName );
145     
146                 // get the attribute types
147                 $aszAttributes['name'] = $oLayer->name;
148                 $aszAttributes['index'] = $oLayer->index;
149                 $aszAttributes['onlineresource'] = $szWFSConnection;
150                 $aszAttributes['minx'] = "";
151                 $aszAttributes['miny'] = "";
152                 $aszAttributes['maxx'] = "";
153                 $aszAttributes['maxy'] = "";
154                 $aszAttributes['fields'] = getAttributeTypes( $szWFSConnection.
155                                 'request=describefeaturetype', $szLayerName );
156                 
157     
158                 break;
159             
160     
161             default:
162                 // open the layer
163                 $oLayer->open();
164                 
165                 //handle tiled shapefiles correctly, otherwise they don't get
166                 //extents or attributes
167                 if ($oLayer->connectiontype == MS_TILED_SHAPEFILE ||
168                     $oLayer->tileindex != "")
169                 {
170                     //first tile is sufficient, assume that all attributes are the same
171                     //in every tile (which is reasonable)
172                     $nTile = 0;
173                 }
174                 else
175                 {
176                     //use -1 in getShape for non-tiled sources
177                     $nTile = -1;
178                 }
179                 // read the first line of the datasource to get
180                 // name, index, and fields
181                 $oShape = $oLayer->getShape($nTile, 0 );
182                 $aszAttributes['name'] = $oLayer->name;
183                 $aszAttributes['index'] = $oLayer->index;
184                 $oRect = $oShape->bounds;
185                 $aszAttributes['minx'] = $oRect->minx;
186                 $aszAttributes['miny'] = $oRect->miny;
187                 $aszAttributes['maxx'] = $oRect->maxx;
188                 $aszAttributes['maxy'] = $oRect->maxy;
189                 
190                 foreach($oShape->values as $key => $value)
191                 {
192                     $aszAttributes['fields'][$key] = "string";
193                 }
194                 break;           
195         }
196     }
197     
198     return $aszAttributes;
199 }
200
201 /**
202  * GetLayerFeatures()
203  *
204  * Postcondition:  This function returns a two dimensional array of layer
205  *                 feature values for either WMS or WFS layers.
206  *
207  * @param $oMap Object - The map object to use.
208  * @param $oLayer Object - The layer object to use.
209  * @param $aszIncludeAttributes Array - Optional list of attribute names to use.
210  * @return Array - Two dimensional array of features.
211  * @desc Returns 2-D array of features.
212  */
213 function GetLayerFeatures( $oMap, $oLayer, $aszIncludeAttributes = array() )
214 {
215     // init vars
216     $aszFeatures = array();
217     $szLayerName = $oLayer->name;
218     $szWFSTypeName = '';
219     if ( $oLayer->connectiontype == MS_WMS )
220     {
221         // get the layer name from metadata if possible to avoid the problems
222         // with context layers being renamed
223         $szLayerName = $oLayer->getMetaData( "wms_name" );
224         if ($szLayerName == "")
225             $szLayerName = $oLayer->name;
226             
227         // get WFS the connection string
228         $aszInfo = getWFSConnection( $oLayer->connection, $szLayerName );
229         $szWFSConnection = $aszInfo['wfs'];
230         
231         // loop and build typename
232         if ( isset( $aszInfo['typename'] )  && is_array( $aszInfo['typename'] ) )
233         {
234                     
235             foreach( $aszInfo['typename'] as $szTypeName )
236             {
237                 $szWFSTypeName .= $szTypeName.',';
238             }
239         }
240         
241         // remove trailing ','
242         if ( substr( $szWFSTypeName, -1, 1 ) == ',' )
243         {
244             $szWFSTypeName = substr( $szWFSTypeName, 0, -1 );
245         }       
246
247         // can only process WMS layer if WFS connection is associated
248         if ( $szWFSConnection != "" )
249         {
250             // fix WFS url as required
251             $szWFSConnection = fixWFSURL( $szWFSConnection, $szWFSTypeName );
252             
253             // get the attribute types
254             $aszAttributes = getAttributeTypes( $szWFSConnection.
255                                   'request=describefeaturetype', $szLayerName );
256         
257             // build list of attrtibutes
258             $szLayerType = '';
259             foreach( $aszAttributes as $key=>$value )
260             {
261                 // get layer type
262                 if ( $key == 'LayerType' )
263                 {
264                     $szLayerType = $value;
265                     break;
266                 }           
267             }
268             
269             // duplicate the layer
270             $oCloneLayer = ms_newLayerObj( $oMap, $oLayer );
271             
272             // reset orig layer name temporarily
273             $oLayer->set( 'name', $oLayer->name.'tmp_backup' );
274
275             // if layer type is WMS then convert to WFS
276             $oCloneLayer->set( 'connectiontype', MS_WFS );
277             $oCloneLayer->set( 'connection', $szWFSConnection.'&ttt=1' );
278             $oCloneLayer->set( 'type', $szLayerType );
279         }
280         else
281         {
282             // no associated WFS layer so return empty
283             return array();
284         }
285     }
286     /*
287     we can really do this on any layer that isn't WMS
288     elseif ( $oLayer->connectiontype != MS_WFS )
289     {
290         // return empty array because not WMS or WFS
291         echo "here3<br>";
292         echo $oLayer->connectiontype."<BR>";
293         return array();
294     }
295     */
296
297     //we want to get all the features for the whole world here
298     //but this may not be the case in general so this may need
299     //to be redone to accomodate querying the current map extents
300     //as an option
301     /*
302     //this is supposed to be the optimized version and would remove the
303     //parseFeatures function, which would be quite slow compared to this,
304     //at least that's what we hope!
305     $oRect = ms_newRectObj();
306     $oRect->setExtent( 10000, 305000, 280000, 619000);
307
308     //if the layer or map has a projection then convert our
309     //lat/lon into that projection before querying
310
311     $szProjOut = $oLayer->getProjection();
312     if ($szProjOut == "")
313     {
314         $szProjOut = $oMap->getProjection();
315     }
316     if ($szProjOut != "")
317     {
318         $oProjIn = ms_newProjectionObj( "init=epsg:4326" );
319         $oProjOut = ms_newProjectionObj( $szProjOut );
320         $oRect->project( $oProjIn, $oProjOut );
321     }
322     print_r($oRect);
323     //at this point, $oRect should have the right things in it
324     $nResults = 0;
325     if (isset($oCloneLayer))
326     {
327         $oCloneLayer->set("template", "blah");
328         $oCloneLayer->queryByRect($oRect);
329         $nResults = $oCloneLayer->getNumResults();
330     }
331     else
332     {
333         $oLayer->set("template", "blah");
334         $oLayer->queryByRect($oRect);
335         $nResults = $oLayer->getNumResults();
336     }
337     
338     if ($nResults > 0)
339     {
340         $oLayer->open();
341         for( $i=0; $i<$nResults; $i++ )
342         {
343             $oResult = $oLayer->getResult($i);
344             $oShape = $oLayer->getShape($oResult->tileindex, $oResult->shapeindex);
345             array_push( $aszFeatures, $oShape->values );
346         }
347         $oLayer->close();
348     }
349     
350     */
351     // debug
352     //$szTmpGML = getGML( $szWFSConnection.'request=getfeature' );
353     
354     // create the gml file to parse into an array
355     $szTmpGML = !isset( $oCloneLayer ) ? $oLayer->executeWFSGetfeature() :
356                                       $oCloneLayer->executeWFSGetfeature();
357                                       
358     // check if the file exists
359     if ( file_exists( $szTmpGML ) )
360     {
361         // read the file, parse it and return it as an array
362        $aszFeatures = parseFeatures( $szTmpGML, $szLayerName,
363                                                         $aszIncludeAttributes );
364       
365         // delete the file
366         unlink( $szTmpGML );
367     }   
368     /**/
369     
370     // delete cloned layer if necessary
371     if ( isset( $oCloneLayer ) )
372     {
373         // restore current layers name
374         $oLayer->set( 'name', substr( $oLayer->name, 0, -10 ) );
375         //$oCloneLayer->set( 'status', MS_DELETE );
376     }
377     
378     // return the features
379     return $aszFeatures;
380 }
381
382 /*
383  * return the SRS value (ESPG:xxxx) for a given layer in a WFS server
384  * by grabbing the capabilities of the server, then looking for any
385  * SRS tag (since all layers are in the same SRS :)
386  */
387 function getWFSSRS( $szXmlUrl )
388 {
389     // read the xml datasource
390     if (function_exists( 'file_get_contents' ))
391     {
392         $data = file_get_contents( $szXmlUrl );
393     }
394     else
395     {
396         $data = implode( '', file($szXmlUrl) );
397     }
398     
399     if ( stristr( $data, '<SERVICEEXCEPTIONREPORT' ) !== false )
400         return "";
401     
402     // parse
403     $parser = xml_parser_create();
404     xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0);
405     xml_parser_set_option($parser,XML_OPTION_SKIP_WHITE,1);
406     xml_parse_into_struct($parser,$data,$values,$tags);
407     xml_parser_free($parser);
408
409     return $values[$tags['SRS'][0]]['value'];
410 }
411
412 /**
413  * getAttributeTypes()
414  *
415  * Postcondition:  This function processes the given XML file returns an array
416  *                 of attribute names and types.
417  *
418  * @param $szXmlUrl string - URL to the XML document to parse.
419  * @return mixed - Array of results or a string of the server error results.
420  * @desc Reads XML datasource and returns array of att->type pairs.
421  */
422 function getAttributeTypes( $szXmlUrl, $szLayerName )
423 {
424     // int vars
425     $data = "";
426     $axReturn = "";
427     
428     // read the xml datasource
429     $aszFile = file( $szXmlUrl );
430
431     // combine results
432     if ( is_array( $aszFile ) )
433     {
434         foreach( $aszFile as $line )
435             $data .= $line;
436     }
437
438     // check to see if an error was generated
439     if ( !is_array( $aszFile ) ||
440          strpos( strtoupper( $data ), '<SERVICEEXCEPTIONREPORT' ) !== false )
441         return array();
442     
443     // parse
444     $parser = xml_parser_create();
445     xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0);
446     xml_parser_set_option($parser,XML_OPTION_SKIP_WHITE,1);
447     xml_parse_into_struct($parser,$data,$values,$tags);
448     xml_parser_free($parser);
449
450     // loop through the structures and process the SEQUENCE
451     foreach ($tags as $key=>$val)
452     {
453         // process ROWSET
454         if (strtoupper( $key ) == "SEQUENCE")
455         {
456             $ranges = $val;
457             // each contiguous pair of array entries are the
458             // lower and upper range for each SEQUENCE definition
459             $nCount = count($ranges);         
460             for ($i=0; $i < $nCount; $i+=2)
461             {
462                 $offset = $ranges[$i] + 1;
463                 $len = $ranges[$i + 1] - $offset;
464                 $axReturn = parseElements( array_slice($values, $offset, $len) );
465             }
466         }
467         else
468         {
469             // otherwise skip
470             continue;
471         }
472     }
473     
474     // return
475     return $axReturn;
476     
477 // end getAttributeTypes() function   
478 }
479
480 /**
481  * parseElements()
482  *
483  * Postcondition:  This function parses the given array returns an array of
484  *                 attribute->type pairs.
485  *
486  * @param axValues Array - Mixed array of XML tags to process.
487  * @return array - Array of att->type pairs if successful or empty array if not.
488  * @desc Parses array and returns array of att->type pairs.
489  */
490 function parseElements( $axValues )
491 {   
492     // init vars
493     $aszReturn = array();
494     
495     // loop through each item of the array
496     $nCount = count( $axValues );
497     for ( $i=0; $i < $nCount; $i++ )
498     {
499         // only process "name" and "type" values
500         if ( strtoupper( $axValues[$i]["tag"] ) == "ELEMENT" )
501         {
502             // add to array
503             if ( isset(  $axValues[$i]["attributes"]["name"] ) &&
504                  $axValues[$i]["attributes"]["type"] )
505             {
506                $aszReturn[$axValues[$i]["attributes"]["name"]] =
507                                             $axValues[$i]["attributes"]["type"];
508             }
509             
510             // check for the layer type
511             $szLayerType = '';
512             if ( isset( $axValues[$i]["attributes"]["ref"] ) )
513                 $szLayerType = strtoupper( $axValues[$i]["attributes"]["ref"] );
514             elseif ( isset( $axValues[$i]["attributes"]["type"] ) &&
515                      strtoupper( substr( $axValues[$i]["attributes"]["type"], 0, 4 ) ) == 'GML:' )
516                 $szLayerType = strtoupper( $axValues[$i]["attributes"]["type"] );
517             
518             // check for the type
519             if (  strlen( $szLayerType ) > 0 )
520             {
521                 // check if poly
522                 if ( strpos( $szLayerType, 'POLYGON' ) !== false )
523                     $aszReturn['LayerType'] = 'MS_LAYER_POLYGON';
524                 elseif ( strpos( $szLayerType, 'BOX' ) !== false )
525                     $aszReturn['LayerType'] = 'MS_LAYER_POLYGON';                   
526                 elseif ( strpos( $szLayerType, 'LINE' ) !== false )
527                     $aszReturn['LayerType'] = 'MS_LAYER_LINE';
528                 elseif ( strpos( $szLayerType, 'POINT' ) !== false )
529                     $aszReturn['LayerType'] = 'MS_LAYER_POINT';                   
530             }
531         }
532     }
533     
534     // return array
535     return $aszReturn;
536     
537 // end parseElements() function
538 }
539
540 /**
541  * getWFSConnection()
542  *
543  * Postscript:  This function reads the given WMS connection and returns the WFS
544  *              online resource.
545  *
546  * @param $szWMSConnection string - WMS connection string.
547  * @return string - WFS online resource if successful, false if failed.
548  * @desc Parses given connection string and returns WFS online resource.
549  */
550 function getWFSConnection( $szWMSConnection, $szSelectedLayerName )
551 {
552     // get the url to perform a describelayer on
553     $szUpperCase = strtoupper( $szWMSConnection );
554
555     // check last char for ? or &
556     if ( substr( $szWMSConnection, -1 ) != "?" &&
557          substr( $szWMSConnection, -1 ) != "&" )
558     {
559         // check for ?
560         if ( strpos( $szWMSConnection, "?" ) === false )
561         {
562             $szWMSConnection .= "?";
563         }
564         else
565             $szWMSConnection .= "&";
566     }
567
568     // check for and add VERSION
569     if ( strpos( $szUpperCase, "VERSION=" ) === false )
570         $szWMSConnection .= "VERSION=1.1.0&";
571
572     // check for and add SERVICE
573     if ( strpos( $szUpperCase, "SERVICE=" ) === false )
574         $szWMSConnection .= "SERVICE=WMS&";
575
576     // add LAYERS
577     if ( strpos( $szUpperCase, "LAYERS=" ) ===  false )
578         $szWMSConnection .= "LAYERS=".$szSelectedLayerName."&";
579
580     // add REQUEST
581     $szWMSConnection .= "REQUEST=DESCRIBELAYER";
582     //echo "wms connection = $szWMSConnection<BR>";
583     
584     // perform a describe layer and return
585     return getWFSResource( $szWMSConnection );
586     
587 // end getWFSConnection function
588 }
589
590 /**
591  * getWFSResource()
592  *
593  * Postscript:  This function reads the given url and returns the WFS online
594  *              resource.
595  *
596  * @param $szURL string - URL to the GML source.
597  * @return string - WFS online resource if successful, false if failed.
598  * @desc Parses given url and returns WFS online resource.
599  */
600 function getWFSResource( $szURL )
601 {
602     // init vars
603     $data = "";
604     $aszReturn = array( 'wfs'=>'', 'typename'=>array() );
605
606     // read the xml datasource   
607     if (!function_exists('file_get_contents'))
608     {
609         $szXMLFile = implode( "", file($szURL) );
610     }
611     else
612     {
613         $szXMLFile = file_get_contents( $szURL );
614     }
615
616     // check to see if an error was generated
617     if ( strpos( strtoupper( $szXMLFile ), '<SERVICEEXCEPTIONREPORT' ) !== false )
618     {
619         return false;
620     }
621
622     // setup the xml parser and parse the file
623     $parser = xml_parser_create();
624     xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
625     xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE,   1);
626     xml_parse_into_struct($parser, $szXMLFile, $aVals, $index);
627     xml_parser_free($parser);
628     
629     // make all keys case insensitive
630     $aVals = lowercaseArrayKeys( $aVals );
631
632     // loop through the results and parse out:
633     // 1) wfs attribute
634     // 2) all query typename values
635     $nCount = count( $aVals );
636     for( $i=0; $i<$nCount; $i++ )
637     {
638         // check wfs
639         if ( strtolower( $aVals[$i]['tag'] ) == 'layerdescription' &&
640              isset( $aVals[$i]['attributes']['wfs'] ) )
641         {
642             $aszReturn['wfs'] = $aVals[$i]['attributes']['wfs'];
643         }
644         
645         // check for query typename
646         if ( strtolower( $aVals[$i]['tag'] ) == 'query' )
647         {
648             array_push( $aszReturn['typename'],
649                                             $aVals[$i]['attributes']['typename'] );
650         }
651     }
652
653     // return values
654     return $aszReturn;
655
656 // end getWFSResource function
657 }
658
659
660 /**
661  * fixWFSURL()
662  *
663  * Postscript:  This function adds any missing WFS parameters to a WFS connection.
664  *
665  * @param $szConnection string - Connection string.
666  * @param $szWFSTypeName string -  typename to add.
667  * @return string - The updated url.
668  * @desc Checks given WFS connection and adds the necessary parameters.
669  */
670 function fixWFSURL( $szConnection, $szWFSTypeName )
671 {
672     // convert the url to uppercase
673     $szUpperCase = strtoupper( $szConnection );
674     
675     // check last char for ? or &
676     if ( substr( $szConnection, -1 ) != "?" &&
677          substr( $szConnection, -1 ) != "&" )
678     {
679         // check for ?
680         if ( strpos( $szConnection, "?" ) === false )
681         {
682             $szConnection .= "?";
683         }
684         else
685             $szConnection .= "&";
686     }   
687     
688     // check for and add VERSION
689     if ( strpos( $szUpperCase, "VERSION=" ) === false )
690         $szConnection .= "VERSION=1.0.0&";
691
692     // check for and add SERVICE
693     if ( strpos( $szUpperCase, "SERVICE=" ) === false )
694         $szConnection .= "SERVICE=WFS&";
695
696     // add TYPENAME
697     if ( strpos( $szUpperCase, "TYPENAME=" ) ===  false )
698         $szConnection .= "TYPENAME=".$szWFSTypeName."&";
699     
700     // return
701     return $szConnection;
702
703 // end fixWFSURL function
704 }
705
706 /**
707  * lowercaseKeys()
708  *
709  * Postcondition:  This function takes the given array and converts all keys
710                    to lowercase.
711  *
712  * @param axConvert string - Array to convert.
713  * @return array - Converted array.
714  * @desc Converts all keys in an array to lowercase.
715  */
716 function lowercaseArrayKeys( $axConvert )
717 {
718     // init vars
719     $axReturn = array();
720     
721     // recusively loop
722     $i=0;
723     foreach( $axConvert as $key=>$value )
724     {
725         // check for array
726         if ( is_array( $value ) )
727         {
728             $value = lowercaseArrayKeys( $value );
729         }
730         
731         // add item to the new array
732         $axReturn[strtolower( $key )] = $value;
733         
734         // sanity check
735         $i++;
736         if ( $i >= 1000000 )
737         {
738             die('Error in lowercaseArrayKeys() 1,000,000 entries was exceeded');
739         }
740     }
741     
742     // return
743     return $axReturn;
744 }
745
746 /**
747  * parseFeatures()
748  *
749  * Postcondition:  This function reads the give and parses it, passing
750  *                 the results to an array.
751  * Precondition:   This function assumes the shared resource exists.
752  *
753  * @param $szFile string - The file to parse.
754  * @param $szLayer string - Layer to parse.
755  * @param $aszAttributes array - list of attributes to return.
756  * @return boolean - true if successful, false if not;
757  * @desc Reads and parses given file and passes results to an array.
758  *
759  **/   
760 function parseFeatures( $szFile, $szLayer, $aszAttributes = array() )
761 {
762     // int vars
763     $data = "";
764     $aszReturn = array();
765     
766     // read the xml datasource
767     /*
768     if ( function_exists( 'file_get_contents' ) )
769     {
770         // read the file to string
771         $data = file_get_contents( $szFile );
772     }
773     else
774     {
775         // read the file to string
776         $aszFile = file( $szFile );
777         foreach( $aszFile as $line )
778         {       
779             // process line
780             $data .= $line;
781         }
782     }
783     */
784     //copy( $szFile, "c:\\test.xml" );
785     $h = fopen($szFile, "r");
786     $loop = 0;
787     do
788     {
789         $line = fread( $h, 1024 );
790         if (strlen($line) == 0)
791             break;
792             
793         $data .= $line;
794         
795         $loop ++;
796         if ($loop > 100000) break;
797     }
798     while(true);
799     //echo "loop: $loop<BR>";
800     //echo "szFile : $szFile<BR>\n";
801     //echo "data :<BR>\n";
802     //echo htmlentities($data);
803     
804     
805     // check to see if an error was generated
806     if ( strpos( strtoupper( $data ), '<SERVICEEXCEPTIONREPORT' ) !== false )
807     {
808         return array();
809     }
810
811     // parse
812     $parser = xml_parser_create();
813     xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0);
814     xml_parser_set_option($parser,XML_OPTION_SKIP_WHITE,1);
815     xml_parse_into_struct($parser,$data,$values,$tags);
816     xml_parser_free($parser);
817
818     // loop through the structures and process the layer name
819     foreach ($tags as $key=>$val)
820     {
821         // process layer name
822         if ( strtoupper( $key ) == strtoupper( $szLayer ) )
823         {
824             $ranges = $val;
825             // each contiguous pair of array entries are the
826             // lower and upper range for each layer definition
827             $nCount = count($ranges);         
828             for ($i=0; $i < $nCount; $i+=2)
829             {
830                 if (isset($ranges[$i+1]))
831                 {
832                     $offset = $ranges[$i] + 1;
833                     $len = $ranges[$i + 1] - $offset;
834                     $axTmp = parseFeatureElements(
835                        array_slice($values, $offset, $len ), $szLayer, $aszAttributes );
836                     $aszReturn = array_merge( $aszReturn, $axTmp );             
837                 }
838             }
839         }
840         else
841         {
842             // otherwise skip
843             continue;
844         }
845     }
846     
847     // return
848     return $aszReturn;
849     
850 // end parseQueryResults
851 }
852     
853 /**
854  * parseFeatureElements()
855  *
856  * Postcondition:  This function parses the given array returns an array of
857  *                 values.
858  *
859  * @param axValues Array - Mixed array of XML tags to process.
860  * @param szLayer String - Layer name.
861  * @param $aszAttributes Array - List of layers to return.
862  * @return Array - Array of values.
863  * @desc Parses array and returns in an array.
864  */
865 function parseFeatureElements( $axValues, $szLayer, $aszAttributes = array() )
866 {   
867     // init vars
868     $axReturn = array();
869     $bAllowAll = ( count( $aszAttributes ) <= 0 ) ? true:false;
870
871     // loop through each item of the array
872     $aResult = array();
873     $nCount = count( $axValues );
874     $j = 0;
875     for ( $i=0; $i < $nCount; $i++ )
876     {
877         //echo "processing count $i<BR>";
878         // only process all non "gml..." values
879         if ( strtoupper( substr( $axValues[$i]["tag"], 0, 3 ) ) != "GML" )
880         {
881             // only add attributes that are in the list
882             if ( $bAllowAll || in_array( $axValues[$i]['tag'], $aszAttributes ) )
883                 {
884                 // add to array
885                 //$aResult[$j]['attribute'] = $axValues[$i]['tag'];
886                 if ( isset( $axValues[$i]['value'] ) )
887                 {
888                     //$aResult[$j]['value'] = $axValues[$i]['value'];
889                     $aResult[$axValues[$i]['tag']] = $axValues[$i]['value'];
890                 }
891                 else
892                 {
893                     $aResult[$axValues[$i]['tag']] = '';
894                 }
895                 $j++;
896             }
897         }
898     }
899     array_push( $axReturn, $aResult );
900     
901     // return
902     return $axReturn;
903     
904 // end parseElements() function
905 }
906
907
908 function getGML( $szURL )
909 {
910     // build temp file
911     $szTmpFile = $_SESSION['gszTmpPath'].md5(uniqid(rand(), true)).'.gml';
912     
913     // read the xml datasource
914     $aszFile = file( $szURL );
915
916     // check to see if an error was generated
917     if ( !is_array( $aszFile ) ||
918          strpos( strtoupper( $aszFile[0] ), '<SERVICEEXCEPTIONREPORT' ) !== false )
919     {
920         // give error
921         if ( !is_array( $aszFile ) )
922             $szServerDump = $aszFile;
923         else
924         {
925             $szServerDump = "";
926             foreach(  $aszFile as $line )
927                 $szServerDump .= $line;
928         }
929
930         // return
931         return 'Error';
932     }
933
934     // open the tmp file for writing
935     if ( !( $fp = fopen( $szTmpFile, "w" ) ) )
936     {
937         // open failed so give error
938         return 'Error';
939     }
940
941     // process url
942     foreach( $aszFile as $line )
943     {
944         // write entry to file
945         fputs($fp, $line."\n");
946     }
947
948     // close the file
949     fclose($fp);
950
951     // return true
952     return $szTmpFile;
953 }
954
955
956 ?>
Note: See TracBrowser for help on using the browser.