[Mapbender-commits] r9758 - in trunk/mapbender/http: classes javascripts php

svn_mapbender at osgeo.org svn_mapbender at osgeo.org
Wed Aug 9 01:12:37 PDT 2017


Author: armin11
Date: 2017-08-09 01:12:36 -0700 (Wed, 09 Aug 2017)
New Revision: 9758

Modified:
   trunk/mapbender/http/classes/class_cswClient.php
   trunk/mapbender/http/classes/class_syncCkan.php
   trunk/mapbender/http/javascripts/mod_syncCkan_client.php
   trunk/mapbender/http/php/mod_syncCkan_server.php
Log:
New possibilities to sync mapbender metadata and external csw sources with ckan instances

Modified: trunk/mapbender/http/classes/class_cswClient.php
===================================================================
--- trunk/mapbender/http/classes/class_cswClient.php	2017-08-01 09:54:15 UTC (rev 9757)
+++ trunk/mapbender/http/classes/class_cswClient.php	2017-08-09 08:12:36 UTC (rev 9758)
@@ -29,6 +29,7 @@
 	var $cswId;
 	var $operationName;
 	var $operationResult;
+	var $additionalFilter;
 	//var $operationStatus;
 	var $operationSuccessful;
 	var $operationException;
@@ -41,7 +42,7 @@
 		$this->operationSuccessful = false;
 	}
 	
-	public function doRequest($cswId, $operationName, $recordId=false, $record=false, $recordtype=false, $maxrecords=false, $startposition=false) {
+	public function doRequest($cswId, $operationName, $recordId=false, $record=false, $recordtype=false, $maxrecords=false, $startposition=false, $additionalFilter=false) {
 		$this->cswId = $cswId;
 		$csw = new csw();
 		$csw->createCatObjFromDB($this->cswId);
@@ -152,18 +153,37 @@
 				//wrapped operations for internal usage
 			case "counthits":
 				$postRequest = '<?xml version="1.0" encoding="UTF-8"?>';
-				$postRequest .= '<csw:GetRecords service="CSW" version="2.0.2" xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" xmlns:ogc="http://www.opengis.net/ogc" xmlns:apiso="http://www.opengis.net/cat/csw/apiso/1.0">';
+				//TODO check the following: - resultType="hits" seems to be default behaviour
+				$postRequest .= '<csw:GetRecords service="CSW" version="2.0.2" xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" xmlns:ogc="http://www.opengis.net/ogc" xmlns:apiso="http://www.opengis.net/cat/csw/apiso/1.0" ';					
+				$postRequest .= 'resultType="hits">';
     				$postRequest .= '<csw:Query typeNames="csw:Record">';
-				$postRequest .= '<csw:ElementSetName>summary</csw:ElementSetName>';
+				$postRequest .= '<csw:ElementSetName>full</csw:ElementSetName>'; //full to get all queryables?
 				if ($recordtype !== false) {
             				$postRequest .= '<csw:Constraint version="1.0.0">';
                 			$postRequest .= '<ogc:Filter>';
+					if ($additionalFilter !== false) {
+						$postRequest .= '<ogc:And>';
+					}
                     			$postRequest .= '<ogc:PropertyIsEqualTo>';
                        			$postRequest .= '<ogc:PropertyName>Type</ogc:PropertyName>';
                         		$postRequest .= '<ogc:Literal>'.$recordtype.'</ogc:Literal>';
                     			$postRequest .= '</ogc:PropertyIsEqualTo>';
+					if ($additionalFilter !== false) {
+						$postRequest .= $additionalFilter;
+					}
+					if ($additionalFilter !== false) {
+						$postRequest .= '</ogc:And>';
+					}
                 			$postRequest .= '</ogc:Filter>';
             				$postRequest .= '</csw:Constraint>';
+				} else {
+					if ($additionalFilter !== false) {
+						$postRequest .= '<csw:Constraint version="1.0.0">';
+                				$postRequest .= '<ogc:Filter>';
+						$postRequest .= $additionalFilter;
+						$postRequest .= '</ogc:Filter>';
+            					$postRequest .= '</csw:Constraint>';
+					}
 				}
         			$postRequest .= '</csw:Query>';
     				$postRequest .= '</csw:GetRecords>';
@@ -184,12 +204,29 @@
 					if ($recordtype !== false) {
             					$postRequest .= '<csw:Constraint version="1.0.0">';
                 				$postRequest .= '<ogc:Filter>';
+						if ($additionalFilter !== false) {
+							$postRequest .= '<ogc:And>';
+						}
                     				$postRequest .= '<ogc:PropertyIsEqualTo>';
                        				$postRequest .= ' <ogc:PropertyName>Type</ogc:PropertyName>';
                         			$postRequest .= '<ogc:Literal>'.$recordtype.'</ogc:Literal>';
                     				$postRequest .= '</ogc:PropertyIsEqualTo>';
+						if ($additionalFilter !== false) {
+							$postRequest .= $additionalFilter;
+						}
+						if ($additionalFilter !== false) {
+							$postRequest .= '</ogc:And>';
+						}
                 				$postRequest .= '</ogc:Filter>';
             					$postRequest .= '</csw:Constraint>';
+					} else {
+						if ($additionalFilter !== false) {
+							$postRequest .= '<csw:Constraint version="1.0.0">';
+                					$postRequest .= '<ogc:Filter>';
+							$postRequest .= $additionalFilter;
+							$postRequest .= '</ogc:Filter>';
+            						$postRequest .= '</csw:Constraint>';
+						}
 					}
         				$postRequest .= '</csw:Query>';
     					$postRequest .= '</csw:GetRecords>';				
@@ -203,6 +240,7 @@
 				break;
 			
 		}
+		//$e = new mb_exception("postdata: ".$postRequest);
 		//do request and return result
 		//$e = new mb_exception($csw->cat_op_values[$operationName]['post']);
 		if (strpos($operationNameCsw, "transaction") === false) {
@@ -211,12 +249,12 @@
 		} else {
 			$this->operationResult = $this->getResult($csw->cat_op_values["transaction"]['post'], $postRequest);
 		}
-		//$e = new mb_exception("test: ".$this->operationResult);
+		//$e = new mb_exception("testresponse: ".$this->operationResult);
 		//parse response
 		libxml_use_internal_errors(true);
 		try {
 			$cswResponseObject = simplexml_load_string($this->operationResult);
-			if ($$cswResponseObject === false) {
+			if ($cswResponseObject === false) {
 				foreach(libxml_get_errors() as $error) {
         				$err = new mb_exception("class_cswClient:".$error->message);
     				}
@@ -260,6 +298,8 @@
 							$this->operationSuccessful = true;
 							//return $metadataRecord[0]->asXML();
 							//return "<result>One metadata record with id ".$recordId." found in catalogue</result>";
+							$this->operationResult = $cswResponseObject;
+							//$e = new mb_exception($cswResponseObject->asXML());
 							return true;
 						}
 						break;
@@ -322,7 +362,7 @@
 	}
 
 	private function getResult($url, $postData, $auth=false) {
-			$e = new mb_exception("postdata: ".$postData);
+			//$e = new mb_exception("postdata: ".$postData);
 			$cswInterfaceObject = new connector();
 			$cswInterfaceObject->set('httpType','POST');
 			$postData = stripslashes($postData);

Modified: trunk/mapbender/http/classes/class_syncCkan.php
===================================================================
--- trunk/mapbender/http/classes/class_syncCkan.php	2017-08-01 09:54:15 UTC (rev 9757)
+++ trunk/mapbender/http/classes/class_syncCkan.php	2017-08-09 08:12:36 UTC (rev 9758)
@@ -20,7 +20,9 @@
 require_once(dirname(__FILE__).'/../classes/class_group.php');
 require_once(dirname(__FILE__) . '/../php/mod_getDownloadOptions.php');
 require_once(dirname(__FILE__).'/../../conf/ckan.conf');
-
+//classes for csw handling
+require_once(dirname(__FILE__)."/../classes/class_cswClient.php");
+require_once(dirname(__FILE__)."/../classes/class_csw.php");
 /**
  * Class to provide functions to sync a mapbender metadata repository to a ckan instance, tested with ckan 2.5.3 in 2016
  *
@@ -55,43 +57,95 @@
 	$this->mapbenderUserId = 0;
 	$this->syncOrgaId = 0;
 	$this->topicCkanCategoryMap = $topicCkanCategoryMap; //from ckan.conf
+	//Mapping of DCAT-AP categories to iso topic categories
+	$this->topicDataThemeCategoryMap = $topicDataThemeCategoryMap; //from ckan.conf
 	$this->compareTimestamps = false; //default to update each dataset, because the ckan index for metadata_modified may not be up to date !!!
     }
 
-    //TODO: Following function is only needed til php 5.5 - after upgrade to debian 8 it is obsolet - see also class_iso19139.php!
-    public function array_column(array $input, $columnKey, $indexKey = null) {
-         $array = array();
-         foreach ($input as $value) {
-             if ( !array_key_exists($columnKey, $value)) {
-                 trigger_error("Key \"$columnKey\" does not exist in array");
-                 return false;
-             }
-             if (is_null($indexKey)) {
-                 $array[] = $value[$columnKey];
-             }
-             else {
-                 if ( !array_key_exists($indexKey, $value)) {
-                     trigger_error("Key \"$indexKey\" does not exist in array");
-                     return false;
-                 }
-                 if ( ! is_scalar($value[$indexKey])) {
-                     trigger_error("Key \"$indexKey\" does not contain scalar value");
-                     return false;
-                 }
-                 $array[$value[$indexKey]] = $value[$columnKey];
-             }
-         }
-         return $array;
-     }
+   //TODO: Following function is only needed til php 5.5 - after upgrade to debian 8 it is obsolet - see also class_iso19139.php!
+   public function array_column(array $input, $columnKey, $indexKey = null) {
+        $array = array();
+        foreach ($input as $value) {
+            if ( !array_key_exists($columnKey, $value)) {
+                trigger_error("Key \"$columnKey\" does not exist in array");
+                return false;
+            }
+            if (is_null($indexKey)) {
+                $array[] = $value[$columnKey];
+            }
+            else {
+                if ( !array_key_exists($indexKey, $value)) {
+                    trigger_error("Key \"$indexKey\" does not exist in array");
+                    return false;
+                }
+                if ( ! is_scalar($value[$indexKey])) {
+                    trigger_error("Key \"$indexKey\" does not contain scalar value");
+                    return false;
+                }
+                $array[$value[$indexKey]] = $value[$columnKey];
+            }
+        }
+        return $array;
+    }
 
+    public function getCswRecordList($cswId, $orgaName, $recordType) {
+	//function to call external csw with orga filter (filter orga which is responsible for publication!)
+	$recordsPerPage = 20;
+	$csw = new csw();
+        $csw->createCatObjFromDB($cswId);
+        $cswClient = new cswClient();
+        $cswClient->cswId = $cswId;
+	$additionalFilter='<ogc:PropertyIsEqualTo><ogc:PropertyName>apiso:OrganisationName</ogc:PropertyName><ogc:Literal>'.$orgaName.'</ogc:Literal></ogc:PropertyIsEqualTo>';
+	$cswResponseObject = $cswClient->doRequest($cswClient->cswId, 'counthits', false, false, $recordType, false, false, $additionalFilter);
+        //$e = new mb_exception("Number of type ".$recordType." datasets for orga: ".$orgaName." in portal CSW: ".$cswClient->operationResult);
+	$maxRecords = (integer)$cswClient->operationResult;
+	$pages = ceil($maxRecords / $recordsPerPage);
+	$metadataArray = array();
+	$numberOfMetadataRecords = 0;
+	for ($i = 0; $i <= $pages-1 ; $i++) {
+		$cswClient = new cswClient();
+		$cswClient->cswId = $cswId;
+		$result = $cswClient->doRequest($cswClient->cswId, 'getrecordspaging', false, false, $recordType, $recordsPerPage, ($i*$recordsPerPage)+1, $additionalFilter);
+		$page = $i + 1;
+		//$e = new mb_exception("page: ".$page." (".$pages.")");
+		if ($cswClient->operationSuccessful == true) {
+			//$e = new mb_exception("operation successfull");	
+			//$e = new mb_exception(gettype($cswClient->operationResult));
+			$metadataRecord = $cswClient->operationResult->xpath('/csw:GetRecordsResponse/csw:SearchResults/gmd:MD_Metadata');
+			//$e = new mb_exception("number of records: ".count($metadataRecord));
+			//what is possible: keywords, categories?, spatial, ...
+			for ($k = 1; $k <= count($metadataRecord) ; $k++) {
+				$fileIdentifier = $cswClient->operationResult->xpath('/csw:GetRecordsResponse/csw:SearchResults/gmd:MD_Metadata['.$k.']/gmd:fileIdentifier/gco:CharacterString');
+				$fileIdentifier = (string)$fileIdentifier[0];
+				$mdDateStamp = $cswClient->operationResult->xpath('/csw:GetRecordsResponse/csw:SearchResults/gmd:MD_Metadata['.$k.']/gmd:dateStamp/gco:Date');
+				$mdDateStamp = (string)$mdDateStamp[0];
+				$datasetIdentifier = $cswClient->operationResult->xpath('/csw:GetRecordsResponse/csw:SearchResults/gmd:MD_Metadata['.$k.']/gmd:identificationInfo/gmd:MD_DataIdentification/@uuid');
+				$datasetidentifier = (string)$datasetidentifier[0];
+				$url =  $cswClient->operationResult->xpath('/csw:GetRecordsResponse/csw:SearchResults/gmd:MD_Metadata['.$k.']/gmd:distributionInfo/gmd:MD_Distribution/gmd:transferOptions/gmd:MD_DigitalTransferOptions/gmd:onLine/gmd:CI_OnlineResource/gmd:linkage/gmd:URL');
+				$url = (string)$url[0];
+				if (isset($url) && $url !=="") {
+					//$metadataArray[$numberOfMetadataRecords]['uuid'] = $datasetIdentifier;
+					$metadataArray[$numberOfMetadataRecords]['uuid'] = $fileIdentifier;
+					$metadataArray[$numberOfMetadataRecords]['changedate'] = $mdDateStamp;
+					$numberOfMetadataRecords++;
+				}
+			}
+		}
+	}
+	//$e = new mb_exception(json_encode($metadataArray, true));
+	return $metadataArray;
+    }
+
     public function getMapbenderOrganizations() {
+	//$e = new mb_exception("getMapbenderOrganizations-> this->syncOrgaId: ".$this->syncOrgaId);
+
         if (isset($this->mapbenderUserId) && (integer)$this->mapbenderUserId > 0) {
             if (isset($this->syncOrgaId) && (integer)$this->syncOrgaId > 0) {
-	        $sql = "SELECT DISTINCT mb_group_id, mb_group_title, mb_group_name, mb_group_title, mb_group_email, mb_group_ckan_uuid, mb_group_ckan_api_key, mb_user_mb_group.mb_user_mb_group_type FROM mb_group JOIN mb_user_mb_group ON mb_group_id = fkey_mb_group_id AND fkey_mb_user_id = $1 AND mb_group_id = $2 AND mb_user_mb_group_type IN (2,3)";
+	        $sql = "SELECT DISTINCT mb_group_id, mb_group_title, mb_group_name, mb_group_title, mb_group_email, mb_group_ckan_uuid, mb_group_ckan_api_key, mb_group_csw_catalogues, mb_user_mb_group.mb_user_mb_group_type FROM mb_group JOIN mb_user_mb_group ON mb_group_id = fkey_mb_group_id AND fkey_mb_user_id = $1 AND mb_group_id = $2 AND mb_user_mb_group_type IN (2,3)";
 	        $v = array($this->mapbenderUserId, $this->syncOrgaId);
 	        $t = array('i','i');
             } else {
-	        $sql = "SELECT DISTINCT mb_group_id, mb_group_title, mb_group_name, mb_group_title, mb_group_email, mb_group_ckan_uuid, mb_group_ckan_api_key, mb_user_mb_group.mb_user_mb_group_type FROM mb_group JOIN mb_user_mb_group ON mb_group_id = fkey_mb_group_id AND fkey_mb_user_id = $1 AND mb_user_mb_group_type IN (2,3)";
+	        $sql = "SELECT DISTINCT mb_group_id, mb_group_title, mb_group_name, mb_group_title, mb_group_email, mb_group_ckan_uuid, mb_group_ckan_api_key, mb_group_csw_catalogues, mb_user_mb_group.mb_user_mb_group_type FROM mb_group JOIN mb_user_mb_group ON mb_group_id = fkey_mb_group_id AND fkey_mb_user_id = $1 AND mb_user_mb_group_type IN (2,3)";
 	        $v = array($this->mapbenderUserId);
 	        $t = array('i');
             }
@@ -110,6 +164,9 @@
                 }
                 $departmentsArray[$countDepArray]["ckan_uuid"] = $row["mb_group_ckan_uuid"];
                 $departmentsArray[$countDepArray]["ckan_api_key"] = $row["mb_group_ckan_api_key"];
+		//if ($row["mb_group_csw_catalogues"] !== null && $row["mb_group_csw_catalogues"] !== '') {
+			$departmentsArray[$countDepArray]["csw_catalogues"] = $row["mb_group_csw_catalogues"];
+		//}
                 if ($row["mb_user_mb_group_type"] == 2) {
                     $departmentsArray[$countDepArray]["is_primary_group"] = true;
                 } else {
@@ -129,6 +186,197 @@
         }
     }
 
+    //function to give back a mixed upper/lowercase string array from the input of a lowercase array and the haystack which is mixed upper/and lowercase 
+    public function searchUpperLowerCase($lowerCaseStringArray, $mixedStringArray) {
+	$result = array();
+	foreach($lowerCaseStringArray as $lowerCaseString) {
+		if (array_search($lowerCaseString, $mixedStringArray) !== false) {
+			$result[] = $mixedStringArray[array_search($lowerCaseString, $mixedStringArray)];
+		} else {
+			if (array_search(strtoupper($lowerCaseString), $mixedStringArray) !== false) {
+				$result[] = $mixedStringArray[array_search(strtoupper($lowerCaseString), $mixedStringArray)];
+			}
+		}
+	}
+    	return $result;
+    }
+
+    public function getSyncListCswJson($departmentsArray, $listAllMetadataInJson = false) {
+        $syncListCsw = new stdClass(); //should handle the returned json object
+	$syncListResultCsw = new stdClass();
+	$syncListCsw->help = "helptext";
+	$syncListCsw->success = false;
+        $syncListCsw->function = "getSyncListCswJson";
+        $numberOfCatalogue = 0;
+	$organization = $departmentsArray[0];
+	$catalogues = json_decode($departmentsArray[0]["csw_catalogues"])->csw_catalogues;
+        foreach ($catalogues as $catalogue) { //only one in this case
+       
+	    $syncListResultCsw->external_csw[$numberOfCatalogue]->id = $catalogue->catalogue_id;
+
+	    $syncListResultCsw->external_csw[$numberOfCatalogue]->orga_filter = $catalogue->organisation_filter;
+	    $syncListResultCsw->external_csw[$numberOfCatalogue]->ckan_filter = $catalogue->ckan_filter;
+	    //things from mapbender database
+ 	    $syncListResultCsw->external_csw[$numberOfCatalogue]->name = $organization["name"];
+            $syncListResultCsw->external_csw[$numberOfCatalogue]->title = $organization["title"];
+            $syncListResultCsw->external_csw[$numberOfCatalogue]->email = $organization["email"];
+	    $syncListResultCsw->external_csw[$numberOfCatalogue]->ckan_orga_ident = $organization["ckan_uuid"];
+
+            if (isset($organization["ckan_uuid"]) && isset($organization["ckan_api_key"])) {
+                //Test if organization with the given external uuid exists in the coupled ckan
+                //show organizations of the authorized user (from geoportal group table) via action api
+                $ckan = new ckanApi($organization["ckan_api_key"], CKAN_SERVER_IP);
+                $ckan->base_url = $this->ckanApiProtocol.'://'.$this->ckanApiUrl.'/api/3/';
+                $ckan->api_version = $this->ckanApiVersion;
+                $result = $ckan->action_organization_list_for_user();
+                foreach($result->result as $orga) {
+                    if ($orga->id == $organization["ckan_uuid"]) {
+			//foreach catalogue entry to sync
+			$syncListResultCsw->external_csw[$numberOfCatalogue]->ckan_orga_ident = $organization["ckan_uuid"];        
+                        //echo "Corresponding ckan organization ".$orga->display_name." found for geoportal group ".$organization["name"]." with id ".$organization["id"]."!<br>";
+                        //get list of ids for existing spatial datasets - category spatial should be defined!!!!!!
+                        //http://localhost:5000/api/3/action/package_search?fq=transparency_category_de_rp:spatial_data
+                        //with org: http://localhost:5000/api/3/action/package_search?fq=transparency_category_de_rp:spatial_data%20AND%20owner_org:81476cf5-6c52-4e99-8b9f-6150d63fcb32
+                        //TODO: define standard category filter in ckan.conf!
+                        //$queryObject->fq = STANDARD_CKAN_FILTER." AND owner_org:".$organization["ckan_uuid"];
+			$queryObject->fq = $catalogue->ckan_filter." AND owner_org:".$organization["ckan_uuid"];
+			//$queryObject->fq = "transparency_category_de_rp:spatial_data AND owner_org:".$organization["ckan_uuid"];
+                        $queryObject->facet = "true";
+			$queryObject->rows = "1000"; //TODO: maybe an problem somewhen
+                        $listOfFilteredData = $ckan->action_package_search(json_encode($queryObject));
+                        $countCkanMetadataArray = 0;
+                        $ckanMetadataArray = array();
+                        //echo "List of datasets in ckan instance:"."<br>";
+                        $ckanPackageNames = array();
+                        if ($listOfFilteredData->success == true) {
+			    //TODO - why only 10 records are given back when search?
+                            $syncListResultCsw->external_csw[$numberOfCatalogue]->count_ckan_packages = $listOfFilteredData->result->count;
+                            //echo json_encode($listOfFilteredData)."<br>";
+                            //$e = new mb_exception("Number of results: ".$listOfFilteredData->result->count);
+                            foreach ($listOfFilteredData->result->results as $dataset) {
+                                $ckanMetadataArray[$countCkanMetadataArray]['id'] = $dataset->id;
+                                $ckanMetadataArray[$countCkanMetadataArray]['name'] = $dataset->name;
+                                $ckanMetadataArray[$countCkanMetadataArray]['changedate'] = $dataset->metadata_modified;
+                                if ($listAllMetadataInJson == true) {
+                                    $syncListResultCsw->external_csw[$numberOfCatalogue]->ckan_packages[$countCkanMetadataArray]->id = $dataset->name;
+                                    $syncListResultCsw->external_csw[$numberOfCatalogue]->ckan_packages[$countCkanMetadataArray]->date_time = $dataset->metadata_modified;
+                                }
+                                //echo $dataset->title." - ".$dataset->name." - ".$dataset->metadata_modified."<br>";
+                                $ckanPackageNames[] = $dataset->name;
+                                $countCkanMetadataArray++;
+				//$e = new mb_exception("ckan dataset number: ".$countCkanMetadataArray);
+                            }
+                        } else {
+                            $e = new mb_exception("classes/class_syncCkan.php: A problem while searching for datasets in ckan occured!");
+                        }				
+                        // only list http://localhost:5000/api/3/action/package_list?q=owner_org:81476cf5-6c52-4e99-8b9f-6150d63fcb32	
+                        //pull all relevant information from mapbender database - first pull the resources which are owned by the corresponding group!
+                        //only use metadata for which real licenses are defined !!!!!! - what should be done with the other metadata?- DO a left join!!!
+                        /*if ($organization['is_primary_group']) {
+                            $sql = "SELECT *, f_get_coupled_resources(metadata_id) from mb_metadata JOIN md_termsofuse ON mb_metadata.metadata_id = md_termsofuse.fkey_metadata_id WHERE fkey_mb_user_id = $1 AND (fkey_mb_group_id is null OR fkey_mb_group_id = 0) AND export2csw IS true";
+                            $v = array($this->mapbenderUserId);
+                            $t = array('i');
+                        } else {
+                            $sql = "SELECT *, f_get_coupled_resources(metadata_id) from mb_metadata JOIN md_termsofuse ON mb_metadata.metadata_id = md_termsofuse.fkey_metadata_id WHERE fkey_mb_group_id = $1 AND export2csw IS true";
+                            $v = array($organization['id']);
+                            $t = array('i');
+                        }*/
+			//get list of distributed metadata sets with their relevant arributes from csw search!!!!!
+			$cswMetadataArray = $this->getCswRecordList((integer)$catalogue->catalogue_id, $catalogue->organisation_filter, 'nonGeographicDataset');
+			$countMetadataArray = count($cswMetadataArray);
+                        if ($countMetadataArray == 0) {
+                            //echo "No published metadata found for user with id ".$userId." <br>";
+                            //delete all records from external ckan instance
+                            /*foreach ($ckanMetadataArray as $ckanPackage) {
+                                //echo "Ckan package ".$ckanPackage['name']." should be deleted"."<br>";
+                            }*/
+                        } else {
+                            $numberCswMetadata = 0;
+                            $cswUuids = array();
+                            foreach($cswMetadataArray as $cswMetadata) {
+                                //if (count($layerArray) > 0  || count($featuretypeArray) > 0) {
+                                    //use only those that have resources!
+                                    //if ($geoportalMetadata['hasResource']) {
+                                        if ($listAllMetadataInJson == true) {
+                                            $syncListResultCsw->external_csw[$numberOfCatalogue]->csw_metadata[$numberCswMetadata]->id = $cswMetadata['uuid'];
+                                            $syncListResultCsw->external_csw[$numberOfCatalogue]->csw_metadata[$numberCswMetadata]->date_time = $cswMetadata['changedate'];
+                                        }
+                                        $cswUuids[] = $cswMetadata['uuid'];
+                                        $numberCswMetadata++;
+                                  //  }
+                                //}
+                            }
+                            $syncListResultCsw->external_csw[$numberOfCatalogue]->count_csw_packages = $numberCswMetadata;
+                            //build diffs for ckan and geoportal
+                            //Arrays: ckanPackageNames / cswUuids
+                            //Those which are only in ckan: delete them
+
+			    //TODO: Problem is that portalu/ingrid mix lowercase and uppercase uuids - to compare them always use lowercase
+			    $cswUuidsLower = array_map('strtolower', $cswUuids);
+//$e = new mb_exception(json_encode($cswUuidsLower));
+//$e = new mb_exception(json_encode($ckanPackageNames));
+                            $onlyInCkan = array_values(array_diff($ckanPackageNames, $cswUuidsLower)); //every time lowercase names!
+//$e = new mb_exception(json_encode($onlyInCkan));
+                            //Those which are only in csw: create them
+                            $onlyInCsw = array_values(array_diff($cswUuidsLower, $ckanPackageNames));
+//$e = new mb_exception(json_encode($onlyInCsw));
+                            //Those which are in both - update them if geoportal metadata is newer than the package in ckan	
+                            $inBoth = array_values(array_intersect($ckanPackageNames, $cswUuidsLower));
+//$e = new mb_exception(json_encode($inBoth));
+			    //rebuild key arrays to mixed case
+			    $onlyInCsw = $this->searchUpperLowerCase($onlyInCsw, $cswUuids);
+			    $inBoth = $this->searchUpperLowerCase($inBoth, $cswUuids);
+
+                            //if the timestamps should be compared before
+                            if ($this->compareTimestamps == true) { 
+                                foreach ($inBoth as $uuid) {
+                                    $e = new mb_notice("classes/class_syncCkan.php: search for uuid: ".$uuid."ckan time : ".$ckanMetadataArray[array_search($uuid, $this->array_column($ckanMetadataArray,'name'))]['changedate']. " - csw time: ".$cswMetadataArray[array_search($uuid, $this->array_column($cswMetadataArray,'uuid'))]['changedate']);
+                                    $dateTimeCkan = new DateTime($ckanMetadataArray[array_search($uuid, $this->array_column($ckanMetadataArray,'name'))]['changedate']);
+                                    $dateTimeCsw = new DateTime($cswMetadataArray[array_search($uuid, $this->array_column($cswMetadataArray,'uuid'))]['changedate']);
+                                    if ($dateTimeCkan > $dateTimeCsw) {
+                                        //delete from $inBoth!
+                                        $e = new mb_notice("classes/class_syncCkan.php: Ckans package newer than csw metadata!");
+                                        $inBoth = array_values(array_diff($inBoth, [$uuid]));
+                                    } else {
+                                        $e = new mb_notice("classes/class_syncCkan.php: Ckans package older than csw metadata!");
+                                    }
+                                }
+                            }
+                            //$e = new mb_exception("Number of packages which are only in ckan: ".count($onlyInCkan)." - number of packages which are only in geoportal: ".count($onlyInGeoportal)." - number of packages which are in both catalogues: ".count($inBoth));
+			    //$e = new mb_exception("both: ".gettype($inBoth)." number: ".count($inBoth)." json: ".json_encode($inBoth));
+		            //$e = new mb_exception("only ckan: ".gettype($onlyInCkan)." number: ".count($onlyInCkan)." json: ".json_encode($onlyInCkan));
+                            //$e = new mb_exception("only geoportal: ".gettype($onlyInGeoportal)." number: ".count($onlyInGeoportal)." json: ".json_encode($onlyInGeoportal));
+                            $syncListResultCsw->external_csw[$numberOfCatalogue]->update = $inBoth;
+                            $syncListResultCsw->external_csw[$numberOfCatalogue]->delete = $onlyInCkan;
+                            $syncListResultCsw->external_csw[$numberOfCatalogue]->create = $onlyInCsw;
+                        }
+                        //then pull the ressources which are owned by the user but have no group defined - only if the primary group of the user is the corresponding group!
+                        //maybe the catalogue itself is the best way to pull all relevant data, cause the coupling is resolved already!
+                        //filter for datasets:
+                        //open data - defined by the licenses
+                        //transparency - no filter at all - licenses only of some exists - otherwise none or freetext
+                    }
+                }
+            } else {
+                $e = new mb_exception("classes/class_syncCkan.php: Coupled ckan cannot be synchronized, cause the required organization-id and/or API-Key is was not found for ".$organization["name"]);
+                //echo "<br> - ".$numberOfCatalogue."<br>";
+            }
+        $numberOfCatalogue++;
+        }
+	//TODO DEBUG
+	/*	foreach($syncListResultCsw->external_csw[0]->create as $cswFileIdentifier) {
+			$e = new mb_exception($cswFileIdentifier);
+			$resultCkanRepresentation = $this->getCkanRepresentationFromCsw($syncListResultCsw->external_csw[0]->id, $cswFileIdentifier, "orga_name", "orga_title", "orga_email", $this->topicDataThemeCategoryMap, "transparency_category_de_rp:environmental_information");	
+		}
+	//
+	*/
+	if (count($syncListResultCsw->external_csw) >= 1) {
+	    $syncList->result = $syncListResultCsw;
+            $syncList->success = true;
+	}
+        return json_encode($syncList);    
+    }
+
     public function getSyncListJson($departmentsArray, $listAllMetadataInJson = false) {
         $syncList = new stdClass(); //should handle the returned json object
 	$syncListResult = new stdClass();
@@ -142,6 +390,7 @@
             $syncListResult->geoportal_organization[$numberGeoportalOrga]->title = $organization["title"];
             $syncListResult->geoportal_organization[$numberGeoportalOrga]->email = $organization["email"];
             $syncListResult->geoportal_organization[$numberGeoportalOrga]->ckan_orga_ident = false;
+	    $syncListResult->geoportal_organization[$numberGeoportalOrga]->csw_catalogues = json_decode($organization["csw_catalogues"])->csw_catalogues;
             if (isset($organization["ckan_uuid"]) && isset($organization["ckan_api_key"])) {
                 //Test if organization with the given external uuid exists in the coupled ckan
                 //show organizations of the authorized user (from geoportal group table) via action api
@@ -157,18 +406,19 @@
                         //http://localhost:5000/api/3/action/package_search?fq=transparency_category_de_rp:spatial_data
                         //with org: http://localhost:5000/api/3/action/package_search?fq=transparency_category_de_rp:spatial_data%20AND%20owner_org:81476cf5-6c52-4e99-8b9f-6150d63fcb32
                         //TODO: define standard category filter in ckan.conf!
-                        $queryObject->fq = "transparency_category_de_rp:spatial_data AND owner_org:".$organization["ckan_uuid"];
+                        $queryObject->fq = STANDARD_CKAN_FILTER." AND owner_org:".$organization["ckan_uuid"];
+			//$queryObject->fq = "transparency_category_de_rp:spatial_data AND owner_org:".$organization["ckan_uuid"];
                         $queryObject->facet = "true";
-                        $listOfSpatialData = $ckan->action_package_search(json_encode($queryObject));
+                        $listOfFilteredData = $ckan->action_package_search(json_encode($queryObject));
                         $countCkanMetadataArray = 0;
                         $ckanMetadataArray = array();
                         //echo "List of datasets in ckan instance:"."<br>";
                         $ckanPackageNames = array();
-                        if ($listOfSpatialData->success == true) {
-                            $syncListResult->geoportal_organization[$numberGeoportalOrga]->count_ckan_packages = $listOfSpatialData->result->count;
-                            //echo json_encode($listOfSpatialData)."<br>";
-                            //$e = new mb_exception("Number of results: ".$listOfSpatialData->result->count);
-                            foreach ($listOfSpatialData->result->results as $dataset) {
+                        if ($listOfFilteredData->success == true) {
+                            $syncListResult->geoportal_organization[$numberGeoportalOrga]->count_ckan_packages = $listOfFilteredData->result->count;
+                            //echo json_encode($listOfFilteredData)."<br>";
+                            //$e = new mb_exception("Number of results: ".$listOfFilteredData->result->count);
+                            foreach ($listOfFilteredData->result->results as $dataset) {
                                 $ckanMetadataArray[$countCkanMetadataArray]['id'] = $dataset->id;
                                 $ckanMetadataArray[$countCkanMetadataArray]['name'] = $dataset->name;
                                 $ckanMetadataArray[$countCkanMetadataArray]['changedate'] = $dataset->metadata_modified;
@@ -185,13 +435,13 @@
                         }				
                         // only list http://localhost:5000/api/3/action/package_list?q=owner_org:81476cf5-6c52-4e99-8b9f-6150d63fcb32	
                         //pull all relevant information from mapbender database - first pull the resources which are owned by the corresponding group!
-                        //only use metadata for which real licenses are defined !!!!!!
+                        //only use metadata for which real licenses are defined !!!!!! - what should be done with the other metadata?- DO a left join!!!
                         if ($organization['is_primary_group']) {
-                            $sql = "SELECT *, f_get_coupled_resources(metadata_id) from mb_metadata JOIN md_termsofuse ON mb_metadata.metadata_id = md_termsofuse.fkey_metadata_id WHERE fkey_mb_user_id = $1 AND (fkey_mb_group_id is null OR fkey_mb_group_id = 0)";
+                            $sql = "SELECT *, f_get_coupled_resources(metadata_id) from mb_metadata JOIN md_termsofuse ON mb_metadata.metadata_id = md_termsofuse.fkey_metadata_id WHERE fkey_mb_user_id = $1 AND (fkey_mb_group_id is null OR fkey_mb_group_id = 0) AND export2csw IS true";
                             $v = array($this->mapbenderUserId);
                             $t = array('i');
                         } else {
-                            $sql = "SELECT *, f_get_coupled_resources(metadata_id) from mb_metadata JOIN md_termsofuse ON mb_metadata.metadata_id = md_termsofuse.fkey_metadata_id WHERE fkey_mb_group_id = $1";
+                            $sql = "SELECT *, f_get_coupled_resources(metadata_id) from mb_metadata JOIN md_termsofuse ON mb_metadata.metadata_id = md_termsofuse.fkey_metadata_id WHERE fkey_mb_group_id = $1 AND export2csw IS true";
                             $v = array($organization['id']);
                             $t = array('i');
                         }
@@ -294,6 +544,119 @@
 	}
         return json_encode($syncList);    
     }
+
+    public function syncSingleCsw($syncListJson) {
+        $resultObject = new stdClass();
+        $resultObject->help = "Syncing external csw with ckan for organization with id: ".$this->syncOrgaId;
+	$syncList = json_decode($syncListJson);
+        //if ($syncList->id == $this->syncOrgaId) { - not relevant for csw sync, cause multiple csw may be synced for one ckan orga 
+            $numberOfDeletedPackages = 0;
+            $numberOfCreatedPackages = 0;
+            $numberOfUpdatedPackages = 0;
+	    //read ckan api-key from database again, because we wont transfer it via json thru the web ;-)
+	    $sql = "SELECT mb_group_ckan_api_key FROM mb_group WHERE mb_group_id = $1"; 
+            $v = array($this->syncOrgaId);
+	    $t = array('s');
+	    $res = db_prep_query($sql, $v, $t);
+	    if ($res) {
+	        $row = db_fetch_assoc($res);
+		$ckanApiKey = $row['mb_group_ckan_api_key'];
+		$ckan = new ckanApi($ckanApiKey, CKAN_SERVER_IP);
+                $ckan->base_url = $this->ckanApiProtocol.'://'.$this->ckanApiUrl.'/api/3/';
+                $ckan->api_version = $this->ckanApiVersion;
+	    } else {
+	        $e = new mb_exception("classes/class_syncCkan.php: No api-key found for mapbender group: ".$this->syncOrgaId);
+	        return false;
+	    }
+            foreach($syncList->delete as $ckanNameToDelete) {
+		//TODO - PortalU Problem lowercase/uppercase
+		$ckanNameToDelete = strtolower($ckanNameToDelete);
+
+                $result = $ckan->action_package_delete("{\"id\":\"".$ckanNameToDelete."\"}");
+                if ($result->success == true) {
+                    $e = new mb_notice("classes/class_syncCkan.php: Ckan package with name ".$ckanNameToDelete." successfully deleted!");
+                    $numberOfDeletedPackages++;
+                } else {
+                    $e = new mb_exception("classes/class_syncCkan.php: A problem occured while trying to delete ckan package with name ".$ckanNameToDelete);
+                }
+            }
+            foreach ($syncList->csw_metadata as $datasetMetadata) {
+                if (in_array($datasetMetadata->id, $syncList->update) || in_array($datasetMetadata->id, $syncList->create)) {
+                    //build resources array for each metadata
+                    /*$layerArrayMetadata = array();
+                    $featuretypeArrayMetadata = array();
+                    foreach ($datasetMetadata->resources->coupledResources->layerIds as $layerId) {
+                        $layerArrayMetadata[] = $layerId;
+                    }
+                    foreach ($datasetMetadata->resources->coupledResources->featuretypeIds as $featuretypeId) {
+                       $featuretypeArrayMetadata[] = $featuretypeId;
+                    }*/
+                    //check if dataset already exists in ckan - we know this, cause we want to update those
+                    //if (in_array($datasetMetadata['uuid'], $ckanMetadataArray['name'])) {
+                        //echo $datasetMetadata['uuid']." has to be updated!"."<br>";
+                    //} else {
+                        //echo $datasetMetadata['uuid']." has to be initial created!"."<br>";
+                        //check if deleted package with same uuid already exists, because the deleted packages only have the state deleted!
+			//TODO fix upper/lowercase problem
+                        $resourceJson->id = strtolower($datasetMetadata->id); //find by id and name name:http://docs.ckan.org/en/latest/api/
+                        $result = $ckan->action_package_show(json_encode($resourceJson));
+                        if ($result->success == true) {
+                            //update existing package
+                            //$resultCkanRepresentation = $this->getCkanRepresentation($datasetMetadata->id, $layerArrayMetadata, $featuretypeArrayMetadata, $syncList->ckan_orga_ident, $syncList->title, $syncList->email, $this->topicCkanCategoryMap);
+                            //TODO - define parameter
+			    $resultCkanRepresentation = $this->getCkanRepresentationFromCsw($syncList->id, $datasetMetadata->id, $syncList->ckan_orga_ident, $syncList->name, $syncList->email, $this->topicDataThemeCategoryMap, $syncList->ckan_filter);
+                            if ($resultCkanRepresentation != false) {
+                                $result = $ckan->action_package_update($resultCkanRepresentation['json']);
+                                if ($result->success == true) {
+                                    //echo "Creation of package successful!"."<br>";
+                                    //recreate views
+                                    //$viewsUpdateProtocol = $this->recreateResourceViews($ckan, $result, $resultCkanRepresentation);
+                                    $numberOfUpdatedPackages++;
+                                    //$e = new mb_exception($viewsUpdateProtocol);
+                                } else {
+                                    //echo "A problem occured while trying to create the ckan package"."<br>";
+                                }
+                            } else {
+                                //echo "A problem occured while trying to create the json object from geoportal metadata!"."<br>";
+                            }
+                        } else {
+                            //create new package
+                            //echo "Package ".$datasetMetadata['uuid']." does not exist and has to be created!"."<br>";
+                            //$resultCkanRepresentation = $this->getCkanRepresentation($datasetMetadata->id, $layerArrayMetadata, $featuretypeArrayMetadata, $syncList->ckan_orga_ident, $syncList->title, $syncList->email, $this->topicCkanCategoryMap);
+			    //TODO
+			    $resultCkanRepresentation = $this->getCkanRepresentationFromCsw($syncList->id, $datasetMetadata->id, $syncList->ckan_orga_ident, $syncList->title, $syncList->email, $this->topicDataThemeCategoryMap, $syncList->ckan_filter);
+                            if ($resultCkanRepresentation != false) {
+                                $result = $ckan->action_package_create($resultCkanRepresentation['json']);
+                                if ($result->success == true) {
+                                    //echo "Creation of package successful!"."<br>";
+                                    //recreate views
+                                    //$viewsUpdateProtocol = $this->recreateResourceViews($ckan, $result, $resultCkanRepresentation);
+                                    $numberOfCreatedPackages++;
+                                    //$e = new mb_exception($viewsUpdateProtocol);
+                                } else {
+                                    $e = new mb_exception("classes/class_syncCkan.php: A problem occured while trying to create the ckan package");
+                                }
+                            } else {
+                                $e = new mb_exception("classes/class_syncCkan.php: A problem occured while trying to create the json object from csw metadata!");
+                            }
+                        }
+                    //}
+                }
+            }
+        /*} else {
+            $e = new mb_exception("classes/class_syncCkan.php (syncSingleCsw): Id from json is not identical to id from class! Sync will not be started!");
+            $resultObject->success = false;
+            $resultObject->error->message = "Organization id for the invoked sync process could not be obtained - please check the id!";
+            //$resultObject->help = "Sync of metadata for orga ";
+            return json_encode($resultObject);
+        }*/     
+        $resultObject->success = true;
+        $resultObject->result->orga_id = $this->syncOrgaId;
+        $resultObject->result->numberOfDeletedPackages = $numberOfDeletedPackages;
+        $resultObject->result->numberOfUpdatedPackages = $numberOfUpdatedPackages;
+        $resultObject->result->numberOfCreatedPackages = $numberOfCreatedPackages;
+        return json_encode($resultObject);
+    }
 	
     public function syncSingleOrga($syncListJson) {
         $resultObject = new stdClass();
@@ -401,6 +764,100 @@
         return json_encode($resultObject);
     }
 
+    //private function getCkanRepresentationFromCsw($syncList->external_csw[0]->id, uuid) {
+    private function getCkanRepresentationFromCsw($cswId, $fileIdentifier, $ckan_orga_ident, $orgaTitle, $orgaEmail, $topicDataThemeCategoryMap, $ckanCategoryFilter) {
+	//getRecordById
+	$csw = new csw();
+	$csw->createCatObjFromDB($cswId);
+	$cswClient = new cswClient();
+	$cswClient->cswId = $cswId;
+	//$e = new mb_exception("invoke get record by id");
+	//$e = new mb_exception("catalogue id = ".$cswId);
+	$cswResponseObject = $cswClient->doRequest($cswClient->cswId, 'getrecordbyid', $fileIdentifier, false, false, false, false, false);
+	//parse XML
+	if ($cswClient->operationSuccessful == true) {
+		$metadataTitle = $cswClient->operationResult->xpath('/csw:GetRecordByIdResponse/gmd:MD_Metadata/gmd:identificationInfo/gmd:MD_DataIdentification/gmd:citation/gmd:CI_Citation/gmd:title/gco:CharacterString');
+		$metadataTitle = (string)$metadataTitle[0];
+		/*$fileIdentifier = $cswClient->operationResult->xpath('/csw:GetRecordByIdResponse/gmd:MD_Metadata/gmd:fileIdentifier/gco:CharacterString');
+		$fileIdentifier = $fileIdentifier[0];*/
+
+		$metadataAbstract = $cswClient->operationResult->xpath('/csw:GetRecordByIdResponse/gmd:MD_Metadata/gmd:identificationInfo/gmd:MD_DataIdentification/gmd:abstract/gco:CharacterString');
+		$metadataAbstract = (string)$metadataAbstract[0];
+
+		$keywords = $cswClient->operationResult->xpath('/csw:GetRecordByIdResponse/gmd:MD_Metadata/gmd:identificationInfo/gmd:MD_DataIdentification/gmd:descriptiveKeywords/gmd:MD_Keywords/gmd:keyword/gco:CharacterString');
+
+		$url =  $cswClient->operationResult->xpath('/csw:GetRecordByIdResponse/gmd:MD_Metadata/gmd:distributionInfo/gmd:MD_Distribution/gmd:transferOptions/gmd:MD_DigitalTransferOptions/gmd:onLine/gmd:CI_OnlineResource/gmd:linkage/gmd:URL');
+		$url = (string)$url[0];
+		$resourceName =  $cswClient->operationResult->xpath('/csw:GetRecordByIdResponse/gmd:MD_Metadata/gmd:distributionInfo/gmd:MD_Distribution/gmd:transferOptions/gmd:MD_DigitalTransferOptions/gmd:onLine/gmd:CI_OnlineResource/gmd:name/gco:CharacterString');
+		$resourceName = (string)$resourceName[0];
+		$format =  $cswClient->operationResult->xpath('/csw:GetRecordByIdResponse/gmd:MD_Metadata/gmd:distributionInfo/gmd:MD_Distribution/gmd:distributionFormat/gmd:MD_Format/gmd:name/gco:CharacterString');
+		$format = (string)$format[0];
+		//$e = new mb_exception($metadataTitle);
+		//$e = new mb_exception($fileIdentifier);
+	
+		//TODO
+	
+        	//write json object
+		$ckanPackage->title = $metadataTitle;
+        	$ckanPackage->notes = $metadataAbstract;
+$ckanPackage->name = strtolower($fileIdentifier);
+		$ckanPackage->author = $orgaTitle;
+		$ckanPackage->author_email = $orgaEmail;
+		$ckanPackage->owner_org = $ckan_orga_ident;
+		$ckanPackage->state = "active";
+		$ckanPackage->private = false;
+        	//convert bbox - if available to geojson
+		//TODO - use key of ckan category from conf!
+		$ckanCategoryFilter = explode(":",$ckanCategoryFilter);
+		$ckanPackage->{$ckanCategoryFilter[0]} = $ckanCategoryFilter[1];
+		//$ckanPackage->type = "ckan-govdata-full-1-1";
+		$ckanPackage->type = "dataset";
+		$ckanPackage->tags = array();
+		$keywords = array_unique($keywords);
+		$keywordIndex = 0;
+	        for ($i=0; $i < count($keywords); $i++) {
+			if ($keywords[$i] !== "" && isset($keywords[$i]) && strpos($keywords[$i], " ") === false) {
+                		$ckanPackage->tags[$keywordIndex]->name = (string)$keywords[$i];
+				$keywordIndex++;
+			}
+            	}
+		$resourcesArray = array();
+		if (isset($resourceName) && $resourceName !=="") {
+			$resourcesArray[0]->name = $resourceName;
+		} else {
+			$resourcesArray[0]->name = "Weitere Infos";
+		}
+		$resourcesArray[0]->url = $url;
+		if (isset($format) && $format !=="") {
+			$resourcesArray[0]->format = $format;
+		} else {
+			$resourcesArray[0]->format = "Unbekannt";
+		}
+		
+		$ckanPackage->resources = array_unique($resourcesArray);
+	}
+        $returnArray = array();
+        $returnArray['json'] = json_encode($ckanPackage);
+        //$e = new mb_exception("json: ".$returnArray['json']);
+        //$returnArray['views'] = $viewArray;
+        return $returnArray;
+	/*
+        //tags
+	$ckanPackage->type
+        //categories
+	//license - dummy!
+	$ckanPackage->license_id = $row['name'];
+	//$ckanPackage->license_id = "odc_odbl";
+	$ckanPackage->license_title = $row['description'];
+	$ckanPackage->license_url = $row['descriptionlink'];
+        //build resource:
+	$resourcesArray = array();
+        $resourcesArray[0]->name = "";
+        $resourcesArray[0]->url = "";
+        $resourcesArray[0]->format = "";*/
+	//$e = new mb_exception(json_encode($ckanPackage, true));
+    }
+
     private function getCkanRepresentation($uuid, $layerArray, $featuretypeArray, $orgaId, $orgaTitle, $orgaEmail, $topicCkanCategoryMap) {
         if (defined("MAPBENDER_PATH") && MAPBENDER_PATH != '') { 
 	    $mapbenderUrl = MAPBENDER_PATH;
@@ -409,7 +866,7 @@
 	}
 	//all or only those which have standardized licenses?
 	//$sql = "SELECT *, f_get_coupled_resources(metadata_id) from mb_metadata LEFT JOIN md_termsofuse ON mb_metadata.metadata_id = md_termsofuse.fkey_metadata_id WHERE mb_metadata.uuid = $1";
-	$sql = "SELECT * from mb_metadata JOIN md_termsofuse ON mb_metadata.metadata_id = md_termsofuse.fkey_metadata_id JOIN termsofuse ON md_termsofuse.fkey_termsofuse_id = termsofuse.termsofuse_id WHERE mb_metadata.uuid = $1";
+	$sql = "SELECT * , st_asgeojson(the_geom) as geojson from mb_metadata JOIN md_termsofuse ON mb_metadata.metadata_id = md_termsofuse.fkey_metadata_id JOIN termsofuse ON md_termsofuse.fkey_termsofuse_id = termsofuse.termsofuse_id WHERE mb_metadata.uuid = $1 AND export2csw IS true";
 	$v = array($uuid);
 	$t = array('s');
 	$res = db_prep_query($sql, $v, $t);
@@ -446,6 +903,7 @@
 	//$ckanPackage->license_id = "odc_odbl";
 	$ckanPackage->license_title = $row['description'];
 	$ckanPackage->license_url = $row['descriptionlink'];
+	$ckanPackage->spatial = $row['geojson'];
         //$ckanPackage->url = "";
 	//special categories
 	//$ckanPackage->govdata_categories = [];
@@ -469,6 +927,7 @@
 	            $resourcesArray[$indexResourceArray]->description = "Anzeige des Kartenlayers ".$row['layer_title']." im integrierten Kartenviewer (GeoPortal.rlp mobile API).";
 	            $resourcesArray[$indexResourceArray]->url = $mapbenderUrl."/extensions/mobilemap/map.php?layerid=".$row['layer_id'];
 	            $resourcesArray[$indexResourceArray]->format = "Kartenviewer inline";
+		    //$resourcesArray[$indexResourceArray]->res_transparency_document_change_classification = "unaltered";
 	            $indexResourceArray++;
 	            //views to generate
 	            $viewArray[$indexViewArray]['view_type'] = "webpage_view";
@@ -514,6 +973,7 @@
                     $resourcesArray[$indexResourceArray]->description = "Download von Rasterdaten über INSPIRE ATOM Feed: ".$metadataObject->title;
                     $resourcesArray[$indexResourceArray]->url = $mapbenderUrl."/plugins/mb_downloadFeedClient.php?url=".urlencode($mapbenderUrl."/php/mod_inspireDownloadFeed.php?id=".$metadataUuid."&type=SERVICE&generateFrom=wmslayer&layerid=".$option->resourceId);
                     $resourcesArray[$indexResourceArray]->format = "ATOM Viewer";
+		    //$resourcesArray[$indexResourceArray]->res_transparency_document_change_classification = "unaltered";
                     $indexResourceArray++;
                     //views to generate
                     //build whole json structure
@@ -530,7 +990,8 @@
                     $resourcesArray[$indexResourceArray]->id = $option->serviceUuid;
                     $resourcesArray[$indexResourceArray]->description = "Download von verlinkten Daten über INSPIRE ATOM Feed: ".$metadataObject->title;
                     $resourcesArray[$indexResourceArray]->url = $mapbenderUrl."/plugins/mb_downloadFeedClient.php?url=".urlencode($mapbenderUrl."/php/mod_inspireDownloadFeed.php?id=".$metadataUuid."&type=SERVICE&generateFrom=dataurl&layerid=".$option->resourceId);
-                    $resourcesArray[$indexResourceArray]->format = "ATOM Viewer";
+                    $resourcesArray[$indexResourceArray]->format = "ATOM Viewer"; 
+                    //$resourcesArray[$indexResourceArray]->res_transparency_document_change_classification = "unaltered";
                     $indexResourceArray++;
                     //views to generate
                     //build whole json structure
@@ -548,6 +1009,7 @@
                     $resourcesArray[$indexResourceArray]->description = "Download von Vektordaten (wfs-basiert) über INSPIRE ATOM Feed: ".$metadataObject->title;
                     $resourcesArray[$indexResourceArray]->url = $mapbenderUrl."/plugins/mb_downloadFeedClient.php?url=".urlencode($mapbenderUrl."/php/mod_inspireDownloadFeed.php?id=".$metadataUuid."&type=SERVICE&generateFrom=wfs&wfsid=".$option->serviceId);
                     $resourcesArray[$indexResourceArray]->format = "ATOM Viewer";
+                    //$resourcesArray[$indexResourceArray]->res_transparency_document_change_classification = "unaltered";
                     $indexResourceArray++;
                     //views to generate
                     //build whole json structure
@@ -565,6 +1027,7 @@
                     $resourcesArray[$indexResourceArray]->description = "Download von verlinkten Daten über INSPIRE ATOM Feed: ".$metadataObject->title;
                     $resourcesArray[$indexResourceArray]->url = $mapbenderUrl."/plugins/mb_downloadFeedClient.php?url=".urlencode($mapbenderUrl."/php/mod_inspireDownloadFeed.php?id=".$metadataUuid."&type=SERVICE&generateFrom=metadata");
                     $resourcesArray[$indexResourceArray]->format = "ATOM Viewer";
+                    //$resourcesArray[$indexResourceArray]->res_transparency_document_change_classification = "unaltered";
                     $indexResourceArray++;
                     //views to generate
                     //build whole json structure

Modified: trunk/mapbender/http/javascripts/mod_syncCkan_client.php
===================================================================
--- trunk/mapbender/http/javascripts/mod_syncCkan_client.php	2017-08-01 09:54:15 UTC (rev 9757)
+++ trunk/mapbender/http/javascripts/mod_syncCkan_client.php	2017-08-09 08:12:36 UTC (rev 9758)
@@ -63,8 +63,105 @@
 $title = _mb('Ckan sync module');	
 ?>
 <title><?php echo $title;?></title>
-<script src="../extensions/jquery-1.12.0.min.js"></script>
+<!--<script src="../extensions/jquery-1.12.0.min.js"></script> -->
+<!--TODO use newer jquery/ui libs! -->
+<script src="../extensions/jquery-ui-1.8.16.custom/js/jquery-1.6.2.min.js"></script>
+<script src="../extensions/jquery-ui-1.8.16.custom/js/jquery-ui-1.8.16.custom.min.js"></script>
+<!--<script src="../extensions/jquery-ui-1.12.1/external/jquery.js"></script> -->
+<!--<script src="../extensions/jquery-ui-1.12.1/jquery-ui.min.js"></script> -->
+<!--<link rel="stylesheet" href="../extensions/jquery-ui-1.12.1/jquery-ui.min.css"> -->
+<link rel="stylesheet" href="../extensions/jquery-ui-1.8.16.custom/css/ui-lightness/jquery-ui-1.8.16.custom.css">
 <script>
+//https://stackoverflow.com/questions/29298462/c-curcss-is-not-a-function-bug-from-jquery
+/*jQuery.curCSS = function(element, prop, val) {
+    return jQuery(element).css(prop, val);
+};*/
+
+function showCatalogues(compareTimestamps, syncDepartment, operation, orgaId) {
+	/*for (csw of csw_catalogues) {
+		console.log(csw);
+	}*/
+	//alert(syncDepartment);
+	$("#load_catalogue_statistics").css("display","block");
+	$.ajax({
+  		url: '../php/mod_syncCkan_server.php',
+  		type: "post",
+		async: true,
+		data: {compareTimestamps: compareTimestamps, syncDepartment: syncDepartment, operation: operation, orgaId: orgaId},
+       		dataType: "json",
+  		success: function(result) {
+			if (result.success == true) {
+				//alert(JSON.stringify(result.result));
+    				$( "#show_catalogues" ).dialog({
+					height: 200,
+      					width: 550,
+      					modal: true,
+       					close: function(event, ui)
+        					{
+            						//$(this).destroy().remove();
+							$("#csw_sync_status_table tr:gt(0)").remove();
+        				}
+				});
+				//$( "#show_catalogues" ).
+				if (operation == 'listCatalogues') {
+				//initialize table
+				for (orga of result.result.result.external_csw) {
+					//read length of delete, update, create into variables
+					if ("undefined" !== typeof(orga.delete)) {var p_delete = (orga.delete).length;} else {var p_delete = 0;}
+					if ("undefined" !== typeof(orga.update)) {var p_update = (orga.update).length;} else {var p_update = 0;}
+					//alert(JSON.stringify(orga.update));
+					//alert(typeof(orga.update));
+					if ("undefined" !== typeof(orga.create)) {var p_create = (orga.create).length;} else {var p_create = 0;}
+					$('#csw_sync_status_table tr:last').after('<tr id=\'csw_r_id_'+orga.id+'\'>'+'<td id=\'csw_ckanorgauuid_'+orga.id+'\'><a target=\'_blank\' href=\'<?php echo $ckanShowOrgaUrl;?>'+orga.ckan_orga_ident+'\'>'+orga.ckan_orga_ident+' ('+orga.count_ckan_packages+')'+'</a></td>'+'<td id=\'csw_orgatitle_'+orga.id+'\'>'+'<a target=\'_blank\' href=\'../php/mod_showOrganizationInfo.php?id='+orga.id+'\'>'+orga.title+' ('+orga.count_csw_packages+')'+'</a>'+'</td>'+'<td id=\'csw_to_delete_'+orga.id+'\'>'+p_delete+'</td>'+'<td id=\'csw_to_update_'+orga.id+'\'>'+p_update+'</td>'+'<td id=\'csw_to_create_'+orga.id+'\'>'+p_create+'</td>'+'</tr>');
+					//add button for start syncing if something may be done ;-)
+					if ((p_delete+p_update+p_create) > 0) {
+						//alert(p_delete+p_update+p_create);
+						//$form .= "<button class=\"btn btn-primary\" type=\"button\" id=\"maintenance_button\" onclick=\"callServer('".$resourceType."','".$maintenanceFunction."',$('#resource_id_list').val(),"."1".");\">";
+						//the first orga.id is the csw id in case of csw sync!!!!!!!
+						$('#csw_r_id_'+orga.id+' td:last').after('<td id=\'csw_button_column_'+orga.id+'\'><button class=\"btn btn-primary\" type=\"button\" id=\"csw_sync_button_'+orga.id+'\" onclick=\"showCatalogues('+compareTimestamps+','+orga.id+',\'syncCsw\','+orgaId+');\">Start sync via CSW</button></td>');
+					} else {
+						//alert(p_delete+p_update+p_create+' - lower or equal zero');
+						//deactivated button
+						$('#csw_r_id_'+orga.id+' td:last').after('<td id=\'csw_button_column_'+orga.id+'\'><button class=\"btn btn-primary\" type=\"button\" id=\"csw_sync_button_'+orga.id+'\" disabled>Nothing to do</button></td>');
+					}
+				}
+		
+				if (operation == 'syncCsw')
+					if (result.success == true) {
+						//update values
+						$('#csw_to_delete_'+result.result.orga_id).text(parseInt($('#csw_to_delete_'+result.result.orga_id).text()) - result.result.numberOfDeletedPackages);
+						$('#csw_to_update_'+result.result.orga_id).text(parseInt($('#csw_to_update_'+result.result.orga_id).text()) - result.result.numberOfUpdatedPackages);
+						$('#csw_to_create_'+result.result.orga_id).text(parseInt($('#csw_to_create_'+result.result.orga_id).text()) - result.result.numberOfCreatedPackages);
+						//check if something more is to be done
+						if ((parseInt($('#csw_to_delete_'+result.result.orga_id).text()) + parseInt($('#csw_to_update_'+result.result.orga_id).text()) + parseInt($('#csw_to_create_'+result.result.orga_id).text())) == 0) {
+							//alert('drop button');
+							$('#csw_button_column_'+result.result.orga_id).remove();
+						} else {
+							//alert((parseInt($('#to_delete_'+result.result.orga_id).text()) + parseInt($('#to_update_'+result.result.orga_id).text()) + parseInt($('#to_create_'+result.result.orga_id).text())));
+						}
+						//$("#csw_sync_status_table tr").remove();
+						//$("#csw_sync_status_table").empty();
+						alert("Packages created: "+result.result.numberOfCreatedPackages+" - Packages updated: "+numberOfUpdatedPackages+" - Packages deleted: "+numberOfDeleteddPackages);
+					}
+					$("#sync_single_csw").css("display","none");
+				}
+				
+				//set title
+				//show button with information about the catalogues and the buttons!
+				//show table
+				//foreach catalogue show line
+				//show button to sync	
+			} else {
+				alert(result.error.message);
+			}	
+			$("#load_catalogue_statistics").css("display","none");
+			//close dialog
+			//$( "#show_catalogues" ).dialog('close');
+ 		}
+	});
+	return false;
+}
+
 function callServer(compareTimestamps, syncDepartment) {
 	if (syncDepartment == 0) {
 		$("#get_orga_list_info").css("display","block");
@@ -94,8 +191,26 @@
 						if ((p_delete+p_update+p_create) > 0) {
 							//$form .= "<button class=\"btn btn-primary\" type=\"button\" id=\"maintenance_button\" onclick=\"callServer('".$resourceType."','".$maintenanceFunction."',$('#resource_id_list').val(),"."1".");\">";
 							$('#r_id_'+orga.id+' td:last').after('<td id=\'button_column_'+orga.id+'\'><button class=\"btn btn-primary\" type=\"button\" id=\"sync_button_'+orga.id+'\" onclick=\"callServer('+compareTimestamps+','+orga.id+');\">Start sync</button></td>');
+						} else {
+							//deactivated button
+							$('#r_id_'+orga.id+' td:last').after('<td id=\'button_column_'+orga.id+'\'><button class=\"btn btn-primary\" type=\"button\" id=\"sync_button_'+orga.id+'\" disabled>Nothing to do</button></td>');
 						}
-						//
+						if (orga.csw_catalogues !== null) {
+							//csw_cataloguesObject = Object.assign({}, orga.csw_catalogues);
+							//csw_cataloguesObject = {};
+							/*var i = 0;
+							for (csw of orga.csw_catalogues) {
+								csw_cataloguesObject[i] = csw;
+							}*/
+							$('#r_id_'+orga.id+' td:last').after('<td id=\'external_button_column_'+orga.id+'\'><button class=\"btn btn-primary\" type=\"button\" id=\"external_sync_button_'+orga.id+'\" onclick=\"showCatalogues('+compareTimestamps+','+orga.id+',\'listCatalogues\','+orga.id+');\">Show catalogue status</button></td><td></td>');
+							/*console.log(typeof(orga.csw_catalogues[0].organisation_filter));
+							console.log(orga.csw_catalogues[0].organisation_filter);
+							for (csw of orga.csw_catalogues) {
+								console.log(csw);
+						
+							}*/
+						}
+						//onclick=\"showCatalogues('+compareTimestamps+','+orga+');\"
 					}
 				} else {
 					//update row for specific organization
@@ -140,6 +255,24 @@
 <div id="title"><?php echo $title; ?></div>
 <div id="get_orga_list_info" style="display: none;"><p><img class="loading_symbol" src="../img/loader_lightblue.gif" style="margin-left: auto; margin-right: auto;"/><?php echo _mb("Getting organization info ..."); ?></p></div>
 <div id="sync_single_orga" style="display: none;"><p><img class="loading_symbol" src="../img/loader_lightblue.gif" style="margin-left: auto; margin-right: auto;"/><?php echo _mb("Syncing metadata ..."); ?></p></div>
+<div id="sync_single_csw" style="display: none;"><p><img class="loading_symbol" src="../img/loader_lightblue.gif" style="margin-left: auto; margin-right: auto;"/><?php echo _mb("Syncing metadata via CSW ..."); ?></p></div>
+<div id="show_catalogues" style="display: none;">
+<form id="csw_sync_status_form">
+    <table id ="csw_sync_status_table">
+        <tr id="csw_sync_status_table_row_header">
+            <th><?php echo _mb('Ckan instance'); ?></th>
+            <th><?php echo _mb('External CSW'); ?></th>
+            <th><?php echo _mb('# delete'); ?></th>
+            <th><?php echo _mb('# update'); ?></th>
+	    <th><?php echo _mb('# create'); ?></th>
+	    <th><?php echo _mb('Action'); ?></th>
+        </tr>
+    </table>
+</form>
+</div>
+<div id="load_catalogue_statistics" style="display: none;"><p><img class="loading_symbol" src="../img/loader_lightblue.gif" style="margin-left: auto; margin-right: auto;"/><?php echo _mb("Loading catalogue statistics ..."); ?></p></div>
+<div id="sync_single_catalogue" style="display: none;"><p><img class="loading_symbol" src="../img/loader_lightblue.gif" style="margin-left: auto; margin-right: auto;"/><?php echo _mb("Syncing catalogue metadata ..."); ?></p></div>
+
 <form id="sync_status_form">
     <table id ="sync_status_table">
         <tr id="sync_status_table_row_header">
@@ -148,7 +281,8 @@
             <th><?php echo _mb('# delete'); ?></th>
             <th><?php echo _mb('# update'); ?></th>
 	    <th><?php echo _mb('# create'); ?></th>
-	    <th><?php echo _mb('Action'); ?></th>
+	    <th><?php echo _mb('Action'); ?></th>	    
+	    <th><?php echo _mb('External catalogues'); ?></th>
         </tr>
     </table>
 </form>

Modified: trunk/mapbender/http/php/mod_syncCkan_server.php
===================================================================
--- trunk/mapbender/http/php/mod_syncCkan_server.php	2017-08-01 09:54:15 UTC (rev 9757)
+++ trunk/mapbender/http/php/mod_syncCkan_server.php	2017-08-09 08:12:36 UTC (rev 9758)
@@ -21,7 +21,7 @@
 $listAllMetadataInJson = true;
 //initiate resultObject to give back as json
 $resultObject->success = false;
-
+$operation = false;
 //parse request parameter
 if (isset($_REQUEST["registratingDepartments"]) & $_REQUEST["registratingDepartments"] != "") {
 	//validate to csv integer list
@@ -49,6 +49,29 @@
         $testMatch = NULL;
 }
 
+if (isset($_REQUEST["orgaId"]) && $_REQUEST["orgaId"] !== "" && $_REQUEST["orgaId"] !== null) {
+        $testMatch = $_REQUEST["orgaId"];
+        $pattern = '/^[0-9]*$/';  
+        if (!preg_match($pattern,$testMatch)){
+                $resultObject->error->message = 'Parameter orgaId is not valid (integer).';
+                echo json_encode($resultObject);
+		die();	
+        }
+        $orgaId = (integer)$testMatch;
+        $testMatch = NULL;
+}
+
+if (isset($_REQUEST["operation"]) && $_REQUEST["operation"] !== "" && $_REQUEST["operation"] !== null) {
+        $testMatch = $_REQUEST["operation"];
+ 	if (!($testMatch == 'listCatalogues' or $testMatch == 'syncCatalogue' or $testMatch == 'syncCsw')){ 
+	 	$resultObject->error->message = 'Parameter operation is not valid (listCatalogues, syncCatalogue, syncCsw).'; 
+		echo json_encode($resultObject);	
+		die();	
+ 	}
+        $operation = $testMatch;
+        $testMatch = NULL;
+}
+
 if (isset($_REQUEST["userId"]) & $_REQUEST["userId"] != "") {
         $testMatch = $_REQUEST["userId"];
         $pattern = '/^[0-9]*$/';  
@@ -119,9 +142,6 @@
         "resultObj": "s.th."
         }
 }
-
-
-
 */
 
 $syncCkanClass = new SyncCkan();
@@ -133,11 +153,55 @@
 	$syncCkanClass->syncOrgaId = $syncDepartment;
 }
 
+if ($operation == 'listCatalogues') {
+	//get orga id from mapbender group!! - where from?
+	$departmentsArray = $syncCkanClass->getMapbenderOrganizations();
+	//invoke check for csw
+	$result = new stdClass();
+	//check for datasets - ckan vs. csw
+	$result->result = json_decode($syncCkanClass->getSyncListCswJson($departmentsArray, $listAllMetadataInJson = true));
+	$result->success = true;
+	header('Content-type:application/json;charset=utf-8');
+	echo json_encode($result);
+	die();
+}
+
+if ($operation == 'syncCsw') {
+	//check if user is allowed to sync for requested organisation
+	//TODO - make code better
+	//overwrite organization from cswId with right orgaId
+	$test = $syncCkanClass->syncOrgaId;
+	$syncCkanClass->syncOrgaId = $orgaId;
+	//$e = new mb_exception($syncCkanClass->syncOrgaId);
+	$departmentsArray = $syncCkanClass->getMapbenderOrganizations();
+	//rewind orgaid to cswid to get right synclist
+	$syncCkanClass->syncOrgaId = $test;
+	$syncListJsonCsw = $syncCkanClass->getSyncListCswJson($departmentsArray, true);
+	//for synching use right orga id for getting apikey for invoking $syncCkanClass->syncSingleCsw
+	$syncCkanClass->syncOrgaId = $orgaId;
+	$syncList = json_decode($syncListJsonCsw);
+	if ($syncList->success = true) {
+    		foreach ($syncList->result->external_csw as $orga) {
+        		//TODO try to sync single orga - the class has already set the syncOrgaId if wished!
+			//if ($syncDepartment == $orga->id) {
+            			//overwrite result with result from sync process
+            			$syncList = json_decode($syncCkanClass->syncSingleCsw(json_encode($orga)));
+			//}
+    		}
+	}
+	//create new syncListJson
+	$syncListJson = json_encode($syncList);
+	header('Content-type:application/json;charset=utf-8');
+	echo $syncListJson;
+	die();
+}
+
 $departmentsArray = $syncCkanClass->getMapbenderOrganizations();
 
 //second parameter is listAllMetadataInJson ( = true) - it is needed if we want to sync afterwards. The syncList includes all necessary information about one organization
 
 $syncListJson = $syncCkanClass->getSyncListJson($departmentsArray, true);
+
 $syncList = json_decode($syncListJson);
 if ($syncList->success = true) {
     foreach ($syncList->result->geoportal_organization as $orga) {
@@ -153,5 +217,4 @@
 header('Content-type:application/json;charset=utf-8');
 echo $syncListJson;
 
-
 ?>



More information about the Mapbender_commits mailing list