wmsId = $wmsId; $this->uploadId = $uploadId; $this->autoUpdate = $autoUpdate; $this->capabilitiesURL = $this->getUploadURL($this->wmsId, $this->uploadId); set_time_limit(TIME_LIMIT); $this->timestamp = time(); if ($this->capabilitiesURL) { $remoteWms = new wms(); $remoteWms->createObjFromXML($this->capabilitiesURL); $this->remoteXML = $remoteWms->wms_getcapabilities_doc; $this->localXML = $this->getCapabilitiesDocByWMS($this->wmsId); // service unreachable if (!$this->remoteXML) { $this->result = -1; $this->comment = "Connection failed."; } /* * service available; * no local copy of capabilities file, * so it has to be updated anyway */ elseif (!$this->localXML) { $this->result = 0; } /* * service available; * check if local copy is different * to remote capabilties document */ else { /* * compare to local capabilities document */ // capabilities files match if ($this->localXML == $this->remoteXML) { $this->result = 1; $this->comment = "WMS is stable."; } // capabilities files don't match else { $this->result = 0; $localXMLArray = explode("\n", htmlentities($this->localXML)); $remoteXMLArray = explode("\n", htmlentities($this->remoteXML)); $this->capabilitiesDiff = $this->outputDiffHtml($localXMLArray,$remoteXMLArray); } } /* * if the WMS is available, * 1) get a map image * 2) update the local backup of the capabilities doc if necessary */ if ($this->result != -1) { $this->mapURL = $this->getMapRequest($this->wmsId); if ($this->isImage($this->mapURL)) { $this->returnsImage = 1; } else { $this->returnsImage = -1; } /* * if the local backup of the capabilities document * is deprecated, update the local backup */ if ($this->result == 0) { $mywms = new wms(); /* * if the capabilities document is valid, * update it OR mark it as "not up to date" */ if ($mywms->createObjFromXML($this->capabilitiesURL)) { if ($this->autoUpdate) { $mywms->updateObjInDB($this->wmsId); $this->updated = "1"; $this->comment = "WMS has been updated."; } else { $this->comment = "WMS is not up to date."; } } // capabilities document is invalid else { $this->result = -1; $this->comment = "Invalid getCapabilities request/document or service exception."; } } } } else { $this->result = -1; $this->comment = "Invalid upload URL."; } $e = new mb_notice("class_monitor: constructor: result = " . $this->result); $e = new mb_notice("class_monitor: constructor: comment = " . $this->comment); $e = new mb_notice("class_monitor: constructor: returnsImage = " . $this->returnsImage); } /** * */ public function __toString() { $str = ""; $str .= "wmsid: " . $this->wmsId . "\nupload_id: " . $this->uploadId . "\n"; $str .= "autoupdate: " . $this->autoUpdate . "\n"; $str .= "result: " . $this->result . "\ncomment: " . $this->comment . "\n"; $str .= "timestamp: " . $this->timestamp . " (".date("F j, Y, G:i:s", $this->timestamp).")\n"; $str .= "getCapabilities URL: " . $this->capabilitiesURL . "\nupdated: " . $this->updated . "\n\n"; $str .= "getMap URL: " . $this->mapURL . "\nis image: " . $this->returnsImage . "\n\n"; $str .= "-------------------------------------------------------------------\n"; $str .= "remote XML:\n\n" . $this->remoteXML . "\n\n"; $str .= "-------------------------------------------------------------------\n"; $str .= "local XML:\n\n" . $this->localXML . "\n\n"; $str .= "-------------------------------------------------------------------\n"; $str .= "diff:\n\n" . $this->capabilitiesDiff . "\n\n"; $str .= "-------------------------------------------------------------------\n"; return (string) $str; } /** * Update database */ function updateInDB() { $sql = "UPDATE mb_monitor SET updated = $1, status = $2, image = $3, status_comment = $4, upload_url = $5, timestamp_end = $6, map_url = $7, timestamp_begin = $8, caps_diff = $9 WHERE upload_id = $10 AND fkey_wms_id = $11"; $v = array($this->updated, $this->result, $this->returnsImage, $this->comment, $this->capabilitiesURL, time(), $this->mapURL, $this->timestamp, $this->capabilitiesDiff, $this->uploadId, $this->wmsId); $t = array('s', 'i', 'i', 's', 's', 's', 's', 's', 's', 's', 'i'); $res = db_prep_query($sql,$v,$t); } /* * Checks if the mapUrl returns an image or an exception */ private function isImage($url) { $headers = get_headers($url, 1); $e = new mb_notice("class_monitor: isImage: map URL is " . $url); $e = new mb_notice("class_monitor: isImage: Content-Type is " . $headers["Content-Type"]); if (preg_match("/xml/", $headers["Content-Type"])) { return false; } return true; } /** * Returns the upload url of some WMS */ private function getUploadURL($wmsId, $upload_id) { $e = new mb_notice("class_monitor: getUploadURL: wms = " . $wmsId); $e = new mb_notice("class_monitor: getUploadURL: upload_id = " . $upload_id); $sql = "SELECT upload_url FROM mb_monitor WHERE fkey_wms_id = $1 AND upload_id = $2"; $v = array($wmsId, $upload_id); $t = array('i', 'i'); $res = db_prep_query($sql,$v,$t); $someArray = db_fetch_array($res); $e = new mb_notice("class_monitor: getUploadURL: url = " . $someArray["upload_url"]); return $someArray["upload_url"]; } /** * Returns the character that needs to be appended to * a given online resource, in order to append other GET * parameters. * * Possible characters: "?", "&", "" */ private function mb_getConjunctionCharacter($onlineresource){ // index of character ? in online resource $indexOfChar = mb_strpos($onlineresource,"?"); if($indexOfChar) { // no conjunction character needed if($indexOfChar == mb_strlen($onlineresource)-1){ return ""; } // no conjunction character needed else if (mb_substr($onlineresource, mb_strlen($onlineresource)-1) == "&") { return ""; } else{ return "&"; } } return "?"; } /** * retrieves all information necessary to build a map request, * concatenates them and returns a valid get map request */ private function getMapRequest($wmsId) { // get map (wms_getmap) // version (wms_version) $sql = "SELECT wms_getmap, wms_version FROM wms WHERE wms_id = $1"; $res = db_prep_query($sql, array($wmsId), array('i')); $row = db_fetch_array($res); $getmap = $row["wms_getmap"]; $version = $row["wms_version"]; //map format $sql = "SELECT * FROM wms_format WHERE data_type = 'map' AND fkey_wms_id = $1"; $res = db_prep_query($sql, array($wmsId), array('i')); $row = db_fetch_array($res); $mapFormat = ""; while ($row = db_fetch_array($res)) { $mapFormat = urlencode($row["data_format"]); if (preg_match("/png/", $mapFormat) || preg_match("/gif/", $mapFormat) || preg_match("/jp.{1}g/", $mapFormat)) { break; } } // layers (all layers) $sql = "SELECT layer_name FROM layer WHERE fkey_wms_id = $1 AND layer_parent <> '' AND layer_pos > 0"; $res = db_prep_query($sql, array($wmsId), array('i')); $layerArray = array(); while ($row = db_fetch_array($res)) { array_push($layerArray, urlencode($row["layer_name"])); } $layerList = implode(",", $layerArray); // srs (layer_epsg: epsg) // bbox (layer_epsg: minx, miny, maxx, maxy) $sql = "SELECT epsg, minx, miny, maxx, maxy "; $sql .= "FROM layer_epsg, (SELECT fkey_wms_id, layer_id FROM layer WHERE fkey_wms_id = $1 AND layer_parent = '' AND layer_pos = 0) AS l "; $sql .= "WHERE l.layer_id = layer_epsg.fkey_layer_id AND l.fkey_wms_id = $1"; $res = db_prep_query($sql, array($wmsId), array('i')); $bboxArray = array(); while ($row = db_fetch_array($res)) { array_push($bboxArray, new Mapbender_bbox($row["minx"], $row["miny"], $row["maxx"], $row["maxy"], $row["epsg"])); } // get a bbox in a preferably non WGS84 epsg to use the scalehints for ($i=0; $i < count($bboxArray); $i++) { $bbox = $bboxArray[$i]; if ($bboxArray[$i]->epsg != "EPSG:4326") { break; } } /* * transform to 31466 if is 4326 * TODO: extend to other EPSG apart from 31466 */ if ($bbox->epsg == "EPSG:4326") { $bbox->transform("EPSG:31466"); } /* * get map and check if result is image */ // check if this WMS supports exception type XML $sql = "SELECT data_format FROM wms_format WHERE fkey_wms_id = $1 AND data_type = 'exception'"; $v = array($wmsId); $t = array('i'); $res = db_prep_query($sql,$v,$t); while ($row = db_fetch_array($res)) { $exceptionFormat = $row["data_format"]; // set the exception type to xml (if possible) if (preg_match('/xml/', $exceptionFormat)) { $this->supportsXMLException = true; break; } } // correct bbox according to scale $scale = $this->getScaleForWMS($wmsId); $bbox = $this->getBBoxInScale($bbox, $scale); return $this->concatenateMapRequest($getmap, $version, $mapFormat, $layerList, $bbox, MONITOR_IMG_WIDTH, MONITOR_IMG_HEIGHT, $exceptionFormat); } /** * updates a given BBox according to a given scale * * @param bbox * @param scale */ private function getBBoxInScale($bbox, $scale) { $e = new mb_notice("class_monitor: getMapRequest: old bbox = " . $bbox); $e = new mb_notice("class_monitor: getMapRequest: old bbox = " . $bbox->min->x . "," . $bbox->min->y . "," . $bbox->max->x . "," . $bbox->max->y); $e = new mb_notice("class_monitor: getMapRequest: scale = " . $scale); if ($scale) { $center = $bbox->min->plus($bbox->max)->times(0.5); $e = new mb_notice("class_monitor: getMapRequest: center = " . $center); /* * TODO: this formula should have documentation */ $offset = MONITOR_IMG_WIDTH / (MB_RESOLUTION * 100 * 2) * $scale; $offsetPoint = new Mapbender_point($offset, $offset, $bbox->epsg); $min = $center->minus($offsetPoint); $max = $center->plus($offsetPoint); $bbox->min = $min; $bbox->max = $max; $e = new mb_notice("class_monitor: getMapRequest: new bbox = " . $bbox); $e = new mb_notice("class_monitor: getMapRequest: new bbox = " . $bbox->min->x . "," . $bbox->min->y . "," . $bbox->max->x . "," . $bbox->max->y); } return $bbox; } /** * Returns an online resource representing a get map request */ private function concatenateMapRequest( $getmap, $wmsVersion, $mapFormat, $layerList, $bbox, $width, $height, $exceptionFormat) { /* * getMap URL */ $mapRequest = $getmap; $mapRequest .= $this->mb_getConjunctionCharacter($getmap); /* * WMS version */ if ($wmsVersion == "1.0.0") { $mapRequest .= "WMTVER=" . $wmsVersion . "&REQUEST=map&"; } else { $mapRequest .= "VERSION=" . $wmsVersion . "&REQUEST=GetMap&SERVICE=WMS&"; } /* * Layer list */ $mapRequest .= "LAYERS=" . $layerList . "&"; /* * Format */ $mapRequest .= "FORMAT=" . $mapFormat . "&"; /* * SRS and BBox */ $mapRequest .= "SRS=" . $bbox->epsg . "&"; $mapRequest .= "BBOX=" . $bbox->min->x . "," . $bbox->min->y . "," . $bbox->max->x . "," . $bbox->max->y . "&"; /* * Width and height */ $mapRequest .= "WIDTH=" . $width . "&"; $mapRequest .= "HEIGHT=" . $height . "&"; /* * BGColor */ $mapRequest .= "BGCOLOR=0xffffff&"; /* * Transparency */ if (preg_match("/png/", $mapFormat) || preg_match("/gif/", $mapFormat)) { $mapRequest .= "TRANSPARENT=TRUE&"; } /* * Exception format */ $mapRequest .= "EXCEPTIONS=" . $exceptionFormat . "&"; // return urlencode($mapRequest); return $mapRequest; } /** * Checks if the given WMS has ScaleHints. If yes, a scale is selected and returned. */ private function getScaleForWMS($wmsId) { // get the scalehints $sql = "SELECT layer_minscale, layer_maxscale FROM layer WHERE fkey_wms_id = $1 AND layer_pos = 0 AND layer_parent = '' AND layer_minscale <> layer_maxscale LIMIT 1"; $v = array($wmsId); $t = array('i'); $res = db_prep_query($sql,$v,$t); $scaleHintArray = db_fetch_array($res); /* * determine the scalehint */ // if a scalehint exists if ($scaleHintArray) { // if upper boundary if ($scaleHintArray["layer_minscale"] < $scaleHintArray["layer_maxscale"]) { // TODO: find a better algorithm with a less obscure scale $scaleHint = round($scaleHintArray["layer_maxscale"] - $scaleHintArray["layer_minscale"]) / 2; } // if lower boundary else { if ($scaleHintArray["layer_minscale"] < MONITOR_DEFAULT_SCALE) { $scaleHint = MONITOR_DEFAULT_SCALE; } else { // TODO: find a better algorithm with a less obscure scale $scaleHint = $scaleHintArray["layer_minscale"] + 1000; } } } // otherwise, use a default value else { $scaleHint = MONITOR_DEFAULT_SCALE; } return $scaleHint; } /** * Returns the local backup of the given WMS' capabilities document */ private function getCapabilitiesDocByWMS($wmsId) { $sql = "SELECT wms_getcapabilities_doc FROM wms WHERE wms_id = $1"; $v = array($wmsId); $t = array('i'); $res = db_prep_query($sql,$v,$t); $someArray = db_fetch_array($res); return $someArray["wms_getcapabilities_doc"]; } /* * creates a html diff of the xml documents */ private function outputDiffHtml($localXMLArray,$remoteXMLArray) { $diffObj = new Diff($localXMLArray,$remoteXMLArray); $dft = new TableDiffFormatter(); return $dft->format($diffObj); } } ?>