├── .php-cs-fixer.dist.php ├── CHANGELOG.md ├── README.md ├── composer.json ├── docs └── media │ ├── demo.gif │ ├── screenshot.png │ └── wps-panel.png ├── license.txt └── wps ├── INSTALL.md ├── adminurls.xml ├── classes ├── lizmapWPSRequest.class.php ├── processStatus.class.php ├── wps.listener.php ├── wpsOGCRequest.class.php ├── wpsWCSRequest.class.php ├── wpsWFSRequest.class.php └── wpsWMSRequest.class.php ├── controllers ├── admin.classic.php ├── ows.classic.php ├── restrictionsAdmin.classic.php ├── results.classic.php └── service.classic.php ├── events.xml ├── forms ├── model_upload.form.xml ├── project_restriction_params.form.xml └── style_upload.form.xml ├── install ├── configure.php ├── install.php └── upgrade_03.php ├── lib ├── ModelFile.php ├── ModelFileManager.php └── StyleFile.php ├── locales ├── en_US │ └── wps.UTF-8.properties └── fr_FR │ └── wps.UTF-8.properties ├── module.xml ├── templates ├── admin.list.tpl ├── admin.model3.confirmdelete.tpl ├── admin.model3.showform.tpl ├── admin.qml.confirmdelete.tpl ├── admin.qml.showform.tpl ├── bottomdock.tpl ├── dock.tpl ├── restrictions.edit.tpl ├── restrictions.show.tpl ├── wcs_exception.tpl └── wps_exception.tpl ├── urls.xml └── www ├── OpenLayers ├── Format │ ├── Filter.js │ ├── Filter │ │ ├── v1.js │ │ └── v1_1_0.js │ ├── GML.js │ ├── GML │ │ ├── Base.js │ │ ├── v2.js │ │ └── v3.js │ ├── OWSCommon.js │ ├── OWSCommon │ │ ├── v1.js │ │ ├── v1_0_0.js │ │ └── v1_1_0.js │ ├── WCSGetCoverage.js │ ├── WFST.js │ ├── WFST │ │ ├── v1.js │ │ └── v1_1_0.js │ ├── WPSCapabilities.js │ ├── WPSCapabilities │ │ └── v1_0_0.js │ ├── WPSDescribeProcess.js │ └── WPSExecute.js ├── Request.js └── Request │ └── XMLHttpRequest.js ├── wps.css └── wps.js /.php-cs-fixer.dist.php: -------------------------------------------------------------------------------- 1 | in(array( 5 | __DIR__.'/wps', 6 | )) 7 | ; 8 | 9 | $config = new PhpCsFixer\Config(); 10 | return $config 11 | ->setCacheFile(__DIR__.'/.php-cs-fixer.cache') 12 | ->setRules([ 13 | '@PSR2' => true, 14 | '@Symfony' => true, 15 | '@PhpCsFixer' => true, 16 | 'array_syntax' => array('syntax'=>'long'), 17 | 'method_argument_space'=> ['on_multiline' => 'ensure_fully_multiline'], 18 | 'new_with_braces'=> true, 19 | 'no_whitespace_in_blank_line'=> true, 20 | 'no_whitespace_before_comma_in_array'=> true, 21 | 'no_useless_return' => true, 22 | 'no_unneeded_final_method'=> false, 23 | 'no_unset_cast' => false, 24 | 'no_leading_import_slash'=> true, 25 | 'no_leading_namespace_whitespace'=> true, 26 | 'no_extra_blank_lines'=> true, 27 | 'no_empty_statement'=> true, 28 | 'no_empty_comment'=> true, 29 | 'object_operator_without_whitespace' => true, 30 | 'ordered_class_elements' => false, 31 | 'phpdoc_var_without_name' => true, 32 | 'phpdoc_types' => true, 33 | 'phpdoc_trim_consecutive_blank_line_separation' => true, 34 | 'phpdoc_no_useless_inheritdoc' => true, 35 | 'phpdoc_no_empty_return' => true, 36 | 'phpdoc_add_missing_param_annotation' => true, 37 | 'protected_to_private' => false, 38 | 'semicolon_after_instruction' => true, 39 | 'short_scalar_cast' => true, 40 | 'simplified_null_return' => false, 41 | 'simple_to_complex_string_variable' => false, 42 | 'standardize_not_equals' => true, 43 | 'standardize_increment' => true, 44 | 'whitespace_after_comma_in_array' => true, 45 | 'yoda_style'=>array( 46 | 'always_move_variable' => false, 47 | 'equal' => false, 48 | 'identical' => false, 49 | 'less_and_greater' => null, 50 | ) 51 | ]) 52 | ->setFinder($finder) 53 | ; 54 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | 8 | 9 | ## Unreleased 10 | 11 | ## 0.5.2 - 2025-05-12 12 | 13 | ### Added 14 | 15 | * French language 16 | * Admin: Manage QGIS Style files for QGIS Models 17 | * UI: Mandatory processing inputs 18 | * WPS panel image 19 | * max Lizmap Web Client version 3.9.* 20 | 21 | ### Fixed 22 | 23 | * GetResults response: OWS Url replacement 24 | * GetResults response: Empty OWS Url 25 | * JS variables for WPS 26 | 27 | 28 | ## 0.5.1 - 2024-07-23 29 | 30 | ### Changed 31 | 32 | * Confirm delete & allow file update 33 | 34 | ### Fixed 35 | 36 | * OL serverType qgis 37 | 38 | ## 0.5.0 - 2024-07-22 39 | 40 | ### Changed 41 | 42 | * Dependencies : Lizmap Web Client 3.8 Minimum version 43 | 44 | ## 0.3.1 - 2024-07-11 45 | 46 | ### Fixed 47 | 48 | * Bugfix JS: Check wps elements are loaded 49 | 50 | ## 0.3.0 - 2024-02-26 51 | 52 | ### Fixed 53 | 54 | * Fixing the delete method of results controller 55 | * Support outputs files and jobs 56 | * UI: No output displayed for undefined layer name 57 | * UI: The triangle before title not cliquable in results 58 | * UI: Hide WPS if no algorithm available 59 | * Fixing the way to manage selection for FeatureSource 60 | * Fixing the results controller 61 | * UI: Adding status in log table 62 | 63 | ### Added 64 | 65 | * Tests: enhancing Test input file destination algorithm 66 | * UI: Display file outputs 67 | * UI: Select default layer 68 | * UI: Update field parameter at startup 69 | * Config: Field parameter can be restricted 70 | * Tests: Algorithm to convert feature source to vector layer 71 | * Support WMS DescribeLayer request 72 | * Using Expression filter when it is provided 73 | * CSS: Add id to processing input control-group 74 | * new config to restrict access to WPS 75 | * Support X-Job-Realm for use 76 | * Support Administrator realm token 77 | * Tests: enhancing Test environment to work with lizmap 3.6 78 | * Job label based on input value 79 | * Select the algorithm if only one is available 80 | * UI: Admin page to upload model3 files 81 | * UI: Admin page to manage WPS enabling restrictions on projects 82 | 83 | ## 0.2.0 - 2022-11-22 84 | 85 | * Fix path to dataviz for Lizmap >= 3.4 86 | * Update to QGIS Server 3.16 87 | * Refactor HTTP calls 88 | * Some cleanup in the code 89 | * Update the composer.json file for Packagist 90 | * Start some tests using the Cypress framework 91 | * Update php-cs-fixer to 3.8.0 92 | * Experimental compatibility with Lizmap 3.6 93 | * Support Extent input 94 | * Support Point input 95 | 96 | ## 0.1.1 - 2021-03-31 97 | 98 | ## 0.1.0 - 2020-11-25 99 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Lizmap WPS Web Client 2 | 3 | [![🔤 Lint](https://github.com/3liz/lizmap-wps-web-client-module/actions/workflows/lint.yml/badge.svg)](https://github.com/3liz/lizmap-wps-web-client-module/actions/workflows/lint.yml) 4 | [![🚀 Release](https://github.com/3liz/lizmap-wps-web-client-module/actions/workflows/release.yml/badge.svg)](https://github.com/3liz/lizmap-wps-web-client-module/actions/workflows/release.yml) 5 | [![Packagist](https://img.shields.io/packagist/v/lizmap/lizmap-wps-web-client)](https://packagist.org/packages/lizmap/lizmap-wps-web-client) 6 | 7 | Lizmap WPS Web Client is a Lizmap module to add a WPS panel into [Lizmap Web Client](https://github.com/3liz/lizmap-web-client/). 8 | 9 | This is an example showing the QGIS Processing Buffer algorithm, exposed as a WPS algorithm within Lizmap Web Client: 10 | 11 | ![Screenshot](docs/media/wps-panel.png) 12 | 13 | ![Screenshot](docs/media/screenshot.png) 14 | 15 | ![Demo gif](docs/media/demo.gif) 16 | 17 | It's also providing another panel showing you the results which have been executed on the Lizmap instance. 18 | 19 | ## Installation 20 | 21 | Since version 0.1.1, it is recommended to install the module 22 | with [Composer](https://getcomposer.org), the package manager for PHP. 23 | If you can't use it or if you are using Lizmap 3.3 or lower, use the manual way to 24 | install the module (jump to the corresponding section below) 25 | 26 | ### Automatic installation with Composer and lizmap 3.4 or higher 27 | 28 | * into `lizmap/my-packages`, create the file `composer.json` (if it doesn't exist) 29 | by copying the file `composer.json.dist`, and install the module with Composer: 30 | 31 | ```bash 32 | cp -n lizmap/my-packages/composer.json.dist lizmap/my-packages/composer.json 33 | composer require --working-dir=lizmap/my-packages "lizmap/lizmap-wps-web-client" 34 | ``` 35 | 36 | * If you are using Lizmap 3.6 or higher, execute 37 | 38 | ```bash 39 | php lizmap/install/configurator.php wps 40 | ``` 41 | 42 | * Then for any version, execute Lizmap install scripts into `lizmap/install/` : 43 | 44 | ```bash 45 | php lizmap/install/installer.php 46 | ./lizmap/install/clean_vartmp.sh 47 | ./lizmap/install/set_rights.sh 48 | ``` 49 | 50 | Go to the "Configuration" section. 51 | 52 | ### Manual installation into lizmap 3.3 or 3.4 without Composer 53 | 54 | * Download the zip archive from the [release page into GitHub](https://github.com/3liz/lizmap-wps-web-client-module/releases). 55 | * Extract files from the archive and copy the directory `wps` into `lizmap/lizmap-modules/` of Lizmap. 56 | * Edit the file `lizmap/var/config/localconfig.ini.php` to add this 57 | into the `[modules]` section 58 | 59 | ```ini 60 | wps.access=2 61 | ``` 62 | 63 | * Then execute Lizmap install scripts into `lizmap/install/` : 64 | 65 | ```bash 66 | php lizmap/install/installer.php 67 | ./lizmap/install/clean_vartmp.sh 68 | ./lizmap/install/set_rights.sh 69 | ``` 70 | 71 | 72 | ## configuration 73 | 74 | Add a section `[wps]` in your `localconfig.ini.php` and add the variables: 75 | 76 | ```ini 77 | [wps] 78 | wps_root_url=http://wps:8080 79 | wps_rootDirectories=/projects/wps 80 | 81 | redis_host=localhost 82 | redis_port=6379 83 | redis_key_prefix=lzmwps 84 | redis_db=1 85 | ows_url=http://map:8080 86 | restrict_to_config_projects=off 87 | restrict_to_authenticated_users=off 88 | enable_job_realm=off 89 | admin_job_realm= 90 | ``` 91 | 92 | The WPS configuration: 93 | 94 | * `wps_root_url` is the URL of the WPS service 95 | * `wps_rootDirectories` is the path of the directories defined for the WPS Service MAP 96 | 97 | The redis configuration for saving process status: uuid, INPUTS, OUTPUTS. 98 | 99 | * `redis_host` the redis host to use 100 | * `redis_port` the redis port to use 101 | * `redis_db` the redis database to use 102 | * `redis_key_prefix` the redis key prefix to use 103 | 104 | The OWS proxy configuration: 105 | 106 | * `ows_url` is the URL of the OWS service used by the WPS service 107 | 108 | The availability of WPS algorithms in the Lizmap Web Client web maps 109 | 110 | * `restrict_to_config_projects` the module is not enabled for projects without a json config for processes. 111 | * `restrict_to_authenticated_users` the module is not enabled if the user is not authenticated. 112 | * `enable_job_realm` enable job access control by associating a realm token to each job. Job realm will be built at user level. 113 | * `admin_job_realm` administrator realm token. It allows bearer to bypass any other token. 114 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lizmap/lizmap-wps-web-client", 3 | "type": "jelix-module", 4 | "description": "Jelix modules to add WPS Web Client.", 5 | "keywords": ["module", "jelix", "lizmap", "wps"], 6 | "homepage": "http://3liz.com", 7 | "license": "MPL-2.0", 8 | "authors": [ 9 | { 10 | "name": "René-Luc Dhont", 11 | "email": "rldhont@3liz.com" 12 | } 13 | ], 14 | "require": { 15 | }, 16 | "minimum-stability": "stable", 17 | "extra" : { 18 | "jelix" : { 19 | "modules": [ 20 | "wps/" 21 | ], 22 | "autoconfig-access-16" : { 23 | "lizmap@3liz.com" : { 24 | "wps": { 25 | "__global": 1, 26 | "index" : 2 27 | } 28 | } 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /docs/media/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3liz/lizmap-wps-web-client-module/de4d8e3ed892e5f6e5f23624e6d943677e820bc1/docs/media/demo.gif -------------------------------------------------------------------------------- /docs/media/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3liz/lizmap-wps-web-client-module/de4d8e3ed892e5f6e5f23624e6d943677e820bc1/docs/media/screenshot.png -------------------------------------------------------------------------------- /docs/media/wps-panel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3liz/lizmap-wps-web-client-module/de4d8e3ed892e5f6e5f23624e6d943677e820bc1/docs/media/wps-panel.png -------------------------------------------------------------------------------- /wps/INSTALL.md: -------------------------------------------------------------------------------- 1 | # Module Petra 2 | 3 | ## Manual Installation 4 | 5 | Copy the *wps* directory to lizmap/lizmap-modules/ folder. 6 | 7 | For Lizmap 3.5 or lower, in `var/config/localconfig.ini.php` create or update the section `[modules]` with the value: 8 | ``` 9 | wps.access=2 10 | ``` 11 | 12 | For Lizmap 3.6 or higher, run the command `php lizmap/install/configurator.php wps`. 13 | 14 | For all Lizmap, then run 15 | 16 | ```bash 17 | php lizmap/install/installer.php 18 | lizmap/install/clean_vartmp.sh 19 | lizmap/install/set_rights.sh 20 | ``` 21 | 22 | 23 | 24 | ## Configuration 25 | 26 | 27 | In `localconfig.ini.php` add: 28 | ``` 29 | [wps] 30 | wps_rootUrl= 31 | wps_rootDirectory= 32 | redis_host=localhost 33 | redis_port=6379 34 | redis_key_prefix=lzmwps 35 | ows_url= 36 | ``` 37 | 38 | The `wps_rootUrl` is the URL of the WPS QGIS Server. 39 | The `wps_rootDirectory` is the directory of the lizmap installation mounted as the WPS QGIS Server projects directory. 40 | The `ows_url` is the URL of the OWS defined in WPS QGIS Server for generated services. 41 | -------------------------------------------------------------------------------- /wps/adminurls.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /wps/classes/lizmapWPSRequest.class.php: -------------------------------------------------------------------------------- 1 | services = lizmap::getServices(); 28 | $nParams = lizmapProxy::normalizeParams($params); 29 | foreach ($params as $k => $v) { 30 | if (strtolower($k) === 'repository' || strtolower($k) === 'project') { 31 | $nParams[strtolower($k)] = $v; 32 | } 33 | } 34 | $this->params = $nParams; 35 | $this->xml_post = $xml_post; 36 | 37 | $wpsConfig = jApp::config()->wps; 38 | $this->wps_url = $wpsConfig['wps_rootUrl']; 39 | if (substr($this->wps_url, -1) != '/') { 40 | $this->wps_url .= '/'; 41 | } 42 | $this->wps_rootDirectories = $wpsConfig['wps_rootDirectories']; 43 | $this->ows_url = $wpsConfig['ows_url']; 44 | if (substr($this->ows_url, -1) != '/') { 45 | $this->ows_url .= '/'; 46 | } 47 | } 48 | 49 | /** 50 | * Do the process. 51 | * 52 | * @internal we override the process() method of lizmapOGCRequest to be sure 53 | * we have the secure version of the method, in case where the lizmap version 54 | * is <= 3.4.3, <= 3.3.15 55 | * 56 | * deprecated: remove this overrided method when we will mark the module compatible 57 | * only with Lizmap 3.5. 58 | * 59 | * @return array 60 | */ 61 | public function process() 62 | { 63 | $req = $this->param('request'); 64 | if ($req) { 65 | $reqMeth = 'process_'.$req; 66 | if (method_exists($this, $reqMeth)) { 67 | return $this->{$reqMeth}(); 68 | } 69 | // old unsecure way, to be compatible with methods of lizmap <= 3.4.3, <= 3.3.15 70 | if (method_exists($this, $req)) { 71 | return $this->{$req}(); 72 | } 73 | } 74 | 75 | if (!$req) { 76 | jMessage::add('Please add or check the value of the REQUEST parameter', 'OperationNotSupported'); 77 | } else { 78 | jMessage::add('Request '.$req.' is not supported', 'OperationNotSupported'); 79 | } 80 | 81 | return $this->serviceException(501); 82 | } 83 | 84 | protected function constructUrl() 85 | { 86 | $url = $this->wps_url.'ows/'; 87 | if (strpos($url, '?') === false) { 88 | $url .= '?'; 89 | } 90 | 91 | $params = array(); 92 | foreach ($this->params as $k => $v) { 93 | if ($k !== '__httpbody') { 94 | $params[$k] = $v; 95 | } 96 | } 97 | 98 | if ($this->wps_rootDirectories 99 | && array_key_exists('repository', $params) 100 | && array_key_exists('project', $params)) { 101 | $project = $params['project']; 102 | $repository = $params['repository']; 103 | $lproj = lizmap::getProject($repository.'~'.$project); 104 | if ($lproj) { 105 | $mapParam = $lproj->getPath(); 106 | if (strpos($mapParam, $this->wps_rootDirectories) === 0) { 107 | $mapParam = str_replace($this->wps_rootDirectories, '', $mapParam); 108 | $mapParam = ltrim($mapParam, '/'); 109 | $params['map'] = $mapParam; 110 | unset($params['project'] , $params['repository']); 111 | } 112 | } 113 | } 114 | 115 | if (!array_key_exists('service', $params)) { 116 | $params['service'] = 'WPS'; 117 | } 118 | 119 | $bparams = http_build_query($params); 120 | 121 | // replace some chars (not needed in php 5.4, use the 4th parameter of http_build_query) 122 | $a = array('+', '_', '.', '-'); 123 | $b = array('%20', '%5F', '%2E', '%2D'); 124 | $bparams = str_replace($a, $b, $bparams); 125 | 126 | return $url.$bparams; 127 | } 128 | 129 | protected function process_getcapabilities() 130 | { 131 | $result = $this->doRequest(); 132 | 133 | if (!$result) { 134 | jMessage::add('Server Error !', 'Error'); 135 | 136 | return $this->serviceException(); 137 | } 138 | 139 | $data = $result->data; 140 | if (empty($data)) { 141 | jMessage::add('Server Error !', 'Error'); 142 | 143 | return $this->serviceException(); 144 | } 145 | 146 | if (preg_match('#ServiceExceptionReport#i', $data)) { 147 | return $result; 148 | } 149 | 150 | // Replace qgis server url in the XML (hide real location) 151 | $sUrl = jUrl::getFull( 152 | 'wps~service:index' 153 | ); 154 | $sUrl = str_replace('&', '&', $sUrl); 155 | preg_match('/.*\n*.+xlink\:href="([^"]+)"/i', $data, $matches); 156 | if (count($matches) < 2) { 157 | preg_match('/get onlineresource="([^"]+)"/i', $data, $matches); 158 | } 159 | if (count($matches) > 1) { 160 | $data = str_replace($matches[1], $sUrl, $data); 161 | } 162 | $data = str_replace('&&', '&', $data); 163 | 164 | return (object) array( 165 | 'code' => 200, 166 | 'mime' => $result->mime, 167 | 'data' => $data, 168 | 'cached' => false, 169 | ); 170 | } 171 | 172 | protected function process_describeprocess() 173 | { 174 | $result = $this->doRequest(); 175 | 176 | if (!$result) { 177 | jMessage::add('Server Error !', 'Error'); 178 | 179 | return $this->serviceException(); 180 | } 181 | 182 | $data = $result->data; 183 | if (empty($data)) { 184 | jMessage::add('Server Error !', 'Error'); 185 | 186 | return $this->serviceException(); 187 | } 188 | 189 | return $result; 190 | } 191 | 192 | protected function process_execute() 193 | { 194 | $result = $this->doRequest(); 195 | 196 | if (!$result) { 197 | jMessage::add('Server Error !', 'Error'); 198 | 199 | return $this->serviceException(); 200 | } 201 | 202 | $data = $result->data; 203 | if (empty($data)) { 204 | jMessage::add('Server Error !', 'Error'); 205 | 206 | return $this->serviceException(); 207 | } 208 | 209 | preg_match_all('/wps:Reference.*(?:xlink:)?href="([^"]+)"/i', $data, $matches); 210 | if (count($matches) > 0) { 211 | $wps_url = ltrim($this->wps_url, '/'); 212 | $store_url = $wps_url.'store/'; 213 | foreach ($matches[1] as $oUrl) { 214 | if (substr($oUrl, 0, strlen($store_url)) === $store_url) { 215 | $exUrl = explode('/', explode('?', substr($oUrl, strlen($store_url)))[0]); 216 | $sUrl = jUrl::getFull( 217 | 'wps~service:store', 218 | array( 219 | 'uuid' => $exUrl[0], 220 | 'file' => $exUrl[1], 221 | ) 222 | ); 223 | $sUrl = str_replace('&', '&', $sUrl); 224 | $data = str_replace($oUrl, $sUrl, $data); 225 | } elseif ($ows_url && $ows_url !== '' 226 | && substr($oUrl, 0, strlen($ows_url)) === $ows_url) { 227 | $sUrl = jUrl::getFull( 228 | 'wps~ows:index' 229 | ); 230 | $sUrl = str_replace('&', '&', $sUrl); 231 | $sUrl .= '?'.explode('?', substr($oUrl, strlen($ows_url)))[1]; 232 | $data = str_replace($oUrl, $sUrl, $data); 233 | } 234 | } 235 | $data = str_replace('&&', '&', $data); 236 | } 237 | 238 | return (object) array( 239 | 'code' => $result->code, 240 | 'mime' => $result->mime, 241 | 'data' => $data, 242 | 'cached' => false, 243 | ); 244 | } 245 | 246 | protected function process_getresults() 247 | { 248 | $result = $this->doRequest(); 249 | 250 | if (!$result) { 251 | jMessage::add('Server Error !', 'Error'); 252 | 253 | return $this->serviceException(); 254 | } 255 | 256 | $data = $result->data; 257 | if (empty($data)) { 258 | jMessage::add('Server Error !', 'Error'); 259 | 260 | return $this->serviceException(); 261 | } 262 | 263 | preg_match_all('/wps:Reference.*(?:xlink:)?href="([^"]+)"/i', $data, $matches); 264 | if (count($matches) > 0) { 265 | $ows_url = ltrim($this->ows_url, '/'); 266 | $wps_url = ltrim($this->wps_url, '/'); 267 | $store_url = $wps_url.'store/'; 268 | $jobs_url = $wps_url.'jobs/'; 269 | foreach ($matches[1] as $oUrl) { 270 | \jLog::log($oUrl); 271 | if (substr($oUrl, 0, strlen($store_url)) === $store_url) { 272 | $exUrl = explode('/', explode('?', substr($oUrl, strlen($store_url)))[0]); 273 | $sUrl = jUrl::getFull( 274 | 'wps~service:store', 275 | array( 276 | 'uuid' => $exUrl[0], 277 | 'file' => $exUrl[1], 278 | ) 279 | ); 280 | $sUrl = str_replace('&', '&', $sUrl); 281 | $data = str_replace($oUrl, $sUrl, $data); 282 | } elseif (substr($oUrl, 0, strlen($jobs_url)) === $jobs_url) { 283 | $exUrl = explode('/', explode('?', substr($oUrl, strlen($jobs_url)))[0]); 284 | if (count($exUrl) > 2 && $exUrl[1] == 'files') { 285 | $fUrl = jUrl::getFull( 286 | 'wps~service:files', 287 | array( 288 | 'uuid' => $exUrl[0], 289 | 'file' => $exUrl[2], 290 | ) 291 | ); 292 | $fUrl = str_replace('&', '&', $fUrl); 293 | $data = str_replace($oUrl, $fUrl, $data); 294 | } 295 | } elseif ($ows_url && $ows_url !== '' 296 | && substr($oUrl, 0, strlen($ows_url)) === $ows_url) { 297 | $sUrl = jUrl::getFull( 298 | 'wps~ows:index' 299 | ); 300 | $sUrl = str_replace('&', '&', $sUrl); 301 | $sUrl .= '?'.explode('?', substr($oUrl, strlen($ows_url) - 1))[1]; 302 | $data = str_replace($oUrl, $sUrl, $data); 303 | } elseif ($ows_url && $ows_url !== '' 304 | && substr($oUrl, 0, strlen($wps_url)) === $wps_url 305 | && str_contains($oUrl, 'MAP=') 306 | && str_contains($oUrl, 'request=GetCapabilities')) { 307 | $sUrl = jUrl::getFull( 308 | 'wps~ows:index' 309 | ); 310 | $sUrl = str_replace('&', '&', $sUrl); 311 | $sUrl .= '?'.explode('?', substr($oUrl, strlen($wps_url) - 1))[1]; 312 | $data = str_replace($oUrl, $sUrl, $data); 313 | } elseif ($ows_url && $ows_url !== '' 314 | && $oUrl[0] === '?' 315 | && str_contains($oUrl, 'MAP=') 316 | && str_contains($oUrl, 'request=GetCapabilities')) { 317 | $sUrl = jUrl::getFull( 318 | 'wps~ows:index' 319 | ); 320 | $sUrl = str_replace('&', '&', $sUrl); 321 | $sUrl .= $oUrl; 322 | $data = str_replace($oUrl, $sUrl, $data); 323 | } 324 | } 325 | $data = str_replace('&&', '&', $data); 326 | } 327 | 328 | return (object) array( 329 | 'code' => $result->code, 330 | 'mime' => $result->mime, 331 | 'data' => $data, 332 | 'cached' => false, 333 | ); 334 | } 335 | 336 | /** 337 | * @return array 338 | */ 339 | protected function doRequest() 340 | { 341 | $querystring = $this->constructUrl(); 342 | 343 | $headers = $this->userHttpHeader(); 344 | $headers['Connection'] = 'close'; 345 | 346 | if ($this->xml_post !== null) { 347 | $headers['Content-Type'] = 'text/xml'; 348 | $options = array( 349 | 'method' => 'post', 350 | 'headers' => $headers, 351 | 'body' => $this->xml_post, 352 | ); 353 | } else { 354 | $options = array( 355 | 'method' => 'get', 356 | 'headers' => $headers, 357 | ); 358 | } 359 | 360 | // launch request 361 | list($data, $mime, $code) = lizmapProxy::getRemoteData( 362 | $querystring, 363 | $options 364 | ); 365 | 366 | return (object) array( 367 | 'code' => $code, 368 | 'mime' => $mime, 369 | 'data' => $data, 370 | 'cached' => false, 371 | ); 372 | } 373 | 374 | protected function userHttpHeader() 375 | { 376 | // Check if a user is authenticated 377 | if (!jAuth::isConnected()) { 378 | // return empty header array 379 | return array(); 380 | } 381 | 382 | $user = jAuth::getUserSession(); 383 | $userGroups = jAcl2DbUserGroup::getGroups(); 384 | 385 | $headers = array( 386 | 'X-Lizmap-User' => $user->login, 387 | 'X-Lizmap-User-Groups' => implode(', ', $userGroups), 388 | ); 389 | 390 | $wpsConfig = jApp::config()->wps; 391 | if (array_key_exists('restrict_to_authenticated_users', $wpsConfig) 392 | && $wpsConfig['restrict_to_authenticated_users'] 393 | && array_key_exists('enable_job_realm', $wpsConfig) 394 | && $wpsConfig['enable_job_realm'] 395 | && array_key_exists('repository', $this->params) 396 | && array_key_exists('project', $this->params)) { 397 | $project = $this->params['project']; 398 | $repository = $this->params['repository']; 399 | $lrep = lizmap::getRepository($repository); 400 | $lproj = lizmap::getProject($repository.'~'.$project); 401 | $realm = jApp::coord()->request->getDomainName() 402 | .'~'.$lrep->getKey() 403 | .'~'.$lproj->getKey() 404 | .'~'.jAuth::getUserSession()->login; 405 | $headers['X-Job-Realm'] = sha1($realm); 406 | 407 | if ($this->param('request') == 'getresults' 408 | && jAcl2::check('lizmap.admin.access') 409 | && array_key_exists('admin_job_realm', $wpsConfig) 410 | && $wpsConfig['admin_job_realm'] 411 | ) { 412 | $headers['X-Job-Realm'] = $wpsConfig['admin_job_realm']; 413 | } 414 | } 415 | 416 | return $headers; 417 | } 418 | } 419 | -------------------------------------------------------------------------------- /wps/classes/processStatus.class.php: -------------------------------------------------------------------------------- 1 | available = self::isAvailable(); 26 | 27 | if (!$this->available) { 28 | return; 29 | } 30 | 31 | self::declareRedisProfile(); 32 | $this->db = jKVDb::getConnection(self::$profile); 33 | $wps_url = jApp::config()->wps['wps_rootUrl']; 34 | $wps_url = ltrim($wps_url, '/'); 35 | if (substr($wps_url, -1) != '/') { 36 | $wps_url .= '/'; 37 | } 38 | 39 | $this->url = $wps_url.'status/'; 40 | } 41 | 42 | public function saved($identifier, $repository, $project) 43 | { 44 | if (!$this->available) { 45 | return array(); 46 | } 47 | 48 | if (!self::isAvailableForProject($repository, $project)) { 49 | return array(); 50 | } 51 | 52 | $url = $this->url.'?SERVICE=WPS'; 53 | $options = array( 54 | 'method' => 'get', 55 | 'headers' => self::userHttpHeader($repository, $project), 56 | ); 57 | list($data, $mime, $code) = lizmapProxy::getRemoteData($url, $options); 58 | 59 | if (empty($data) or floor($code / 100) >= 4) { 60 | jLog::log('Status get all is empty or failed with code '.$code, 'errors'); 61 | 62 | $data = array(); 63 | } 64 | 65 | $wpsConfig = jApp::config()->wps; 66 | $realm = null; 67 | if (array_key_exists('restrict_to_authenticated_users', $wpsConfig) 68 | && $wpsConfig['restrict_to_authenticated_users'] 69 | && array_key_exists('enable_job_realm', $wpsConfig) 70 | && $wpsConfig['enable_job_realm'] 71 | && array_key_exists('X-Job-Realm', $options['headers'])) { 72 | $realm = $options['headers']['X-Job-Realm']; 73 | } 74 | $adminRealm = $wpsConfig['admin_job_realm']; 75 | $data = json_decode($data); 76 | 77 | if (property_exists($data, 'status')) { 78 | $uuids = array(); 79 | foreach ($data->status as $s) { 80 | if ($realm === null 81 | || $realm === $adminRealm 82 | || $s->realm === $realm) { 83 | $uuids[] = $s->uuid; 84 | } 85 | } 86 | $data = $uuids; 87 | } else { 88 | $data = array(); 89 | } 90 | 91 | $saved = $this->getFromDb($identifier, $repository, $project); 92 | 93 | if (!$saved) { 94 | return array(); 95 | } 96 | 97 | if (count($saved) > 0) { 98 | $uuids = array(); 99 | foreach ($data as $d) { 100 | if (in_array($d, $saved)) { 101 | $uuids[] = $d; 102 | } 103 | } 104 | 105 | return $uuids; 106 | } 107 | 108 | return array(); 109 | } 110 | 111 | public function get($identifier, $repository, $project, $uuid) 112 | { 113 | if (!$this->available) { 114 | return null; 115 | } 116 | 117 | if (!self::isAvailableForProject($repository, $project)) { 118 | return null; 119 | } 120 | 121 | $url = $this->url.$uuid.'?SERVICE=WPS'; 122 | $options = array( 123 | 'method' => 'get', 124 | 'headers' => self::userHttpHeader($repository, $project), 125 | ); 126 | list($data, $mime, $code) = lizmapProxy::getRemoteData($url, $options); 127 | if (empty($data) or floor($code / 100) >= 4) { 128 | jLog::log('Status get '.$uuid.' is empty or failed with code '.$code, 'errors'); 129 | 130 | return null; 131 | } 132 | 133 | $status = $this->getFromDb($identifier, $repository, $project, $uuid); 134 | if (!$status) { 135 | jLog::log('Status get '.$uuid.' not in db', 'errors'); 136 | 137 | return null; 138 | } 139 | 140 | return $status; 141 | } 142 | 143 | public function update($identifier, $repository, $project, $uuid, $status) 144 | { 145 | if (!$this->available) { 146 | return false; 147 | } 148 | 149 | if (!self::isAvailableForProject($repository, $project)) { 150 | return false; 151 | } 152 | 153 | return $this->setToDb($identifier, $repository, $project, $uuid, $status); 154 | } 155 | 156 | public function delete($identifier, $repository, $project, $uuid) 157 | { 158 | if (!$this->available) { 159 | return false; 160 | } 161 | 162 | if (!self::isAvailableForProject($repository, $project)) { 163 | return false; 164 | } 165 | 166 | return $this->setToDb($identifier, $repository, $project, $uuid); 167 | } 168 | 169 | protected function getFromDb($identifier, $repository, $project, $uuid = null) 170 | { 171 | // Get the list of uuids saved in db 172 | $saved = $this->db->get($identifier.':'.$repository.':'.$project); 173 | 174 | if (!$saved && !$uuid) { 175 | // the list of uuids is empty and no uuid provided 176 | // return an empty list, it is probably the first time 177 | // db is requested 178 | return array(); 179 | } 180 | if (!$saved && $uuid) { 181 | // the list of uuids is empty and a uuid provided 182 | // log message and set an empty array 183 | jLog::log('Status getFromDb '.$identifier.':'.$repository.':'.$project.' not in db'); 184 | $saved = array(); 185 | } else { 186 | // the list of uuids is not empty in db 187 | // transform to an aray and removed empty string 188 | $saved = explode(',', $saved); 189 | $saved = array_filter($saved, function ($s) { 190 | return strlen($s) != 0; 191 | }); 192 | } 193 | 194 | // No uuid provided, returns the list of uuids as an array 195 | if (!$uuid) { 196 | return $saved; 197 | } 198 | 199 | // Get the status from DB 200 | $status = $this->db->get($uuid); 201 | if (!$status) { 202 | jLog::log('Status getFromDb '.$uuid.' not in db'); 203 | 204 | $this->setToDb($identifier, $repository, $project, $uuid); 205 | 206 | return null; 207 | } 208 | $this->setToDb($identifier, $repository, $project, $uuid, $status); 209 | 210 | return json_decode($status); 211 | } 212 | 213 | public function setToDb($identifier, $repository, $project, $uuid, $status = null) 214 | { 215 | // Get list of uuids 216 | $saved = $this->getFromDb($identifier, $repository, $project); 217 | 218 | // if status is null, update the db by removing uuid from list and status in db associated 219 | if ($status === null) { 220 | if (!in_array($uuid, $saved)) { 221 | // check if uuid is in db and removed it 222 | if ($this->db->get($uuid)) { 223 | $this->db->delete($uuid); 224 | 225 | return true; 226 | } 227 | // Nothing has been done 228 | return false; 229 | } 230 | 231 | // Reduced the list of uuids 232 | unset($saved[array_search($uuid, $saved)]); 233 | 234 | // removed uuid and saved new uuids list 235 | $this->db->delete($uuid); 236 | $this->db->set($identifier.':'.$repository.':'.$project, implode(',', $saved)); 237 | 238 | return true; 239 | } 240 | 241 | // Adding uuid to the list if needed 242 | if (!in_array($uuid, $saved)) { 243 | $saved[] = $uuid; 244 | } 245 | 246 | // Save status associated to the uuid to the db 247 | if (is_object($status) || is_array($status)) { 248 | $this->db->set($uuid, json_encode($status)); 249 | } else { 250 | $this->db->set($uuid, $status); 251 | } 252 | 253 | // Save list of uuids 254 | $this->db->set($identifier.':'.$repository.':'.$project, implode(',', $saved)); 255 | 256 | return true; 257 | } 258 | 259 | protected static function declareRedisProfile() 260 | { 261 | $wpsConfig = jApp::config()->wps; 262 | 263 | $statusRedisHost = $wpsConfig['redis_host']; 264 | $statusRedisPort = $wpsConfig['redis_port']; 265 | $statusRedisKeyPrefix = $wpsConfig['redis_key_prefix']; 266 | $statusRedisDb = $wpsConfig['redis_db']; 267 | 268 | if (extension_loaded('redis')) { 269 | $driver = 'redis_ext'; 270 | } else { 271 | $driver = 'redis_php'; 272 | } 273 | 274 | // Virtual status profile parameter 275 | $statusParams = array( 276 | 'driver' => $driver, 277 | 'host' => $statusRedisHost, 278 | 'port' => $statusRedisPort, 279 | 'key_prefix' => $statusRedisKeyPrefix, 280 | 'db' => $statusRedisDb, 281 | ); 282 | 283 | // Create the virtual status profile 284 | jProfiles::createVirtualProfile('jkvdb', self::$profile, $statusParams); 285 | } 286 | 287 | protected static function isAvailable() 288 | { 289 | // WPS Config 290 | $wpsConfig = jApp::config()->wps; 291 | 292 | // get wps rootDirectories 293 | $rootDirectories = $wpsConfig['wps_rootDirectories']; 294 | if (!$rootDirectories) { 295 | return false; 296 | } 297 | 298 | // WPS only available to authenticated users 299 | if (array_key_exists('restrict_to_authenticated_users', $wpsConfig) 300 | && $wpsConfig['restrict_to_authenticated_users'] 301 | && !jAuth::isConnected()) { 302 | return false; 303 | } 304 | 305 | return true; 306 | } 307 | 308 | protected static function isAvailableForProject($repository, $project) 309 | { 310 | // WPS Config 311 | $wpsConfig = jApp::config()->wps; 312 | 313 | // get wps rootDirectories 314 | $rootDirectories = $wpsConfig['wps_rootDirectories']; 315 | if (!$rootDirectories) { 316 | return false; 317 | } 318 | 319 | $lrep = lizmap::getRepository($repository); 320 | if (!$lrep) { 321 | return false; 322 | } 323 | 324 | if (strpos($lrep->getPath(), $rootDirectories) !== 0) { 325 | return false; 326 | } 327 | 328 | $lproj = lizmap::getProject($repository.'~'.$project); 329 | if (!$lproj) { 330 | return false; 331 | } 332 | 333 | // WPS only available for configured projects 334 | if (array_key_exists('restrict_to_config_projects', $wpsConfig) 335 | && $wpsConfig['restrict_to_config_projects'] 336 | && !file_exists($lproj->getQgisPath().'.json')) { 337 | return false; 338 | } 339 | 340 | return true; 341 | } 342 | 343 | public function allFromServer($identifier, $repository, $project) 344 | { 345 | $url = $this->url.'?SERVICE=WPS'; 346 | $headers = $this->userHttpHeader($repository, $project); 347 | $options = array( 348 | 'method' => 'get', 349 | 'headers' => $headers, 350 | ); 351 | list($data, $mime, $code) = lizmapProxy::getRemoteData($url, $options); 352 | 353 | if (empty($data) or floor($code / 100) >= 4) { 354 | $data = array(); 355 | } else { 356 | $data = json_decode($data); 357 | } 358 | 359 | return $data; 360 | } 361 | 362 | protected static function userHttpHeader($repository, $project) 363 | { 364 | // Check if a user is authenticated 365 | if (!jAuth::isConnected()) { 366 | // return empty header array 367 | return array(); 368 | } 369 | 370 | $user = jAuth::getUserSession(); 371 | $userGroups = jAcl2DbUserGroup::getGroups(); 372 | 373 | $headers = array( 374 | 'X-Lizmap-User' => $user->login, 375 | 'X-Lizmap-User-Groups' => implode(', ', $userGroups), 376 | ); 377 | 378 | $wpsConfig = jApp::config()->wps; 379 | if (array_key_exists('restrict_to_authenticated_users', $wpsConfig) 380 | && $wpsConfig['restrict_to_authenticated_users'] 381 | && array_key_exists('enable_job_realm', $wpsConfig) 382 | && $wpsConfig['enable_job_realm'] 383 | ) { 384 | $lrep = lizmap::getRepository($repository); 385 | $lproj = lizmap::getProject($repository.'~'.$project); 386 | $realm = jApp::coord()->request->getDomainName() 387 | .'~'.$lrep->getKey() 388 | .'~'.$lproj->getKey() 389 | .'~'.jAuth::getUserSession()->login; 390 | $headers['X-Job-Realm'] = sha1($realm); 391 | 392 | if (jAcl2::check('lizmap.admin.access') 393 | && array_key_exists('admin_job_realm', $wpsConfig) 394 | && $wpsConfig['admin_job_realm'] 395 | ) { 396 | $headers['X-Job-Realm'] = $wpsConfig['admin_job_realm']; 397 | } 398 | } 399 | 400 | return $headers; 401 | } 402 | } 403 | -------------------------------------------------------------------------------- /wps/classes/wps.listener.php: -------------------------------------------------------------------------------- 1 | isAvailable($event)) { 10 | return; 11 | } 12 | 13 | $js = array( 14 | jUrl::get('jelix~www:getfile', array('targetmodule' => 'wps', 'file' => 'OpenLayers/Request.js')), 15 | jUrl::get('jelix~www:getfile', array('targetmodule' => 'wps', 'file' => 'OpenLayers/Request/XMLHttpRequest.js')), 16 | jUrl::get('jelix~www:getfile', array('targetmodule' => 'wps', 'file' => 'OpenLayers/Format/OWSCommon.js')), 17 | jUrl::get('jelix~www:getfile', array('targetmodule' => 'wps', 'file' => 'OpenLayers/Format/OWSCommon/v1.js')), 18 | jUrl::get('jelix~www:getfile', array('targetmodule' => 'wps', 'file' => 'OpenLayers/Format/OWSCommon/v1_0_0.js')), 19 | jUrl::get('jelix~www:getfile', array('targetmodule' => 'wps', 'file' => 'OpenLayers/Format/OWSCommon/v1_1_0.js')), 20 | jUrl::get('jelix~www:getfile', array('targetmodule' => 'wps', 'file' => 'OpenLayers/Format/GML.js')), 21 | jUrl::get('jelix~www:getfile', array('targetmodule' => 'wps', 'file' => 'OpenLayers/Format/GML/Base.js')), 22 | jUrl::get('jelix~www:getfile', array('targetmodule' => 'wps', 'file' => 'OpenLayers/Format/GML/v2.js')), 23 | jUrl::get('jelix~www:getfile', array('targetmodule' => 'wps', 'file' => 'OpenLayers/Format/GML/v3.js')), 24 | jUrl::get('jelix~www:getfile', array('targetmodule' => 'wps', 'file' => 'OpenLayers/Format/Filter.js')), 25 | jUrl::get('jelix~www:getfile', array('targetmodule' => 'wps', 'file' => 'OpenLayers/Format/Filter/v1.js')), 26 | jUrl::get('jelix~www:getfile', array('targetmodule' => 'wps', 'file' => 'OpenLayers/Format/Filter/v1_1_0.js')), 27 | jUrl::get('jelix~www:getfile', array('targetmodule' => 'wps', 'file' => 'OpenLayers/Format/WCSGetCoverage.js')), 28 | jUrl::get('jelix~www:getfile', array('targetmodule' => 'wps', 'file' => 'OpenLayers/Format/WFST.js')), 29 | jUrl::get('jelix~www:getfile', array('targetmodule' => 'wps', 'file' => 'OpenLayers/Format/WFST/v1.js')), 30 | jUrl::get('jelix~www:getfile', array('targetmodule' => 'wps', 'file' => 'OpenLayers/Format/WFST/v1_1_0.js')), 31 | jUrl::get('jelix~www:getfile', array('targetmodule' => 'wps', 'file' => 'OpenLayers/Format/WPSDescribeProcess.js')), 32 | jUrl::get('jelix~www:getfile', array('targetmodule' => 'wps', 'file' => 'OpenLayers/Format/WPSExecute.js')), 33 | jUrl::get('jelix~www:getfile', array('targetmodule' => 'wps', 'file' => 'OpenLayers/Format/WPSCapabilities.js')), 34 | jUrl::get('jelix~www:getfile', array('targetmodule' => 'wps', 'file' => 'OpenLayers/Format/WPSCapabilities/v1_0_0.js')), 35 | jUrl::get('jelix~www:getfile', array('targetmodule' => 'wps', 'file' => 'wps.js')), 36 | ); 37 | $jscode = array( 38 | ); 39 | $jsvars = array( 40 | 'lizWpsUrls' => array( 41 | 'wps_wps' => jUrl::get('wps~service:index'), 42 | 'wps_wps_results' => jUrl::get('wps~results:index'), 43 | 'wps_wps_results_update' => jUrl::get('wps~results:update'), 44 | 'wps_wps_results_delete' => jUrl::get('wps~results:delete'), 45 | 'wps_wps_status' => jUrl::get('wps~service:status'), 46 | 'wps_wps_store' => jUrl::get('wps~service:store'), 47 | ), 48 | ); 49 | $css = array( 50 | jUrl::get('jelix~www:getfile', array('targetmodule' => 'wps', 'file' => 'wps.css')), 51 | ); 52 | 53 | // Add Dataviz if not already available 54 | if (!$this->getDatavizStatus($event)) { 55 | $bp = jApp::urlBasePath(); 56 | $js[] = $bp.'assets/js/dataviz/plotly-latest.min.js'; 57 | $js[] = $bp.'assets/js/dataviz/dataviz.js'; 58 | } 59 | 60 | // Check if there is a processing configuration for this project 61 | $path = $this->lproj->getPath().'.json'; 62 | $rconfig = jFile::read($path); 63 | if (!empty($rconfig)) { 64 | $config = json_decode($rconfig); 65 | $je = json_last_error(); 66 | if ($je === JSON_ERROR_NONE && is_object($config)) { 67 | $jsvars = array_merge($jsvars, array('wps_wps_project_config' => $config)); 68 | } else { 69 | $errorMsg = 'Error in processing configuration file: '.$path; 70 | $errorMsg .= ' - Error code: '.$je.' - '.json_last_error_msg(); 71 | if ($je === JSON_ERROR_NONE) { 72 | $errorMsg .= ' but parsing result is not an object'; 73 | } 74 | jLog::log($errorMsg, 'error'); 75 | } 76 | } 77 | 78 | // Add translation 79 | // $locales = $this->getLocales(); 80 | // $jscode[] = 'var wpsLocales = '.json_encode($locales).';'; 81 | 82 | $event->add( 83 | array( 84 | 'js' => $js, 85 | 'jsvars' => $jsvars, 86 | 'jscode' => $jscode, 87 | 'css' => $css, 88 | ) 89 | ); 90 | } 91 | 92 | public function onmapDockable($event) 93 | { 94 | if (!$this->isAvailable($event)) { 95 | return; 96 | } 97 | 98 | // Use template dock 99 | $assign = array(); 100 | $content = array('wps~dock', $assign); 101 | $dock = new lizmapMapDockItem( 102 | 'processing', 103 | \jLocale::get('wps~wps.dock.main.title'), 104 | $content, 105 | 15, 106 | null, // done with getMapAdditions 107 | null 108 | ); 109 | $event->add($dock); 110 | } 111 | 112 | public function onmapBottomDockable($event) 113 | { 114 | if (!$this->isAvailable($event)) { 115 | return; 116 | } 117 | 118 | // Use template dataviz-dock 119 | $assign = array(); 120 | $content = array('wps~bottomdock', $assign); 121 | $dock = new lizmapMapDockItem( 122 | 'processing-results', 123 | \jLocale::get('wps~wps.dock.results.title'), 124 | $content, 125 | 15, 126 | null, // done with getMapAdditions 127 | null 128 | ); 129 | $event->add($dock); 130 | } 131 | 132 | protected function isAvailable($event) 133 | { 134 | // WPS Config 135 | $wpsConfig = jApp::config()->wps; 136 | 137 | // get wps rootDirectories 138 | $rootDirectories = $wpsConfig['wps_rootDirectories']; 139 | if (!$rootDirectories) { 140 | return false; 141 | } 142 | 143 | // WPS only available to authenticated users 144 | if (array_key_exists('restrict_to_authenticated_users', $wpsConfig) 145 | && $wpsConfig['restrict_to_authenticated_users'] 146 | && !jAuth::isConnected()) { 147 | return false; 148 | } 149 | 150 | $project = $event->getParam('project'); 151 | $repository = $event->getParam('repository'); 152 | 153 | $lrep = lizmap::getRepository($repository); 154 | if (!$lrep) { 155 | return false; 156 | } 157 | 158 | if (strpos($lrep->getPath(), $rootDirectories) !== 0) { 159 | return false; 160 | } 161 | 162 | $lproj = lizmap::getProject($repository.'~'.$project); 163 | if (!$lproj) { 164 | return false; 165 | } 166 | 167 | $this->lproj = $lproj; 168 | 169 | // WPS only available for configured projects 170 | if (array_key_exists('restrict_to_config_projects', $wpsConfig) 171 | && $wpsConfig['restrict_to_config_projects'] 172 | && !file_exists($lproj->getQgisPath().'.json')) { 173 | return false; 174 | } 175 | 176 | return true; 177 | } 178 | 179 | protected function getDatavizStatus($event) 180 | { 181 | $project = $event->getParam('project'); 182 | $repository = $event->getParam('repository'); 183 | 184 | // Check dataviz config 185 | jClasses::inc('dataviz~datavizConfig'); 186 | $dv = new datavizConfig($repository, $project); 187 | 188 | return $dv->getStatus(); 189 | } 190 | 191 | protected function onmasteradminGetMenuContent($event) 192 | { 193 | // new section 194 | $sectionAuth = new masterAdminMenuItem('wps_admin', \jLocale::get('wps~wps.ui.admin.menu.group'), '', 150); 195 | 196 | if (jAcl2::check('wps.modelfile.manage')) { 197 | // add config page 198 | $sectionAuth->childItems[] = new masterAdminMenuItem('wps_admin_upload', \jLocale::get('wps~wps.ui.admin.menu.model3list'), jUrl::get('wps~admin:list'), 150, 'wps_admin'); 199 | } 200 | if (jAcl2::check('wps.options.manage')) { 201 | // add config page for projects restriction options 202 | $sectionAuth->childItems[] = new masterAdminMenuItem('wps_proj_restrict', \jLocale::get('wps~wps.ui.admin.menu.project_restriction'), jUrl::get('wps~restrictionsAdmin:show'), 160, 'wps_admin'); 203 | } 204 | $event->add($sectionAuth); 205 | } 206 | 207 | private function getLocales() 208 | { 209 | $data = array(); 210 | $path = jApp::getModulePath('wps').'locales/en_US/wps.UTF-8.properties'; 211 | if (file_exists($path)) { 212 | $lines = file($path); 213 | foreach ($lines as $lineNumber => $lineContent) { 214 | if (!empty($lineContent) and $lineContent != '\n') { 215 | $exp = explode('=', trim($lineContent)); 216 | if (!empty($exp[0])) { 217 | $data[$exp[0]] = jLocale::get('wps~wps.'.$exp[0]); 218 | } 219 | } 220 | } 221 | } 222 | 223 | return $data; 224 | } 225 | } 226 | -------------------------------------------------------------------------------- /wps/classes/wpsOGCRequest.class.php: -------------------------------------------------------------------------------- 1 | services = lizmap::getServices(); 35 | $nParams = lizmapProxy::normalizeParams($params); 36 | foreach ($params as $k => $v) { 37 | if (strtolower($k) === 'repository' || strtolower($k) === 'project') { 38 | $nParams[strtolower($k)] = $v; 39 | } 40 | } 41 | $this->params = $nParams; 42 | $this->xml_post = $xml_post; 43 | 44 | $this->ows_url = jApp::config()->wps['ows_url']; 45 | } 46 | 47 | /** 48 | * Do the process. 49 | * 50 | * @internal we override the process() method of lizmapOGCRequest to be sure 51 | * we have the secure version of the method, in case where the lizmap version 52 | * is <= 3.4.3, <= 3.3.15 53 | * 54 | * @deprecated remove this overrided method when we will mark the module compatible 55 | * only with Lizmap 3.5. 56 | * 57 | * @return array 58 | */ 59 | public function process() 60 | { 61 | $req = $this->param('request'); 62 | if ($req) { 63 | $reqMeth = 'process_'.$req; 64 | if (method_exists($this, $reqMeth)) { 65 | return $this->{$reqMeth}(); 66 | } 67 | } 68 | 69 | if (!$req) { 70 | jMessage::add('Please add or check the value of the REQUEST parameter', 'OperationNotSupported'); 71 | } else { 72 | jMessage::add('Request '.$req.' is not supported', 'OperationNotSupported'); 73 | } 74 | 75 | return $this->serviceException(501); 76 | } 77 | 78 | protected function constructUrl() 79 | { 80 | $url = $this->ows_url; 81 | if (strpos($url, '?') === false) { 82 | $url .= '?'; 83 | } 84 | 85 | $params = array(); 86 | foreach ($this->params as $k => $v) { 87 | if ($k !== '__httpbody') { 88 | $params[$k] = $v; 89 | } 90 | } 91 | 92 | $bparams = http_build_query($params); 93 | 94 | // replace some chars (not needed in php 5.4, use the 4th parameter of http_build_query) 95 | $a = array('+', '_', '.', '-'); 96 | $b = array('%20', '%5F', '%2E', '%2D'); 97 | $bparams = str_replace($a, $b, $bparams); 98 | 99 | return $url.$bparams; 100 | } 101 | 102 | protected function process_getcapabilities() 103 | { 104 | $querystring = $this->constructUrl(); 105 | 106 | // Get remote data 107 | list($data, $mime, $code) = lizmapProxy::getRemoteData($querystring); 108 | 109 | // Retry if 500 error ( hackish, but QGIS Server segfault sometimes with cache issue ) 110 | if ($code == 500) { 111 | // Get remote data 112 | list($data, $mime, $code) = lizmapProxy::getRemoteData($querystring); 113 | } 114 | 115 | return (object) array( 116 | 'code' => $code, 117 | 'mime' => $mime, 118 | 'data' => $data, 119 | 'cached' => false, 120 | ); 121 | } 122 | 123 | /** 124 | * @return array 125 | */ 126 | protected function doRequest() 127 | { 128 | $querystring = $this->constructUrl(); 129 | 130 | if ($this->xml_post !== null) { 131 | $options = array( 132 | 'method' => 'post', 133 | 'headers' => array( 134 | 'Content-Type' => 'text/xml', 135 | ), 136 | 'body' => $this->xml_post, 137 | ); 138 | } else { 139 | $options = array( 140 | 'method' => 'get', 141 | ); 142 | } 143 | 144 | // launch request 145 | list($data, $mime, $code) = lizmapProxy::getRemoteData( 146 | $querystring, 147 | $options 148 | ); 149 | 150 | return (object) array( 151 | 'code' => $code, 152 | 'mime' => $mime, 153 | 'data' => $data, 154 | 'cached' => false, 155 | ); 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /wps/classes/wpsWCSRequest.class.php: -------------------------------------------------------------------------------- 1 | params)) { 19 | $this->params['service'] = 'WCS'; 20 | } 21 | 22 | return parent::constructUrl(); 23 | } 24 | 25 | protected function process_getcapabilities() 26 | { 27 | $result = parent::process_getcapabilities(); 28 | 29 | $data = $result->data; 30 | if (empty($data) or floor($result->code / 100) >= 4) { 31 | jMessage::add('Server Error !', 'Error'); 32 | 33 | return $this->serviceException(); 34 | } 35 | 36 | if (preg_match('#ServiceExceptionReport#i', $data)) { 37 | return $result; 38 | } 39 | 40 | // Replace qgis server url in the XML (hide real location) 41 | $sUrl = jUrl::getFull( 42 | 'wps~ows:index' 43 | ); 44 | $sUrl = str_replace('&', '&', $sUrl); 45 | preg_match('/.*\n*.+xlink\:href="([^"]+)"/i', $data, $matches); 46 | if (count($matches) < 2) { 47 | preg_match('/get onlineresource="([^"]+)"/i', $data, $matches); 48 | } 49 | if (count($matches) < 2) { 50 | preg_match('/ows:get.+xlink\:href="([^"]+)"/i', $data, $matches); 51 | } 52 | if (count($matches) > 1) { 53 | $data = str_replace($matches[1], $sUrl, $data); 54 | } 55 | $data = str_replace('&&', '&', $data); 56 | 57 | return (object) array( 58 | 'code' => 200, 59 | 'mime' => $result->mime, 60 | 'data' => $data, 61 | 'cached' => false, 62 | ); 63 | } 64 | 65 | protected function process_describecoverage() 66 | { 67 | $result = $this->doRequest(); 68 | 69 | if (!$result) { 70 | jMessage::add('Server Error !', 'Error'); 71 | 72 | return $this->serviceException(); 73 | } 74 | 75 | $data = $result->data; 76 | if (empty($data) or floor($result->code / 100) >= 4) { 77 | jMessage::add('Server Error !', 'Error'); 78 | 79 | return $this->serviceException(); 80 | } 81 | 82 | return $result; 83 | } 84 | 85 | protected function process_getcoverage() 86 | { 87 | $result = $this->doRequest(); 88 | 89 | if (!$result) { 90 | jMessage::add('Server Error !', 'Error'); 91 | 92 | return $this->serviceException(); 93 | } 94 | 95 | $data = $result->data; 96 | if (empty($data) or floor($result->code / 100) >= 4) { 97 | jMessage::add('Server Error !', 'Error'); 98 | 99 | return $this->serviceException(); 100 | } 101 | 102 | return $result; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /wps/classes/wpsWFSRequest.class.php: -------------------------------------------------------------------------------- 1 | params)) { 19 | $this->params['service'] = 'WFS'; 20 | } 21 | 22 | return parent::constructUrl(); 23 | } 24 | 25 | protected function process_getcapabilities() 26 | { 27 | $result = parent::process_getcapabilities(); 28 | 29 | $data = $result->data; 30 | if (empty($data) or floor($result->code / 100) >= 4) { 31 | jMessage::add('Server Error !', 'Error'); 32 | 33 | return $this->serviceException(); 34 | } 35 | 36 | if (preg_match('#ServiceExceptionReport#i', $data)) { 37 | return $result; 38 | } 39 | 40 | // Replace qgis server url in the XML (hide real location) 41 | $sUrl = jUrl::getFull( 42 | 'wps~ows:index' 43 | ); 44 | $sUrl = str_replace('&', '&', $sUrl); 45 | preg_match('/.*\n*.+xlink\:href="([^"]+)"/i', $data, $matches); 46 | if (count($matches) < 2) { 47 | preg_match('/get onlineresource="([^"]+)"/i', $data, $matches); 48 | } 49 | if (count($matches) < 2) { 50 | preg_match('/ows:get.+xlink\:href="([^"]+)"/i', $data, $matches); 51 | } 52 | if (count($matches) > 1) { 53 | $data = str_replace($matches[1], $sUrl, $data); 54 | } 55 | $data = str_replace('&&', '&', $data); 56 | 57 | return (object) array( 58 | 'code' => 200, 59 | 'mime' => $result->mime, 60 | 'data' => $data, 61 | 'cached' => false, 62 | ); 63 | } 64 | 65 | protected function process_describefeaturetype() 66 | { 67 | $result = $this->doRequest(); 68 | 69 | if (!$result) { 70 | jMessage::add('Server Error !', 'Error'); 71 | 72 | return $this->serviceException(); 73 | } 74 | 75 | $data = $result->data; 76 | if (empty($data) or floor($result->code / 100) >= 4) { 77 | jMessage::add('Server Error !', 'Error'); 78 | 79 | return $this->serviceException(); 80 | } 81 | 82 | return $result; 83 | } 84 | 85 | protected function process_getfeature() 86 | { 87 | $result = $this->doRequest(); 88 | 89 | if (!$result) { 90 | jMessage::add('Server Error !', 'Error'); 91 | 92 | return $this->serviceException(); 93 | } 94 | 95 | $data = $result->data; 96 | if (empty($data) or floor($result->code / 100) >= 4) { 97 | jMessage::add('Server Error !', 'Error'); 98 | 99 | return $this->serviceException(); 100 | } 101 | 102 | return $result; 103 | } 104 | 105 | protected function process_transaction() 106 | { 107 | $result = $this->doRequest(); 108 | 109 | if (!$result) { 110 | jMessage::add('Server Error !', 'Error'); 111 | 112 | return $this->serviceException(); 113 | } 114 | 115 | $data = $result->data; 116 | if (empty($data) or floor($result->code / 100) >= 4) { 117 | jMessage::add('Server Error !', 'Error'); 118 | 119 | return $this->serviceException(); 120 | } 121 | 122 | return $result; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /wps/classes/wpsWMSRequest.class.php: -------------------------------------------------------------------------------- 1 | params)) { 19 | $this->params['service'] = 'WMS'; 20 | } 21 | 22 | return parent::constructUrl(); 23 | } 24 | 25 | protected function process_getcapabilities() 26 | { 27 | $result = parent::process_getcapabilities(); 28 | 29 | $data = $result->data; 30 | if (empty($data) or floor($result->code / 100) >= 4) { 31 | jMessage::add('Server Error !', 'Error'); 32 | 33 | return $this->serviceException(); 34 | } 35 | 36 | if (preg_match('#ServiceExceptionReport#i', $data)) { 37 | return $result; 38 | } 39 | 40 | // Replace qgis server url in the XML (hide real location) 41 | $sUrl = jUrl::getFull( 42 | 'wps~ows:index' 43 | ); 44 | $sUrl = str_replace('&', '&', $sUrl); 45 | preg_match('/.*\n*.+xlink\:href="([^"]+)"/i', $data, $matches); 46 | if (count($matches) < 2) { 47 | preg_match('/get onlineresource="([^"]+)"/i', $data, $matches); 48 | } 49 | if (count($matches) > 1) { 50 | $data = str_replace($matches[1], $sUrl, $data); 51 | } 52 | $data = str_replace('&&', '&', $data); 53 | 54 | return (object) array( 55 | 'code' => 200, 56 | 'mime' => $result->mime, 57 | 'data' => $data, 58 | 'cached' => false, 59 | ); 60 | } 61 | 62 | protected function process_getmap() 63 | { 64 | $result = $this->doRequest(); 65 | 66 | if (!$result) { 67 | jMessage::add('Server Error !', 'Error'); 68 | 69 | return $this->serviceException(); 70 | } 71 | 72 | $data = $result->data; 73 | if (empty($data) or floor($result->code / 100) >= 4) { 74 | jMessage::add('Server Error !', 'Error'); 75 | 76 | return $this->serviceException(); 77 | } 78 | 79 | return $result; 80 | } 81 | 82 | protected function process_describelayer() 83 | { 84 | $result = $this->doRequest(); 85 | 86 | if (!$result) { 87 | jMessage::add('Server Error !', 'Error'); 88 | 89 | return $this->serviceException(); 90 | } 91 | 92 | return $result; 93 | 94 | $data = $result->data; 95 | if (empty($data) or floor($result->code / 100) >= 4) { 96 | jMessage::add('Server Error !', 'Error'); 97 | 98 | return $this->serviceException(); 99 | } 100 | 101 | return $result; 102 | } 103 | 104 | protected function process_getlegendgraphic() 105 | { 106 | return $this->process_getlegendgraphics(); 107 | } 108 | 109 | protected function process_getlegendgraphics() 110 | { 111 | $result = $this->doRequest(); 112 | 113 | if (!$result) { 114 | jMessage::add('Server Error !', 'Error'); 115 | 116 | return $this->serviceException(); 117 | } 118 | 119 | $data = $result->data; 120 | if (empty($data) or floor($result->code / 100) >= 4) { 121 | jMessage::add('Server Error !', 'Error'); 122 | 123 | return $this->serviceException(); 124 | } 125 | 126 | return $result; 127 | } 128 | 129 | protected function process_getfeatureinfo() 130 | { 131 | $result = $this->doRequest(); 132 | 133 | if (!$result) { 134 | jMessage::add('Server Error !', 'Error'); 135 | 136 | return $this->serviceException(); 137 | } 138 | 139 | $data = $result->data; 140 | if (empty($data) or floor($result->code / 100) >= 4) { 141 | jMessage::add('Server Error !', 'Error'); 142 | 143 | return $this->serviceException(); 144 | } 145 | 146 | return $result; 147 | } 148 | 149 | protected function process_getstyles() 150 | { 151 | $result = $this->doRequest(); 152 | 153 | if (!$result) { 154 | jMessage::add('Server Error !', 'Error'); 155 | 156 | return $this->serviceException(); 157 | } 158 | 159 | $data = $result->data; 160 | if (empty($data) or floor($result->code / 100) >= 4) { 161 | jMessage::add('Server Error !', 'Error'); 162 | 163 | return $this->serviceException(); 164 | } 165 | 166 | return $result; 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /wps/controllers/admin.classic.php: -------------------------------------------------------------------------------- 1 | array('jacl2.right' => 'wps.modelfile.manage'), 10 | ); 11 | 12 | public function showUploadModel() 13 | { 14 | $formID = null; 15 | if (!empty($this->param('fileId'))) { 16 | $formID = $this->param('fileId'); 17 | } 18 | $form = jForms::get('wps~model_upload', $formID); 19 | if (is_null($form)) { 20 | $form = jForms::create('wps~model_upload', $formID); 21 | } 22 | if ($formID != null) { 23 | // file update : ensure it exists and set data 24 | $finder = new WPS\ModelFileManager(); 25 | $file = $finder->findBySHA1($formID); 26 | if ($file === false) { 27 | \jMessage::add(\jLocale::get('wps.message.error.unknow_file'), 'error'); 28 | 29 | return $this->redirect('admin:list'); 30 | } 31 | $formUploadCtrl = $form->getControl('modelfile'); 32 | $formUploadCtrl->setDataFromDao($file->fileName(), 'string'); 33 | } 34 | 35 | /** 36 | * @var jResponseHTML; $resp 37 | */ 38 | $resp = $this->getResponse('html'); 39 | $resp->body->assign('selectedMenuItem', 'wps_admin_upload'); 40 | $tpl = new jTpl(); 41 | $tpl->assign('form', $form); 42 | $tpl->assign('fileId', $formID); 43 | $resp->body->assign('MAIN', $tpl->fetch('admin.model3.showform')); 44 | 45 | return $resp; 46 | } 47 | 48 | public function saveUploadModel() 49 | { 50 | $formID = null; 51 | $newFile = true; 52 | if (!empty($this->param('fileId'))) { 53 | $formID = $this->param('fileId'); 54 | $newFile = false; 55 | } 56 | 57 | /** 58 | * @var jResponseHTML; $resp 59 | */ 60 | $resp = $this->getResponse('redirect'); 61 | $form = jForms::fill('wps~model_upload', $formID); 62 | 63 | if (is_null($form) || !$form->check()) { 64 | return $this->redirect('admin:showUploadModel', array('fileId' => $formID)); 65 | } 66 | $finder = new WPS\ModelFileManager(); 67 | 68 | /** @var \jFormsControlUpload2 $uploadCtrl */ 69 | $uploadCtrl = $form->getControl('modelfile'); 70 | 71 | try { 72 | $finder->saveModel($uploadCtrl, $newFile); 73 | } catch (Exception $e) { 74 | $form->setErrorOn('modelfile', $e->getMessage()); 75 | 76 | return $this->redirect('admin:showUploadModel', array('fileId' => $formID)); 77 | } 78 | if ($newFile) { 79 | \jMessage::add(\jLocale::get('wps.message.ok.file_added'), 'success'); 80 | jForms::destroy('wps~model_upload'); 81 | } else { 82 | \jMessage::add(\jLocale::get('wps.message.ok.file_modified'), 'success'); 83 | jForms::destroy('wps~model_upload', $formID); 84 | } 85 | 86 | $resp->action = 'wps~admin:list'; 87 | 88 | return $resp; 89 | } 90 | 91 | public function confirmDeleteModel() 92 | { 93 | $finder = new WPS\ModelFileManager(); 94 | 95 | $file = $finder->findBySHA1($this->param('fileId')); 96 | if ($file === false) { 97 | \jMessage::add(\jLocale::get('wps.message.error.unknow_file'), 'error'); 98 | 99 | return $this->redirect('admin:list'); 100 | } 101 | 102 | $tpl = \lizmap::getAppContext()->getTpl(); 103 | $tpl->assign('file', $file); 104 | 105 | /** 106 | * @var jResponseHTML; $resp 107 | */ 108 | $resp = $this->getResponse('html'); 109 | $resp->body->assign('MAIN', $tpl->fetch('wps~admin.model3.confirmdelete')); 110 | 111 | return $resp; 112 | } 113 | 114 | public function deleteModel() 115 | { 116 | $finder = new WPS\ModelFileManager(); 117 | 118 | $file = $finder->findBySHA1($this->param('fileId')); 119 | if ($file === false) { 120 | \jMessage::add(\jLocale::get('wps.message.error.unknown_file'), 'error'); 121 | 122 | return $this->redirect('admin:list'); 123 | } 124 | 125 | $finder->deleteModel($file); 126 | \jMessage::add(\jLocale::get('wps.message.ok.file_deleted'), 'success'); 127 | 128 | return $this->redirect('admin:list'); 129 | } 130 | 131 | public function showUploadStyle() 132 | { 133 | $formID = null; 134 | if (!empty($this->param('fileId'))) { 135 | $formID = $this->param('fileId'); 136 | } 137 | $form = jForms::get('wps~style_upload', $formID); 138 | if (is_null($form)) { 139 | $form = jForms::create('wps~style_upload', $formID); 140 | } 141 | if ($formID != null) { 142 | // file update : ensure it exists and set data 143 | $finder = new WPS\ModelFileManager(); 144 | $file = $finder->findBySHA1($formID); 145 | if ($file === false) { 146 | \jMessage::add(\jLocale::get('wps.message.error.unknow_file'), 'error'); 147 | 148 | return $this->redirect('admin:list'); 149 | } 150 | $formUploadCtrl = $form->getControl('stylefile'); 151 | $formUploadCtrl->setDataFromDao($file->fileName(), 'string'); 152 | } 153 | 154 | /** 155 | * @var jResponseHTML; $resp 156 | */ 157 | $resp = $this->getResponse('html'); 158 | $resp->body->assign('selectedMenuItem', 'wps_admin_upload'); 159 | $tpl = new jTpl(); 160 | $tpl->assign('form', $form); 161 | $tpl->assign('fileId', $formID); 162 | $resp->body->assign('MAIN', $tpl->fetch('admin.qml.showform')); 163 | 164 | return $resp; 165 | } 166 | 167 | public function saveUploadStyle() 168 | { 169 | $formID = null; 170 | $newFile = true; 171 | if (!empty($this->param('fileId'))) { 172 | $formID = $this->param('fileId'); 173 | $newFile = false; 174 | } 175 | 176 | /** 177 | * @var jResponseHTML; $resp 178 | */ 179 | $resp = $this->getResponse('redirect'); 180 | $form = jForms::fill('wps~style_upload', $formID); 181 | 182 | if (is_null($form) || !$form->check()) { 183 | return $this->redirect('admin:showUploadStyle', array('fileId' => $formID)); 184 | } 185 | $finder = new WPS\ModelFileManager(); 186 | 187 | /** @var \jFormsControlUpload2 $uploadCtrl */ 188 | $uploadCtrl = $form->getControl('stylefile'); 189 | 190 | try { 191 | $finder->saveStyle($uploadCtrl, $newFile); 192 | } catch (Exception $e) { 193 | $form->setErrorOn('stylefile', $e->getMessage()); 194 | 195 | return $this->redirect('admin:showUploadStyle', array('fileId' => $formID)); 196 | } 197 | if ($newFile) { 198 | \jMessage::add(\jLocale::get('wps.message.ok.file_added'), 'success'); 199 | jForms::destroy('wps~style_upload'); 200 | } else { 201 | \jMessage::add(\jLocale::get('wps.message.ok.file_modified'), 'success'); 202 | jForms::destroy('wps~style_upload', $formID); 203 | } 204 | 205 | $resp->action = 'wps~admin:list'; 206 | 207 | return $resp; 208 | } 209 | 210 | public function confirmDeleteStyle() 211 | { 212 | $finder = new WPS\ModelFileManager(); 213 | 214 | $file = $finder->findBySHA1($this->param('fileId')); 215 | if ($file === false) { 216 | \jMessage::add(\jLocale::get('wps.message.error.unknow_file'), 'error'); 217 | 218 | return $this->redirect('admin:list'); 219 | } 220 | 221 | $tpl = \lizmap::getAppContext()->getTpl(); 222 | $tpl->assign('file', $file); 223 | 224 | /** 225 | * @var jResponseHTML; $resp 226 | */ 227 | $resp = $this->getResponse('html'); 228 | $resp->body->assign('MAIN', $tpl->fetch('wps~admin.qml.confirmdelete')); 229 | 230 | return $resp; 231 | } 232 | 233 | public function deleteStyle() 234 | { 235 | $finder = new WPS\ModelFileManager(); 236 | 237 | $file = $finder->findBySHA1($this->param('fileId')); 238 | if ($file === false) { 239 | \jMessage::add(\jLocale::get('wps.message.error.unknown_file'), 'error'); 240 | 241 | return $this->redirect('admin:list'); 242 | } 243 | 244 | $finder->deleteStyle($file); 245 | \jMessage::add(\jLocale::get('wps.message.ok.file_deleted'), 'success'); 246 | 247 | return $this->redirect('admin:list'); 248 | } 249 | 250 | public function list() 251 | { 252 | /** 253 | * @var jResponseHTML; $resp 254 | */ 255 | $resp = $this->getResponse('html'); 256 | $resp->body->assign('selectedMenuItem', 'wps_admin_upload'); 257 | $tpl = new jTpl(); 258 | $finder = new WPS\ModelFileManager(); 259 | $models = array(); 260 | $styles = array(); 261 | 262 | try { 263 | $models = $finder->getModelFiles(); 264 | } catch (\Exception $e) { 265 | \jMessage::add(\jLocale::get('wps.message.error.model3_path_invalid'), 'error'); 266 | 267 | return $resp; 268 | } 269 | 270 | try { 271 | $styles = $finder->getStyleFiles(); 272 | } catch (\Exception $e) { 273 | \jMessage::add(\jLocale::get('wps.message.error.model3_path_invalid'), 'error'); 274 | 275 | return $resp; 276 | } 277 | $tpl->assign('models', $models); 278 | $tpl->assign('styles', $styles); 279 | $resp->body->assign('MAIN', $tpl->fetch('admin.list')); 280 | 281 | return $resp; 282 | } 283 | } 284 | -------------------------------------------------------------------------------- /wps/controllers/ows.classic.php: -------------------------------------------------------------------------------- 1 | request->params; 29 | $params = lizmapProxy::normalizeParams($pParams); 30 | foreach ($pParams as $k => $v) { 31 | if (strtolower($k) === 'repository' || strtolower($k) === 'project') { 32 | $params[strtolower($k)] = $v; 33 | } 34 | } 35 | $this->params = $params; 36 | 37 | // Get and parsed xml post 38 | $requestXml = $this->param('__httpbody'); 39 | 40 | if ($requestXml) { 41 | $xml = simplexml_load_string($requestXml); 42 | if ($xml !== false) { 43 | $attrs = $xml->attributes(); 44 | if (isset($attrs['service'])) { 45 | $params['service'] = (string) $attrs['service']; 46 | if (isset($attrs['version'])) { 47 | $params['version'] = (string) $attrs['version']; 48 | } 49 | $xml_request = $xml->getName(); 50 | if (strpos($xml_request, ':') !== false) { 51 | $xml_request = explode(':', $xml_request)[1]; 52 | } 53 | $params['request'] = (string) $xml_request; 54 | $this->xml_post = $requestXml; 55 | } 56 | } 57 | } 58 | 59 | // Return the appropriate action 60 | if (!array_key_exists('service', $params)) { 61 | jMessage::add('SERVICE parameter is mandatory!', 'InvalidRequest'); 62 | 63 | return $this->serviceException(); 64 | } 65 | $service = strtoupper($params['service']); 66 | if (!array_key_exists('request', $params)) { 67 | jMessage::add('REQUEST parameter is mandatory!', 'InvalidRequest'); 68 | 69 | return $this->serviceException(); 70 | } 71 | $request = strtolower($params['request']); 72 | 73 | $owsRequest = null; 74 | if ($service === 'WMS') { 75 | $owsRequest = new wpsWMSRequest($params, $this->xml_post); 76 | } elseif ($service === 'WFS') { 77 | $owsRequest = new wpsWFSRequest($params, $this->xml_post); 78 | } elseif ($service === 'WCS') { 79 | $owsRequest = new wpsWCSRequest($params, $this->xml_post); 80 | } 81 | 82 | if ($owsRequest === null) { 83 | jMessage::add('SERVICE '.$service.' not supported', 'InvalidRequest'); 84 | 85 | return $this->serviceException(); 86 | } 87 | 88 | $result = $owsRequest->process(); 89 | 90 | $rep = $this->getResponse('binary'); 91 | $rep->mimeType = $result->mime; 92 | $rep->content = $result->data; 93 | $rep->doDownload = false; 94 | $rep->outputFileName = $service.'_'.$request; 95 | 96 | return $rep; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /wps/controllers/restrictionsAdmin.classic.php: -------------------------------------------------------------------------------- 1 | array('jacl2.right' => 'wps.options.manage'), 7 | ); 8 | 9 | private $iniFile; 10 | 11 | private $wpsSection = 'wps'; 12 | 13 | public function __construct($request) 14 | { 15 | parent::__construct($request); 16 | $file = jApp::varConfigPath('liveconfig.ini.php'); 17 | $this->iniFile = new \Jelix\IniFile\IniModifier($file); 18 | } 19 | 20 | public function show() 21 | { 22 | $resp = $this->getResponse('html'); 23 | $form = jForms::create('wps~project_restriction_params'); 24 | $tpl = new jTpl(); 25 | $this->initFormWithIni($form); 26 | $tpl->assign('form', $form); 27 | 28 | $resp->body->assign('MAIN', $tpl->fetch('restrictions.show')); 29 | $resp->body->assign('selectedMenuItem', 'wps_proj_restrict'); 30 | 31 | return $resp; 32 | } 33 | 34 | public function prepare() 35 | { 36 | $form = jForms::create('wps~project_restriction_params'); 37 | $this->initFormWithIni($form); 38 | 39 | return $this->redirect('restrictionsAdmin:edit'); 40 | } 41 | 42 | public function edit() 43 | { 44 | /** 45 | * @var jResponseHTML; $resp 46 | */ 47 | $resp = $this->getResponse('html'); 48 | 49 | $form = jForms::get('wps~project_restriction_params'); 50 | if (is_null($form)) { 51 | // redirect to default page 52 | return $this->redirect('restrictionsAdmin:prepare'); 53 | } 54 | $tpl = new jTpl(); 55 | $tpl->assign('form', $form); 56 | 57 | $resp->body->assign('MAIN', $tpl->fetch('restrictions.edit')); 58 | $resp->body->assign('selectedMenuItem', 'wps_proj_restrict'); 59 | 60 | return $resp; 61 | } 62 | 63 | public function save() 64 | { 65 | $form = jForms::fill('wps~project_restriction_params'); 66 | if (is_null($form)) { 67 | // redirect to default page 68 | return $this->redirect('restrictionsAdmin:prepare'); 69 | } 70 | 71 | if (!$form->check()) { 72 | return $this->redirect('restrictionsAdmin:edit'); 73 | } 74 | // Save the data 75 | foreach ($form->getControls() as $ctrl) { 76 | if ($ctrl->type != 'submit') { 77 | if ($form->getData($ctrl->ref) == true) { 78 | $optionValue = 'on'; 79 | } else { 80 | $optionValue = 'off'; 81 | } 82 | $this->iniFile->setValue($ctrl->ref, $optionValue, $this->wpsSection); 83 | } 84 | } 85 | $this->iniFile->save(); 86 | jForms::destroy('wps~project_restriction_params'); 87 | 88 | return $this->redirect('restrictionsAdmin:show'); 89 | } 90 | 91 | private function initFormWithIni($form) 92 | { 93 | // read the value from the actual config, not the ini file, as we 94 | // don't know if the value is set into mainconfig, localconfig or liveconfig. 95 | $config = \jApp::config()->wps; 96 | foreach ($form->getControls() as $ctrl) { 97 | if ($ctrl->type != 'submit') { 98 | $form->setData($ctrl->ref, $config[$ctrl->ref]); 99 | } 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /wps/controllers/results.classic.php: -------------------------------------------------------------------------------- 1 | getResponse('binary'); 17 | $rep->outputFileName = 'wps_results.json'; 18 | $rep->mimeType = 'application/json'; 19 | $content = 'null'; 20 | $rep->content = $content; 21 | 22 | // wps process identifier 23 | $identifier = $this->param('identifier'); 24 | if (!$identifier) { 25 | jLog::log('results controller, index: No identifier param', 'errors'); 26 | 27 | return $rep; 28 | } 29 | 30 | // lizmap project and repository 31 | $repository = $this->param('repository'); 32 | if (!$repository) { 33 | jLog::log('results controller, index: No repository param', 'errors'); 34 | 35 | return $rep; 36 | } 37 | $project = $this->param('project'); 38 | if (!$project) { 39 | jLog::log('results controller, index: No project param', 'errors'); 40 | 41 | return $rep; 42 | } 43 | 44 | /** @var processStatus $pStatus */ 45 | $pStatus = jClasses::getService('wps~processStatus'); 46 | 47 | $data = array(); 48 | $saved = $pStatus->saved($identifier, $repository, $project); 49 | foreach ($saved as $uuid) { 50 | $data[$uuid] = $pStatus->get($identifier, $repository, $project, $uuid); 51 | } 52 | if (count($data) > 0) { 53 | $rep->content = json_encode($data); 54 | } 55 | 56 | return $rep; 57 | } 58 | 59 | public function all() 60 | { 61 | $rep = $this->getResponse('binary'); 62 | $rep->outputFileName = 'wps_results.json'; 63 | $rep->mimeType = 'application/json'; 64 | $content = 'null'; 65 | $rep->content = $content; 66 | 67 | // wps process identifier 68 | $identifier = $this->param('identifier'); 69 | if (!$identifier) { 70 | jLog::log('results controller, index: No identifier param', 'errors'); 71 | 72 | return $rep; 73 | } 74 | 75 | // lizmap project and repository 76 | $repository = $this->param('repository'); 77 | if (!$repository) { 78 | jLog::log('results controller, index: No repository param', 'errors'); 79 | 80 | return $rep; 81 | } 82 | $project = $this->param('project'); 83 | if (!$project) { 84 | jLog::log('results controller, index: No project param', 'errors'); 85 | 86 | return $rep; 87 | } 88 | 89 | $pStatus = jClasses::getService('wps~processStatus'); 90 | 91 | $rep->content = json_encode($pStatus->allFromServer($identifier, $repository, $project)); 92 | 93 | return $rep; 94 | } 95 | 96 | public function update() 97 | { 98 | $rep = $this->getResponse('binary'); 99 | $rep->outputFileName = 'wps_result_update.json'; 100 | $rep->mimeType = 'application/json'; 101 | $content = 'null'; 102 | $rep->content = $content; 103 | 104 | // wps process identifier 105 | $identifier = $this->param('identifier'); 106 | if (!$identifier) { 107 | jLog::log('results controller, update: No identifier param', 'errors'); 108 | 109 | return $rep; 110 | } 111 | 112 | // lizmap project and repository 113 | $repository = $this->param('repository'); 114 | if (!$repository) { 115 | jLog::log('results controller, update: No repository param', 'errors'); 116 | 117 | return $rep; 118 | } 119 | $project = $this->param('project'); 120 | if (!$project) { 121 | jLog::log('results controller, update: No project param', 'errors'); 122 | 123 | return $rep; 124 | } 125 | 126 | // Get and decode json post 127 | $requestJson = $this->param('__httpbody'); 128 | if (!$requestJson) { 129 | $requestJson = json_decode($this->request->getBody(), true); 130 | } 131 | 132 | if (!$requestJson) { 133 | jLog::log('results controller, update: No request JSON', 'errors'); 134 | 135 | return $rep; 136 | } 137 | // depending on how jelix is configured, we could have directly 138 | // decoded json, so let's decode data only if needed 139 | $data = (is_string($requestJson) ? json_decode($requestJson, true) : $requestJson); 140 | 141 | if (!array_key_exists('uuid', $data)) { 142 | jLog::log('results controller, update: No uuid in request JSON'); 143 | 144 | return $rep; 145 | } 146 | 147 | $pStatus = jClasses::getService('wps~processStatus'); 148 | $pStatus->update($identifier, $repository, $project, $data['uuid'], $data); 149 | 150 | $rep->content = json_encode($pStatus->get($identifier, $repository, $project, $data['uuid'])); 151 | 152 | return $rep; 153 | } 154 | 155 | public function delete() 156 | { 157 | $rep = $this->getResponse('binary'); 158 | $rep->outputFileName = 'wps_result_update.json'; 159 | $rep->mimeType = 'application/json'; 160 | $content = 'null'; 161 | $rep->content = $content; 162 | 163 | // wps process identifier 164 | $identifier = $this->param('identifier'); 165 | if (!$identifier) { 166 | jLog::log('results controller, delete: No identifier param', 'errors'); 167 | 168 | return $rep; 169 | } 170 | 171 | // lizmap project and repository 172 | $repository = $this->param('repository'); 173 | if (!$repository) { 174 | jLog::log('results controller, delete: No repository param', 'errors'); 175 | 176 | return $rep; 177 | } 178 | $project = $this->param('project'); 179 | if (!$project) { 180 | jLog::log('results controller, delete: No project param', 'errors'); 181 | 182 | return $rep; 183 | } 184 | 185 | // wps process uuid 186 | $uuid = $this->param('uuid'); 187 | if (!$uuid) { 188 | return $rep; 189 | } 190 | 191 | $pStatus = jClasses::getService('wps~processStatus'); 192 | $pStatus->delete($identifier, $repository, $project, $uuid); 193 | 194 | $rep->content = json_encode($pStatus->get($identifier, $repository, $project, $uuid)); 195 | 196 | return $rep; 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /wps/controllers/service.classic.php: -------------------------------------------------------------------------------- 1 | request->params; 29 | $params = lizmapProxy::normalizeParams($pParams); 30 | foreach ($pParams as $k => $v) { 31 | if (strtolower($k) === 'repository' || strtolower($k) === 'project') { 32 | $params[strtolower($k)] = $v; 33 | } 34 | } 35 | $this->params = $params; 36 | 37 | // Get and parsed xml post 38 | $requestXml = $this->param('__httpbody'); 39 | 40 | if ($requestXml) { 41 | $xml = simplexml_load_string($requestXml); 42 | if ($xml !== false) { 43 | $attrs = $xml->attributes(); 44 | if (isset($attrs['service'])) { 45 | $params['service'] = (string) $attrs['service']; 46 | if (isset($attrs['version'])) { 47 | $params['version'] = (string) $attrs['version']; 48 | } 49 | $xml_request = $xml->getName(); 50 | if (strpos($xml_request, ':') !== false) { 51 | $xml_request = explode(':', $xml_request)[1]; 52 | } 53 | $params['request'] = (string) $xml_request; 54 | $this->xml_post = $requestXml; 55 | } 56 | } 57 | } 58 | 59 | // Return the appropriate action 60 | if (!array_key_exists('service', $params)) { 61 | jMessage::add('SERVICE parameter is mandatory!', 'InvalidRequest'); 62 | 63 | return $this->serviceException(); 64 | } 65 | $service = strtoupper($params['service']); 66 | if ($service != 'WPS') { 67 | jMessage::add('SERVICE '.$service.' is not supported!', 'InvalidRequest'); 68 | 69 | return $this->serviceException(); 70 | } 71 | if (!array_key_exists('request', $params)) { 72 | jMessage::add('REQUEST parameter is mandatory!', 'InvalidRequest'); 73 | 74 | return $this->serviceException(); 75 | } 76 | 77 | // WPS Config 78 | $wpsConfig = jApp::config()->wps; 79 | 80 | // WPS only available to authenticated users 81 | if (array_key_exists('restrict_to_authenticated_users', $wpsConfig) 82 | && $wpsConfig['restrict_to_authenticated_users'] 83 | && !jAuth::isConnected()) { 84 | jMessage::add('Authorization is required to access WPS!', 'AuthorizationRequired'); 85 | 86 | return $this->serviceException(); 87 | } 88 | 89 | $request = strtolower($params['request']); 90 | $wpsRequest = null; 91 | if ($request == 'getcapabilities') { 92 | $wpsRequest = new lizmapWPSRequest( 93 | array( 94 | 'service' => 'WPS', 95 | 'request' => 'GetCapabilities', 96 | ) 97 | ); 98 | } elseif ($request == 'describeprocess') { 99 | $wpsRequest = new lizmapWPSRequest($params, $this->xml_post); 100 | } elseif ($request == 'execute') { 101 | $wpsRequest = new lizmapWPSRequest($params, $this->xml_post); 102 | } elseif ($request == 'getresults') { 103 | $wpsRequest = new lizmapWPSRequest($params, $this->xml_post); 104 | } 105 | 106 | if ($wpsRequest === null) { 107 | jMessage::add('REQUEST '.$request.' not supported', 'InvalidRequest'); 108 | 109 | return $this->serviceException(); 110 | } 111 | 112 | $result = $wpsRequest->process(); 113 | 114 | $rep = $this->getResponse('binary'); 115 | $rep->mimeType = $result->mime; 116 | $rep->content = $result->data; 117 | $rep->doDownload = false; 118 | $rep->outputFileName = 'wps_'.$request; 119 | 120 | return $rep; 121 | } 122 | 123 | /** 124 | * Send an OGC service Exception. 125 | * 126 | * @param $SERVICE the OGC service 127 | * 128 | * @return XML OGC Service Exception 129 | */ 130 | public function serviceException() 131 | { 132 | $messages = jMessage::getAll(); 133 | if (!$messages) { 134 | $messages = array(); 135 | } 136 | $rep = $this->getResponse('xml'); 137 | $rep->contentTpl = 'wps~wps_exception'; 138 | $rep->content->assign('messages', $messages); 139 | jMessage::clearAll(); 140 | 141 | foreach ($messages as $code => $msg) { 142 | if ($code == 'AuthorizationRequired') { 143 | $rep->setHttpStatus(401, $code); 144 | } elseif ($code == 'ProjectNotDefined') { 145 | $rep->setHttpStatus(404, 'Not Found'); 146 | } elseif ($code == 'RepositoryNotDefined') { 147 | $rep->setHttpStatus(404, 'Not Found'); 148 | } 149 | } 150 | 151 | return $rep; 152 | } 153 | 154 | public function store() 155 | { 156 | $rep = $this->getResponse('binary'); 157 | $rep->outputFileName = 'wps_store.json'; 158 | $rep->mimeType = 'application/json'; 159 | $content = 'null'; 160 | $rep->content = $content; 161 | 162 | $uuid = $this->param('uuid'); 163 | if (!$uuid) { 164 | return $rep; 165 | } 166 | 167 | $file = $this->param('file'); 168 | if (!$file) { 169 | return $rep; 170 | } 171 | 172 | $wps_url = jApp::config()->wps['wps_rootUrl']; 173 | $wps_url = ltrim($wps_url, '/'); 174 | if (substr($wps_url, -1) != '/') { 175 | $wps_url .= '/'; 176 | } 177 | 178 | $url = $wps_url.'store/'.$uuid.'/'.$file.'?service=WPS'; 179 | 180 | list($data, $mime, $code) = lizmapProxy::getRemoteData($url); 181 | 182 | $rep->outputFileName = $file; 183 | $rep->mimeType = $mime; 184 | $rep->content = $data; 185 | $rep->doDownload = false; 186 | 187 | return $rep; 188 | } 189 | 190 | public function files() 191 | { 192 | $rep = $this->getResponse('binary'); 193 | $rep->outputFileName = 'wps_store.json'; 194 | $rep->mimeType = 'application/json'; 195 | $content = 'null'; 196 | $rep->content = $content; 197 | 198 | $uuid = $this->param('uuid'); 199 | if (!$uuid) { 200 | return $rep; 201 | } 202 | 203 | $file = $this->param('file'); 204 | if (!$file) { 205 | return $rep; 206 | } 207 | 208 | $wps_url = jApp::config()->wps['wps_rootUrl']; 209 | $wps_url = ltrim($wps_url, '/'); 210 | if (substr($wps_url, -1) != '/') { 211 | $wps_url .= '/'; 212 | } 213 | 214 | $url = $wps_url.'jobs/'.$uuid.'/'.'files/'.$file; 215 | 216 | list($data, $mime, $code) = lizmapProxy::getRemoteData($url); 217 | 218 | $rep->outputFileName = $file; 219 | $rep->mimeType = $mime; 220 | $rep->content = $data; 221 | $rep->doDownload = false; 222 | 223 | return $rep; 224 | } 225 | 226 | public function status() 227 | { 228 | $rep = $this->getResponse('binary'); 229 | $rep->outputFileName = 'wps_store.json'; 230 | $rep->mimeType = 'application/json'; 231 | $content = 'null'; 232 | $rep->content = $content; 233 | 234 | $wps_url = jApp::config()->wps['wps_rootUrl']; 235 | $wps_url = ltrim($wps_url, '/'); 236 | if (substr($wps_url, -1) != '/') { 237 | $wps_url .= '/'; 238 | } 239 | 240 | $url = $wps_url.'status/'; 241 | 242 | $uuid = $this->param('uuid'); 243 | if ($uuid) { 244 | $url .= $uuid; 245 | } 246 | 247 | $url .= '?SERVICE=WPS'; 248 | 249 | list($data, $mime, $code) = lizmapProxy::getRemoteData($url); 250 | 251 | if (empty($data) or floor($code / 100) >= 4) { 252 | $rep->setHttpStatus($code, 'Not Found'); 253 | 254 | return $rep; 255 | } 256 | 257 | $sUrl = jUrl::getFull( 258 | 'wps~service:index' 259 | ); 260 | $data = json_decode($data); 261 | 262 | if (property_exists($data, 'status')) { 263 | if (property_exists($data->status, 'status_url')) { 264 | $oUrl = $data->status->status_url; 265 | $data->status->status_url = $sUrl.'?'.explode('?', $oUrl)[1]; 266 | } else { 267 | $uuids = array(); 268 | foreach ($data->status as $s) { 269 | $uuids[] = $s->uuid; 270 | } 271 | $data = $uuids; 272 | } 273 | } 274 | 275 | $rep->mimeType = $mime; 276 | $rep->content = json_encode($data); 277 | $rep->doDownload = false; 278 | 279 | return $rep; 280 | } 281 | } 282 | -------------------------------------------------------------------------------- /wps/events.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /wps/forms/model_upload.form.xml: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 6 | 7 | 8 | 9 |
10 | -------------------------------------------------------------------------------- /wps/forms/project_restriction_params.form.xml: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 8 | 9 | 13 | 14 | 15 | 16 |
-------------------------------------------------------------------------------- /wps/forms/style_upload.form.xml: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 6 | 7 | 8 | 9 |
10 | -------------------------------------------------------------------------------- /wps/install/configure.php: -------------------------------------------------------------------------------- 1 | havingName( 27 | 'admin', 28 | array( 29 | new MapInclude('adminurls.xml'), 30 | ) 31 | ) 32 | ; 33 | 34 | $registerOnEntryPoint->havingName( 35 | 'index', 36 | array( 37 | new MapInclude('urls.xml'), 38 | ) 39 | ) 40 | ; 41 | } 42 | 43 | public function configure(Jelix\Installer\Module\API\ConfigurationHelpers $helpers) 44 | { 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /wps/install/install.php: -------------------------------------------------------------------------------- 1 | 'wps~wps.acl2.model.manage', 16 | 'wps.options.manage' => 'wps~wps.acl2.options.manage', 17 | ); 18 | foreach ($rights as $rightName => $rightLocale) { 19 | // Add right subject 20 | jAcl2DbManager::addSubject($rightName, $rightLocale, 'lizmap.admin.grp'); 21 | 22 | // Add right on admins group 23 | jAcl2DbManager::addRight('admins', $rightName); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /wps/install/upgrade_03.php: -------------------------------------------------------------------------------- 1 | 'wps~wps.acl2.model.manage', 21 | 'wps.options.manage' => 'wps~wps.acl2.options.manage', 22 | ); 23 | foreach ($rights as $rightName => $rightLocale) { 24 | // Add right subject 25 | jAcl2DbManager::addSubject($rightName, $rightLocale, 'lizmap.admin.grp'); 26 | 27 | // Add right on admins group 28 | jAcl2DbManager::addRight('admins', $rightName); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /wps/lib/ModelFile.php: -------------------------------------------------------------------------------- 1 | fileName = $fileName; 14 | $this->sha1 = sha1($fileName); 15 | } 16 | 17 | public function fileName() 18 | { 19 | return $this->fileName; 20 | } 21 | 22 | public function uniqueID() 23 | { 24 | return $this->sha1; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /wps/lib/ModelFileManager.php: -------------------------------------------------------------------------------- 1 | modelPath)) { 16 | $this->modelPath = \jApp::config()->wps[self::MODEL_PATH_PARAM_NAME]; 17 | if (empty($this->modelPath)) { 18 | \jlog::log('WPS path is empty', 'lizmapadmin'); 19 | 20 | throw new \Exception('WPS path is empty'); 21 | } 22 | // ensure trailing slash is here 23 | if (substr($this->modelPath, -1) == '/') { 24 | $this->modelPath.'/'; 25 | } 26 | if (!is_dir($this->modelPath)) { 27 | \jlog::log('WPS path is invalid', 'lizmapadmin'); 28 | 29 | throw new \Exception('WPS path is invalid'); 30 | } 31 | } 32 | 33 | return $this->modelPath; 34 | } 35 | 36 | public function getModelFiles() 37 | { 38 | $files = scandir($this->getModelsPath()); 39 | $realModels = array(); 40 | foreach ($files as $file) { 41 | if (is_file($this->getModelsPath().$file) 42 | && pathinfo($file, PATHINFO_EXTENSION) === 'model3') { 43 | $realModels[] = new ModelFile($file); 44 | } 45 | } 46 | 47 | return $realModels; 48 | } 49 | 50 | public function getStyleFiles() 51 | { 52 | $files = scandir($this->getModelsPath()); 53 | $realModels = array(); 54 | foreach ($files as $file) { 55 | if (is_file($this->getModelsPath().$file) 56 | && pathinfo($file, PATHINFO_EXTENSION) === 'qml') { 57 | $realModels[] = new StyleFile($file); 58 | } 59 | } 60 | 61 | return $realModels; 62 | } 63 | 64 | public function findBySHA1(string $sha1) 65 | { 66 | $files = scandir($this->getModelsPath()); 67 | foreach ($files as $file) { 68 | if ($sha1 == sha1($file) && is_file($this->getModelsPath().$file)) { 69 | if (pathinfo($file, PATHINFO_EXTENSION) === 'model3') { 70 | return new ModelFile($file); 71 | } 72 | if (pathinfo($file, PATHINFO_EXTENSION) === 'qml') { 73 | return new StyleFile($file); 74 | } 75 | } 76 | } 77 | 78 | return false; 79 | } 80 | 81 | public function deleteModel(ModelFile $file) 82 | { 83 | unlink($this->getModelsPath().$file->fileName()); 84 | $this->notifyWPS(); 85 | } 86 | 87 | public function saveModel(\jFormsControlUpload2 $ctrl, bool $new) 88 | { 89 | // check filename 90 | $filePath = $this->getModelsPath().$ctrl->getNewFile(); 91 | if ($ctrl->isModified() && !preg_match('/^.+\.model3$/i', $ctrl->getNewFile())) { 92 | throw new \Exception(\jLocale::get('wps.message.error.upload.model3_bad_filename')); 93 | } 94 | if (!$new && $ctrl->isModified() && $ctrl->getOriginalFile() != $ctrl->getNewFile()) { 95 | throw new \Exception(\jLocale::get('wps.message.error.upload.modify.not_same')); 96 | } 97 | if ($new && is_file($filePath)) { 98 | throw new \Exception(\jLocale::get('wps.message.error.upload.existing')); 99 | } 100 | // disable xml reader error 101 | $previouXMLErrorConfig = libxml_use_internal_errors(true); 102 | $alternateName = ''; 103 | $originalFilePath = $this->getModelsPath().$ctrl->getNewFile(); 104 | if (!$new) { 105 | // use a temp file to perform check content 106 | $alternateName = $ctrl->getUniqueFileName($this->getModelsPath()); 107 | $filePath = $this->getModelsPath().$alternateName; 108 | } 109 | $ctrl->saveFile($this->getModelsPath(), $alternateName); 110 | $fileAsXML = simplexml_load_file($filePath); 111 | if ($ctrl->isModified() && ($fileAsXML === false || (!property_exists($fileAsXML, 'Option')) || $fileAsXML->attributes()['type'] != 'Map')) { 112 | unlink($filePath); 113 | 114 | throw new \Exception(\jLocale::get('wps.message.error.upload.bad_content')); 115 | } 116 | // restore xml error conf 117 | libxml_use_internal_errors($previouXMLErrorConfig); 118 | if (!$new) { 119 | // content is ok, rename tempfile to initial fileName 120 | rename($filePath, $originalFilePath); 121 | } 122 | $this->notifyWPS(); 123 | } 124 | 125 | private function notifyWPS() 126 | { 127 | $restartMon = \jApp::config()->wps[self::RESTART_FILE_PATH_PARAM_NAME]; 128 | if (empty($restartMon)) { 129 | \jMessage::add(\jLocale::get('wps.message.error.restart_notify'), 'danger'); 130 | } else { 131 | touch($restartMon); 132 | } 133 | } 134 | 135 | public function deleteStyle(StyleFile $file) 136 | { 137 | unlink($this->getModelsPath().$file->fileName()); 138 | } 139 | 140 | public function saveStyle(\jFormsControlUpload2 $ctrl, bool $new) 141 | { 142 | // check filename 143 | $filePath = $this->getModelsPath().$ctrl->getNewFile(); 144 | if ($ctrl->isModified() && !preg_match('/^.+\.qml$/i', $ctrl->getNewFile())) { 145 | throw new \Exception(\jLocale::get('wps.message.error.upload.qml_bad_filename')); 146 | } 147 | if (!$new && $ctrl->isModified() && $ctrl->getOriginalFile() != $ctrl->getNewFile()) { 148 | throw new \Exception(\jLocale::get('wps.message.error.upload.modify.not_same')); 149 | } 150 | if ($new && is_file($filePath)) { 151 | throw new \Exception(\jLocale::get('wps.message.error.upload.existing')); 152 | } 153 | // disable xml reader error 154 | $previouXMLErrorConfig = libxml_use_internal_errors(true); 155 | $alternateName = ''; 156 | $originalFilePath = $this->getModelsPath().$ctrl->getNewFile(); 157 | if (!$new) { 158 | // use a temp file to perform check content 159 | $alternateName = $ctrl->getUniqueFileName($this->getModelsPath()); 160 | $filePath = $this->getModelsPath().$alternateName; 161 | } 162 | $ctrl->saveFile($this->getModelsPath(), $alternateName); 163 | $fileAsXML = simplexml_load_file($filePath); 164 | if ($ctrl->isModified() && $fileAsXML === false) { 165 | unlink($filePath); 166 | 167 | throw new \Exception(\jLocale::get('wps.message.error.upload.bad_content')); 168 | } 169 | // restore xml error conf 170 | libxml_use_internal_errors($previouXMLErrorConfig); 171 | if (!$new) { 172 | // content is ok, rename tempfile to initial fileName 173 | rename($filePath, $originalFilePath); 174 | } 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /wps/lib/StyleFile.php: -------------------------------------------------------------------------------- 1 | fileName = $fileName; 14 | $this->sha1 = sha1($fileName); 15 | } 16 | 17 | public function fileName() 18 | { 19 | return $this->fileName; 20 | } 21 | 22 | public function uniqueID() 23 | { 24 | return $this->sha1; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /wps/locales/en_US/wps.UTF-8.properties: -------------------------------------------------------------------------------- 1 | acl2.model.manage=Manage WPS model3 files 2 | acl2.options.manage=Manage WPS projects restrictions 3 | 4 | message.error.restart_notify=Cannot notify restart monitor 5 | message.error.model3_path_invalid=WPS model3 path unavailable 6 | message.error.unknown_file=Unknown file 7 | message.error.upload.model3_bad_filename=Empty filename or bad extension (.model3) 8 | message.error.upload.qml_bad_filename=Empty filename or bad extension (.qml) 9 | message.error.upload.existing=File already exists, delete it first 10 | message.error.upload.bad_content=Invalid Content 11 | message.error.upload.modify.not_same=Modified filename must be the same as original 12 | message.ok.file_added=File added 13 | message.ok.file_deleted=File deleted 14 | message.ok.file_modified=File modified 15 | 16 | ui.button.model3.file.add=Add a QGIS model file 17 | ui.button.qml.file.add=Add a QGIS style file 18 | 19 | ui.form.model3.file=QGIS model file 20 | ui.form.qml.file=QGIS style file 21 | 22 | ui.page.model3.list.title=QGIS model List 23 | ui.page.model3.list.empty_dir=No QGIS models submitted 24 | ui.page.model3.upload.title=QGIS model file upload 25 | ui.page.qml.list.title=QGIS style List 26 | ui.page.qml.list.empty_dir=No QGIS styles submitted 27 | ui.page.qml.upload.title=QGIS style file upload 28 | ui.page.conf.title=Project restrictions configuration 29 | ui.page.confirmdelete.title=Confirm file deletion 30 | ui.page.confirmdelete.msg.html=Are you sure to want to delete %s ? 31 | 32 | ui.admin.menu.group=WPS configuration 33 | ui.admin.menu.model3list=Manage QGIS models 34 | ui.admin.menu.project_restriction=Project restrictions 35 | 36 | form.projects.restrict_to_authenticated_users=Restrict to authenticated users 37 | form.projects.restrict_to_config_projects=Restrict to projects with WPS configuration 38 | 39 | dock.main.title=Processing 40 | run.tab.execute.button=Run 41 | run.tab.help.button=Help 42 | run.tab.dropdown=Choose a process to run 43 | run.tab.processing.help=Fill in the form and click the Execute button 44 | run.tab.processing.title=Title 45 | run.tab.processing.description=Description 46 | run.tab.processing.inputs=Parameters 47 | run.tab.processing.input=Parameter 48 | run.tab.processing.input.name=Name 49 | run.tab.processing.input.type=Type 50 | run.tab.processing.input.required=Required 51 | run.tab.processing.outputs=Outputs 52 | run.tab.processing.output.name=Name 53 | run.tab.processing.output.type=Type 54 | dock.results.title=Processing results 55 | -------------------------------------------------------------------------------- /wps/locales/fr_FR/wps.UTF-8.properties: -------------------------------------------------------------------------------- 1 | acl2.model.manage=Gestion des fichiers WPS model3 2 | acl2.options.manage=Gestion des restrictions de projets WPS 3 | 4 | message.error.restart_notify=Impossible de notifier le redémarrage WPS 5 | message.error.model3_path_invalid=Chemin vers les WPS model3 invalide 6 | message.error.unknown_file=Fichier non trouvé 7 | message.error.upload.model3_bad_filename=Nom de fichier vide ou mauvaise extension (.model3) 8 | message.error.upload.qml_bad_filename=Nom de fichier vide ou mauvaise extension (.qml) 9 | message.error.upload.existing=Fichier déjà existant, effacez-le d'abord 10 | message.error.upload.bad_content=Contenu invalide 11 | message.error.upload.modify.not_same=Le fichier doit avoir le même nom que l'original 12 | message.ok.file_added=Fichier ajouté 13 | message.ok.file_deleted=Fichier effacé 14 | message.ok.file_modified=Fichier modifié 15 | 16 | ui.button.model3.file.add=Ajouter un fichier de modèle QGIS 17 | ui.button.qml.file.add=Ajouter un fichier de style QGIS 18 | 19 | ui.page.model3.list.title=Liste des modèles QGIS 20 | ui.page.model3.list.empty_dir=Aucun modèle QGIS disponible 21 | ui.page.model3.upload.title=Téléversement d'un fichier de modèle QGIS 22 | ui.page.qml.list.title=Liste des styles QGIS 23 | ui.page.qml.list.empty_dir=Aucun style QGIS disponible 24 | ui.page.qml.upload.title=Téléversement d'un fichier de style QGIS 25 | ui.page.conf.title=Configuration des restrictions de projet 26 | ui.page.confirmdelete.title=Confirmer la suppression du fichier 27 | ui.page.confirmdelete.msg.html=Êtes-vous sûr de vouloir supprimer le fichier %s ? 28 | 29 | ui.admin.menu.group=Configuration WPS 30 | ui.admin.menu.model3list=Gestion des modèles QGIS 31 | ui.admin.menu.project_restriction=Restrictions de projet 32 | 33 | form.projects.restrict_to_authenticated_users=Restreindre aux utilisateurs authentifiés 34 | form.projects.restrict_to_config_projects=Restreindre aux projets ayant une configuration WPS 35 | 36 | dock.main.title=Traitement 37 | run.tab.execute.button=Exécuter 38 | run.tab.help.button=Aide 39 | run.tab.dropdown=Choisir un traitement à effectuer 40 | run.tab.processing.help=Compléter le formulaire et cliquer sur le bouton Exécuter 41 | run.tab.processing.title=Nom 42 | run.tab.processing.description=Description 43 | run.tab.processing.inputs=Paramètres 44 | run.tab.processing.input=Paramètre 45 | run.tab.processing.input.name=Nom 46 | run.tab.processing.input.type=Type 47 | run.tab.processing.input.required=Requis 48 | run.tab.processing.outputs=Sorties 49 | run.tab.processing.output.name=Nom 50 | run.tab.processing.output.type=Type 51 | dock.results.title=Résultats des traitements 52 | -------------------------------------------------------------------------------- /wps/module.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 0.5.2 5 | 6 | 7 | Mozilla Public Licence 8 | 2017-2025 3liz 9 | 10 | 11 | http://3liz.com 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /wps/templates/admin.list.tpl: -------------------------------------------------------------------------------- 1 |

{@wps.ui.page.model3.list.title@}

2 | {if count($models) > 0} 3 | 4 | 5 | {foreach $models as $file} 6 | 7 | 8 | 9 | 10 | 11 | {/foreach} 12 | 13 |
{$file->fileName()}{@jelix~crud.link.edit.record@}{@jelix~ui.buttons.delete@}
14 | {else } 15 |

16 | {@wps.ui.page.model3.list.empty_dir@} 17 |

18 | {/if} 19 | {@wps.ui.button.model3.file.add@} 20 | 21 |

{@wps.ui.page.qml.list.title@}

22 | {if count($styles) > 0} 23 | 24 | 25 | {foreach $styles as $file} 26 | 27 | 28 | 29 | 30 | 31 | {/foreach} 32 | 33 |
{$file->fileName()}{@jelix~crud.link.edit.record@}{@jelix~ui.buttons.delete@}
34 | {else } 35 |

36 | {@wps.ui.page.qml.list.empty_dir@} 37 |

38 | {/if} 39 | {@wps.ui.button.qml.file.add@} 40 | -------------------------------------------------------------------------------- /wps/templates/admin.model3.confirmdelete.tpl: -------------------------------------------------------------------------------- 1 |

{@wps.ui.page.confirmdelete.title@}

2 |

3 | {jlocale 'wps~wps.ui.page.confirmdelete.msg.html', array($file->fileName())} 4 | 5 |
6 | {@jelix~ui.buttons.yes@} 7 | 8 | {@jelix~ui.buttons.no@} 9 |

10 | -------------------------------------------------------------------------------- /wps/templates/admin.model3.showform.tpl: -------------------------------------------------------------------------------- 1 |

{@wps.ui.page.model3.upload.title@}

2 | {form $form ,'wps~admin:saveUploadModel' , array('fileId' => $fileId), 'htmlbootstrap'} 3 |
4 | {formcontrols} 5 |
6 | {ctrl_label} 7 |
{ctrl_control}
8 |
9 | {/formcontrols} 10 |
11 |
{formsubmit} 12 | {@jelix~ui.buttons.back@} 13 |
14 | {/form} 15 | -------------------------------------------------------------------------------- /wps/templates/admin.qml.confirmdelete.tpl: -------------------------------------------------------------------------------- 1 |

{@wps.ui.page.confirmdelete.title@}

2 |

3 | {jlocale 'wps~wps.ui.page.confirmdelete.msg.html', array($file->fileName())} 4 | 5 |
6 | {@jelix~ui.buttons.yes@} 7 | 8 | {@jelix~ui.buttons.no@} 9 |

10 | -------------------------------------------------------------------------------- /wps/templates/admin.qml.showform.tpl: -------------------------------------------------------------------------------- 1 |

{@wps.ui.page.qml.upload.title@}

2 | {form $form ,'wps~admin:saveUploadStyle' , array('fileId' => $fileId), 'htmlbootstrap'} 3 |
4 | {formcontrols} 5 |
6 | {ctrl_label} 7 |
{ctrl_control}
8 |
9 | {/formcontrols} 10 |
11 |
{formsubmit} 12 | {@jelix~ui.buttons.back@} 13 |
14 | {/form} 15 | -------------------------------------------------------------------------------- /wps/templates/bottomdock.tpl: -------------------------------------------------------------------------------- 1 | 63 | -------------------------------------------------------------------------------- /wps/templates/dock.tpl: -------------------------------------------------------------------------------- 1 |
2 | {@ wps~wps.run.tab.dropdown @} 3 |
4 | 5 |
6 | 49 | -------------------------------------------------------------------------------- /wps/templates/restrictions.edit.tpl: -------------------------------------------------------------------------------- 1 |

{@wps.ui.page.conf.title@}

2 | {form $form , 'wps~restrictionsAdmin:save' , array(),'htmlbootstrap'} 3 |
4 | {formcontrols} 5 |
6 | {ctrl_label} 7 |
{ctrl_control}
8 |
9 | {/formcontrols} 10 |
11 |
{formsubmit} 12 |
13 | {/form} 14 | -------------------------------------------------------------------------------- /wps/templates/restrictions.show.tpl: -------------------------------------------------------------------------------- 1 |

{@wps.ui.page.conf.title@}

2 | {form $form , 'wps~restrictionsAdmin:save' , array(),'htmlbootstrap'} 3 | 4 | 5 | {formcontrols} 6 | 7 | 8 | 9 | 10 | {/formcontrols} 11 | 12 |
{ctrl_label}{ctrl_value}
13 | 14 | {/form} 15 | 16 | {@jelix~ui.buttons.update@} -------------------------------------------------------------------------------- /wps/templates/wcs_exception.tpl: -------------------------------------------------------------------------------- 1 | 2 | {foreach $messages as $type_msg => $all_msg} 3 | 4 | {foreach $all_msg as $msg} 5 | {$msg} 6 | {/foreach} 7 | 8 | {/foreach} 9 | 10 | -------------------------------------------------------------------------------- /wps/templates/wps_exception.tpl: -------------------------------------------------------------------------------- 1 | 2 | {foreach $messages as $type_msg => $all_msg} 3 | 4 | {foreach $all_msg as $msg} 5 | {$msg} 6 | {/foreach} 7 | 8 | {/foreach} 9 | 10 | -------------------------------------------------------------------------------- /wps/urls.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /wps/www/OpenLayers/Format/Filter.js: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for 2 | * full list of contributors). Published under the 2-clause BSD license. 3 | * See license.txt in the OpenLayers distribution or repository for the 4 | * full text of the license. */ 5 | 6 | /** 7 | * @requires OpenLayers/Format/XML/VersionedOGC.js 8 | * @requires OpenLayers/Filter/FeatureId.js 9 | * @requires OpenLayers/Filter/Logical.js 10 | * @requires OpenLayers/Filter/Comparison.js 11 | */ 12 | 13 | /** 14 | * Class: OpenLayers.Format.Filter 15 | * Read/Write ogc:Filter. Create a new instance with the 16 | * constructor. 17 | * 18 | * Inherits from: 19 | * - 20 | */ 21 | OpenLayers.Format.Filter = OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC, { 22 | 23 | /** 24 | * APIProperty: defaultVersion 25 | * {String} Version number to assume if none found. Default is "1.0.0". 26 | */ 27 | defaultVersion: "1.0.0", 28 | 29 | /** 30 | * APIMethod: write 31 | * Write an ogc:Filter given a filter object. 32 | * 33 | * Parameters: 34 | * filter - {} An filter. 35 | * options - {Object} Optional configuration object. 36 | * 37 | * Returns: 38 | * {Elment} An ogc:Filter element node. 39 | */ 40 | 41 | /** 42 | * APIMethod: read 43 | * Read and Filter doc and return an object representing the Filter. 44 | * 45 | * Parameters: 46 | * data - {String | DOMElement} Data to read. 47 | * 48 | * Returns: 49 | * {} A filter object. 50 | */ 51 | 52 | CLASS_NAME: "OpenLayers.Format.Filter" 53 | }); 54 | -------------------------------------------------------------------------------- /wps/www/OpenLayers/Format/Filter/v1_1_0.js: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for 2 | * full list of contributors). Published under the 2-clause BSD license. 3 | * See license.txt in the OpenLayers distribution or repository for the 4 | * full text of the license. */ 5 | 6 | /** 7 | * @requires OpenLayers/Format/Filter/v1.js 8 | * @requires OpenLayers/Format/GML/v3.js 9 | */ 10 | 11 | /** 12 | * Class: OpenLayers.Format.Filter.v1_1_0 13 | * Write ogc:Filter version 1.1.0. 14 | * 15 | * Differences from the v1.0.0 parser: 16 | * - uses GML v3 instead of GML v2 17 | * - reads matchCase attribute on ogc:PropertyIsEqual and 18 | * ogc:PropertyIsNotEqual elements. 19 | * - writes matchCase attribute from comparison filters of type EQUAL_TO, 20 | * NOT_EQUAL_TO and LIKE. 21 | * 22 | * Inherits from: 23 | * - 24 | * - 25 | */ 26 | OpenLayers.Format.Filter.v1_1_0 = OpenLayers.Class( 27 | OpenLayers.Format.GML.v3, OpenLayers.Format.Filter.v1, { 28 | 29 | /** 30 | * Constant: VERSION 31 | * {String} 1.1.0 32 | */ 33 | VERSION: "1.1.0", 34 | 35 | /** 36 | * Property: schemaLocation 37 | * {String} http://www.opengis.net/ogc/filter/1.1.0/filter.xsd 38 | */ 39 | schemaLocation: "http://www.opengis.net/ogc/filter/1.1.0/filter.xsd", 40 | 41 | /** 42 | * Constructor: OpenLayers.Format.Filter.v1_1_0 43 | * Instances of this class are not created directly. Use the 44 | * constructor instead. 45 | * 46 | * Parameters: 47 | * options - {Object} An optional object whose properties will be set on 48 | * this instance. 49 | */ 50 | initialize: function(options) { 51 | OpenLayers.Format.GML.v3.prototype.initialize.apply( 52 | this, [options] 53 | ); 54 | }, 55 | 56 | /** 57 | * Property: readers 58 | * Contains public functions, grouped by namespace prefix, that will 59 | * be applied when a namespaced node is found matching the function 60 | * name. The function will be applied in the scope of this parser 61 | * with two arguments: the node being read and a context object passed 62 | * from the parent. 63 | */ 64 | readers: { 65 | "ogc": OpenLayers.Util.applyDefaults({ 66 | "PropertyIsEqualTo": function(node, obj) { 67 | var matchCase = node.getAttribute("matchCase"); 68 | var filter = new OpenLayers.Filter.Comparison({ 69 | type: OpenLayers.Filter.Comparison.EQUAL_TO, 70 | matchCase: !(matchCase === "false" || matchCase === "0") 71 | }); 72 | this.readChildNodes(node, filter); 73 | obj.filters.push(filter); 74 | }, 75 | "PropertyIsNotEqualTo": function(node, obj) { 76 | var matchCase = node.getAttribute("matchCase"); 77 | var filter = new OpenLayers.Filter.Comparison({ 78 | type: OpenLayers.Filter.Comparison.NOT_EQUAL_TO, 79 | matchCase: !(matchCase === "false" || matchCase === "0") 80 | }); 81 | this.readChildNodes(node, filter); 82 | obj.filters.push(filter); 83 | }, 84 | "PropertyIsLike": function(node, obj) { 85 | var filter = new OpenLayers.Filter.Comparison({ 86 | type: OpenLayers.Filter.Comparison.LIKE 87 | }); 88 | this.readChildNodes(node, filter); 89 | var wildCard = node.getAttribute("wildCard"); 90 | var singleChar = node.getAttribute("singleChar"); 91 | var esc = node.getAttribute("escapeChar"); 92 | filter.value2regex(wildCard, singleChar, esc); 93 | obj.filters.push(filter); 94 | } 95 | }, OpenLayers.Format.Filter.v1.prototype.readers["ogc"]), 96 | "gml": OpenLayers.Format.GML.v3.prototype.readers["gml"], 97 | "feature": OpenLayers.Format.GML.v3.prototype.readers["feature"] 98 | }, 99 | 100 | /** 101 | * Property: writers 102 | * As a compliment to the readers property, this structure contains public 103 | * writing functions grouped by namespace alias and named like the 104 | * node names they produce. 105 | */ 106 | writers: { 107 | "ogc": OpenLayers.Util.applyDefaults({ 108 | "PropertyIsEqualTo": function(filter) { 109 | var node = this.createElementNSPlus("ogc:PropertyIsEqualTo", { 110 | attributes: {matchCase: filter.matchCase} 111 | }); 112 | // no ogc:expression handling for PropertyName for now 113 | this.writeNode("PropertyName", filter, node); 114 | // handle Literals or Functions for now 115 | this.writeOgcExpression(filter.value, node); 116 | return node; 117 | }, 118 | "PropertyIsNotEqualTo": function(filter) { 119 | var node = this.createElementNSPlus("ogc:PropertyIsNotEqualTo", { 120 | attributes: {matchCase: filter.matchCase} 121 | }); 122 | // no ogc:expression handling for PropertyName for now 123 | this.writeNode("PropertyName", filter, node); 124 | // handle Literals or Functions for now 125 | this.writeOgcExpression(filter.value, node); 126 | return node; 127 | }, 128 | "PropertyIsLike": function(filter) { 129 | var node = this.createElementNSPlus("ogc:PropertyIsLike", { 130 | attributes: { 131 | matchCase: filter.matchCase, 132 | wildCard: "*", singleChar: ".", escapeChar: "!" 133 | } 134 | }); 135 | // no ogc:expression handling for now 136 | this.writeNode("PropertyName", filter, node); 137 | // convert regex string to ogc string 138 | this.writeNode("Literal", filter.regex2value(), node); 139 | return node; 140 | }, 141 | "BBOX": function(filter) { 142 | var node = this.createElementNSPlus("ogc:BBOX"); 143 | // PropertyName is optional in 1.1.0 144 | filter.property && this.writeNode("PropertyName", filter, node); 145 | var box = this.writeNode("gml:Envelope", filter.value); 146 | if(filter.projection) { 147 | box.setAttribute("srsName", filter.projection); 148 | } 149 | node.appendChild(box); 150 | return node; 151 | }, 152 | "SortBy": function(sortProperties) { 153 | var node = this.createElementNSPlus("ogc:SortBy"); 154 | for (var i=0,l=sortProperties.length;i} filter and converts it into XML. 192 | * 193 | * Parameters: 194 | * filter - {} The filter. 195 | * name - {String} Name of the generated XML element. 196 | * 197 | * Returns: 198 | * {DOMElement} The created XML element. 199 | */ 200 | writeSpatial: function(filter, name) { 201 | var node = this.createElementNSPlus("ogc:"+name); 202 | this.writeNode("PropertyName", filter, node); 203 | if(filter.value instanceof OpenLayers.Filter.Function) { 204 | this.writeNode("Function", filter.value, node); 205 | } else { 206 | var child; 207 | if(filter.value instanceof OpenLayers.Geometry) { 208 | child = this.writeNode("feature:_geometry", filter.value).firstChild; 209 | } else { 210 | child = this.writeNode("gml:Envelope", filter.value); 211 | } 212 | if(filter.projection) { 213 | child.setAttribute("srsName", filter.projection); 214 | } 215 | node.appendChild(child); 216 | } 217 | return node; 218 | }, 219 | 220 | CLASS_NAME: "OpenLayers.Format.Filter.v1_1_0" 221 | 222 | }); 223 | -------------------------------------------------------------------------------- /wps/www/OpenLayers/Format/GML/v2.js: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for 2 | * full list of contributors). Published under the 2-clause BSD license. 3 | * See license.txt in the OpenLayers distribution or repository for the 4 | * full text of the license. */ 5 | 6 | /** 7 | * @requires OpenLayers/Format/GML/Base.js 8 | */ 9 | 10 | /** 11 | * Class: OpenLayers.Format.GML.v2 12 | * Parses GML version 2. 13 | * 14 | * Inherits from: 15 | * - 16 | */ 17 | OpenLayers.Format.GML.v2 = OpenLayers.Class(OpenLayers.Format.GML.Base, { 18 | 19 | /** 20 | * Property: schemaLocation 21 | * {String} Schema location for a particular minor version. 22 | */ 23 | schemaLocation: "http://www.opengis.net/gml http://schemas.opengis.net/gml/2.1.2/feature.xsd", 24 | 25 | /** 26 | * Constructor: OpenLayers.Format.GML.v2 27 | * Create a parser for GML v2. 28 | * 29 | * Parameters: 30 | * options - {Object} An optional object whose properties will be set on 31 | * this instance. 32 | * 33 | * Valid options properties: 34 | * featureType - {String} Local (without prefix) feature typeName (required). 35 | * featureNS - {String} Feature namespace (required). 36 | * geometryName - {String} Geometry element name. 37 | */ 38 | initialize: function(options) { 39 | OpenLayers.Format.GML.Base.prototype.initialize.apply(this, [options]); 40 | }, 41 | 42 | /** 43 | * Property: readers 44 | * Contains public functions, grouped by namespace prefix, that will 45 | * be applied when a namespaced node is found matching the function 46 | * name. The function will be applied in the scope of this parser 47 | * with two arguments: the node being read and a context object passed 48 | * from the parent. 49 | */ 50 | readers: { 51 | "gml": OpenLayers.Util.applyDefaults({ 52 | "outerBoundaryIs": function(node, container) { 53 | var obj = {}; 54 | this.readChildNodes(node, obj); 55 | container.outer = obj.components[0]; 56 | }, 57 | "innerBoundaryIs": function(node, container) { 58 | var obj = {}; 59 | this.readChildNodes(node, obj); 60 | container.inner.push(obj.components[0]); 61 | }, 62 | "Box": function(node, container) { 63 | var obj = {}; 64 | this.readChildNodes(node, obj); 65 | if(!container.components) { 66 | container.components = []; 67 | } 68 | var min = obj.points[0]; 69 | var max = obj.points[1]; 70 | container.components.push( 71 | new OpenLayers.Bounds(min.x, min.y, max.x, max.y) 72 | ); 73 | } 74 | }, OpenLayers.Format.GML.Base.prototype.readers["gml"]), 75 | "feature": OpenLayers.Format.GML.Base.prototype.readers["feature"], 76 | "wfs": OpenLayers.Format.GML.Base.prototype.readers["wfs"] 77 | }, 78 | 79 | /** 80 | * Method: write 81 | * 82 | * Parameters: 83 | * features - {Array() | OpenLayers.Feature.Vector} 84 | * An array of features or a single feature. 85 | * 86 | * Returns: 87 | * {String} Given an array of features, a doc with a gml:featureMembers 88 | * element will be returned. Given a single feature, a doc with a 89 | * gml:featureMember element will be returned. 90 | */ 91 | write: function(features) { 92 | var name; 93 | if(OpenLayers.Util.isArray(features)) { 94 | // GML2 only has abstract feature collections 95 | // wfs provides a feature collection from a well-known schema 96 | name = "wfs:FeatureCollection"; 97 | } else { 98 | name = "gml:featureMember"; 99 | } 100 | var root = this.writeNode(name, features); 101 | this.setAttributeNS( 102 | root, this.namespaces["xsi"], 103 | "xsi:schemaLocation", this.schemaLocation 104 | ); 105 | 106 | return OpenLayers.Format.XML.prototype.write.apply(this, [root]); 107 | }, 108 | 109 | /** 110 | * Property: writers 111 | * As a compliment to the readers property, this structure contains public 112 | * writing functions grouped by namespace alias and named like the 113 | * node names they produce. 114 | */ 115 | writers: { 116 | "gml": OpenLayers.Util.applyDefaults({ 117 | "Point": function(geometry) { 118 | var node = this.createElementNSPlus("gml:Point"); 119 | this.writeNode("coordinates", [geometry], node); 120 | return node; 121 | }, 122 | "coordinates": function(points) { 123 | var numPoints = points.length; 124 | var parts = new Array(numPoints); 125 | var point; 126 | for(var i=0; i 13 | * constructor. 14 | * 15 | * Inherits from: 16 | * - 17 | */ 18 | OpenLayers.Format.OWSCommon = OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC, { 19 | 20 | /** 21 | * APIProperty: defaultVersion 22 | * {String} Version number to assume if none found. Default is "1.0.0". 23 | */ 24 | defaultVersion: "1.0.0", 25 | 26 | /** 27 | * Constructor: OpenLayers.Format.OWSCommon 28 | * Create a new parser for OWSCommon. 29 | * 30 | * Parameters: 31 | * options - {Object} An optional object whose properties will be set on 32 | * this instance. 33 | */ 34 | 35 | /** 36 | * Method: getVersion 37 | * Returns the version to use. Subclasses can override this function 38 | * if a different version detection is needed. 39 | * 40 | * Parameters: 41 | * root - {DOMElement} 42 | * options - {Object} Optional configuration object. 43 | * 44 | * Returns: 45 | * {String} The version to use. 46 | */ 47 | getVersion: function(root, options) { 48 | var version = this.version; 49 | if(!version) { 50 | // remember version does not correspond to the OWS version 51 | // it corresponds to the WMS/WFS/WCS etc. request version 52 | var uri = root.getAttribute("xmlns:ows"); 53 | // the above will fail if the namespace prefix is different than 54 | // ows and if the namespace is declared on a different element 55 | if (uri && uri.substring(uri.lastIndexOf("/")+1) === "1.1") { 56 | version ="1.1.0"; 57 | } 58 | if(!version) { 59 | version = this.defaultVersion; 60 | } 61 | } 62 | return version; 63 | }, 64 | 65 | /** 66 | * APIMethod: read 67 | * Read an OWSCommon document and return an object. 68 | * 69 | * Parameters: 70 | * data - {String | DOMElement} Data to read. 71 | * options - {Object} Options for the reader. 72 | * 73 | * Returns: 74 | * {Object} An object representing the structure of the document. 75 | */ 76 | 77 | CLASS_NAME: "OpenLayers.Format.OWSCommon" 78 | }); 79 | -------------------------------------------------------------------------------- /wps/www/OpenLayers/Format/OWSCommon/v1.js: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for 2 | * full list of contributors). Published under the 2-clause BSD license. 3 | * See license.txt in the OpenLayers distribution or repository for the 4 | * full text of the license. */ 5 | 6 | /** 7 | * @requires OpenLayers/Format/OWSCommon.js 8 | */ 9 | 10 | /** 11 | * Class: OpenLayers.Format.OWSCommon.v1 12 | * Common readers and writers for OWSCommon v1.X formats 13 | * 14 | * Inherits from: 15 | * - 16 | */ 17 | OpenLayers.Format.OWSCommon.v1 = OpenLayers.Class(OpenLayers.Format.XML, { 18 | 19 | /** 20 | * Property: regExes 21 | * Compiled regular expressions for manipulating strings. 22 | */ 23 | regExes: { 24 | trimSpace: (/^\s*|\s*$/g), 25 | removeSpace: (/\s*/g), 26 | splitSpace: (/\s+/), 27 | trimComma: (/\s*,\s*/g) 28 | }, 29 | 30 | /** 31 | * Method: read 32 | * 33 | * Parameters: 34 | * data - {DOMElement} An OWSCommon document element. 35 | * options - {Object} Options for the reader. 36 | * 37 | * Returns: 38 | * {Object} An object representing the OWSCommon document. 39 | */ 40 | read: function(data, options) { 41 | options = OpenLayers.Util.applyDefaults(options, this.options); 42 | var ows = {}; 43 | this.readChildNodes(data, ows); 44 | return ows; 45 | }, 46 | 47 | /** 48 | * Property: readers 49 | * Contains public functions, grouped by namespace prefix, that will 50 | * be applied when a namespaced node is found matching the function 51 | * name. The function will be applied in the scope of this parser 52 | * with two arguments: the node being read and a context object passed 53 | * from the parent. 54 | */ 55 | readers: { 56 | "ows": { 57 | "Exception": function(node, exceptionReport) { 58 | var exception = { 59 | code: node.getAttribute('exceptionCode'), 60 | locator: node.getAttribute('locator'), 61 | texts: [] 62 | }; 63 | exceptionReport.exceptions.push(exception); 64 | this.readChildNodes(node, exception); 65 | }, 66 | "ExceptionText": function(node, exception) { 67 | var text = this.getChildValue(node); 68 | exception.texts.push(text); 69 | }, 70 | "ServiceIdentification": function(node, obj) { 71 | obj.serviceIdentification = {}; 72 | this.readChildNodes(node, obj.serviceIdentification); 73 | }, 74 | "Title": function(node, obj) { 75 | obj.title = this.getChildValue(node); 76 | }, 77 | "Abstract": function(node, serviceIdentification) { 78 | serviceIdentification["abstract"] = this.getChildValue(node); 79 | }, 80 | "Keywords": function(node, serviceIdentification) { 81 | serviceIdentification.keywords = {}; 82 | this.readChildNodes(node, serviceIdentification.keywords); 83 | }, 84 | "Keyword": function(node, keywords) { 85 | keywords[this.getChildValue(node)] = true; 86 | }, 87 | "ServiceType": function(node, serviceIdentification) { 88 | serviceIdentification.serviceType = { 89 | codeSpace: node.getAttribute('codeSpace'), 90 | value: this.getChildValue(node)}; 91 | }, 92 | "ServiceTypeVersion": function(node, serviceIdentification) { 93 | serviceIdentification.serviceTypeVersion = this.getChildValue(node); 94 | }, 95 | "Fees": function(node, serviceIdentification) { 96 | serviceIdentification.fees = this.getChildValue(node); 97 | }, 98 | "AccessConstraints": function(node, serviceIdentification) { 99 | serviceIdentification.accessConstraints = 100 | this.getChildValue(node); 101 | }, 102 | "ServiceProvider": function(node, obj) { 103 | obj.serviceProvider = {}; 104 | this.readChildNodes(node, obj.serviceProvider); 105 | }, 106 | "ProviderName": function(node, serviceProvider) { 107 | serviceProvider.providerName = this.getChildValue(node); 108 | }, 109 | "ProviderSite": function(node, serviceProvider) { 110 | serviceProvider.providerSite = this.getAttributeNS(node, 111 | this.namespaces.xlink, "href"); 112 | }, 113 | "ServiceContact": function(node, serviceProvider) { 114 | serviceProvider.serviceContact = {}; 115 | this.readChildNodes(node, serviceProvider.serviceContact); 116 | }, 117 | "IndividualName": function(node, serviceContact) { 118 | serviceContact.individualName = this.getChildValue(node); 119 | }, 120 | "PositionName": function(node, serviceContact) { 121 | serviceContact.positionName = this.getChildValue(node); 122 | }, 123 | "ContactInfo": function(node, serviceContact) { 124 | serviceContact.contactInfo = {}; 125 | this.readChildNodes(node, serviceContact.contactInfo); 126 | }, 127 | "Phone": function(node, contactInfo) { 128 | contactInfo.phone = {}; 129 | this.readChildNodes(node, contactInfo.phone); 130 | }, 131 | "Voice": function(node, phone) { 132 | phone.voice = this.getChildValue(node); 133 | }, 134 | "Address": function(node, contactInfo) { 135 | contactInfo.address = {}; 136 | this.readChildNodes(node, contactInfo.address); 137 | }, 138 | "DeliveryPoint": function(node, address) { 139 | address.deliveryPoint = this.getChildValue(node); 140 | }, 141 | "City": function(node, address) { 142 | address.city = this.getChildValue(node); 143 | }, 144 | "AdministrativeArea": function(node, address) { 145 | address.administrativeArea = this.getChildValue(node); 146 | }, 147 | "PostalCode": function(node, address) { 148 | address.postalCode = this.getChildValue(node); 149 | }, 150 | "Country": function(node, address) { 151 | address.country = this.getChildValue(node); 152 | }, 153 | "ElectronicMailAddress": function(node, address) { 154 | address.electronicMailAddress = this.getChildValue(node); 155 | }, 156 | "Role": function(node, serviceContact) { 157 | serviceContact.role = this.getChildValue(node); 158 | }, 159 | "OperationsMetadata": function(node, obj) { 160 | obj.operationsMetadata = {}; 161 | this.readChildNodes(node, obj.operationsMetadata); 162 | }, 163 | "Operation": function(node, operationsMetadata) { 164 | var name = node.getAttribute("name"); 165 | operationsMetadata[name] = {}; 166 | this.readChildNodes(node, operationsMetadata[name]); 167 | }, 168 | "DCP": function(node, operation) { 169 | operation.dcp = {}; 170 | this.readChildNodes(node, operation.dcp); 171 | }, 172 | "HTTP": function(node, dcp) { 173 | dcp.http = {}; 174 | this.readChildNodes(node, dcp.http); 175 | }, 176 | "Get": function(node, http) { 177 | if (!http.get) { 178 | http.get = []; 179 | } 180 | var obj = { 181 | url: this.getAttributeNS(node, this.namespaces.xlink, "href") 182 | }; 183 | this.readChildNodes(node, obj); 184 | http.get.push(obj); 185 | }, 186 | "Post": function(node, http) { 187 | if (!http.post) { 188 | http.post = []; 189 | } 190 | var obj = { 191 | url: this.getAttributeNS(node, this.namespaces.xlink, "href") 192 | }; 193 | this.readChildNodes(node, obj); 194 | http.post.push(obj); 195 | }, 196 | "Parameter": function(node, operation) { 197 | if (!operation.parameters) { 198 | operation.parameters = {}; 199 | } 200 | var name = node.getAttribute("name"); 201 | operation.parameters[name] = {}; 202 | this.readChildNodes(node, operation.parameters[name]); 203 | }, 204 | "Constraint": function(node, obj) { 205 | if (!obj.constraints) { 206 | obj.constraints = {}; 207 | } 208 | var name = node.getAttribute("name"); 209 | obj.constraints[name] = {}; 210 | this.readChildNodes(node, obj.constraints[name]); 211 | }, 212 | "Value": function(node, allowedValues) { 213 | allowedValues[this.getChildValue(node)] = true; 214 | }, 215 | "OutputFormat": function(node, obj) { 216 | obj.formats.push({value: this.getChildValue(node)}); 217 | this.readChildNodes(node, obj); 218 | }, 219 | "WGS84BoundingBox": function(node, obj) { 220 | var boundingBox = {}; 221 | boundingBox.crs = node.getAttribute("crs"); 222 | if (obj.BoundingBox) { 223 | obj.BoundingBox.push(boundingBox); 224 | } else { 225 | obj.projection = boundingBox.crs; 226 | boundingBox = obj; 227 | } 228 | this.readChildNodes(node, boundingBox); 229 | }, 230 | "BoundingBox": function(node, obj) { 231 | // FIXME: We consider that BoundingBox is the same as WGS84BoundingBox 232 | // LowerCorner = "min_x min_y" 233 | // UpperCorner = "max_x max_y" 234 | // It should normally depend on the projection 235 | this.readers['ows']['WGS84BoundingBox'].apply(this, [node, obj]); 236 | }, 237 | "LowerCorner": function(node, obj) { 238 | var str = this.getChildValue(node).replace( 239 | this.regExes.trimSpace, ""); 240 | str = str.replace(this.regExes.trimComma, ","); 241 | var pointList = str.split(this.regExes.splitSpace); 242 | obj.left = pointList[0]; 243 | obj.bottom = pointList[1]; 244 | }, 245 | "UpperCorner": function(node, obj) { 246 | var str = this.getChildValue(node).replace( 247 | this.regExes.trimSpace, ""); 248 | str = str.replace(this.regExes.trimComma, ","); 249 | var pointList = str.split(this.regExes.splitSpace); 250 | obj.right = pointList[0]; 251 | obj.top = pointList[1]; 252 | obj.bounds = new OpenLayers.Bounds(obj.left, obj.bottom, 253 | obj.right, obj.top); 254 | delete obj.left; 255 | delete obj.bottom; 256 | delete obj.right; 257 | delete obj.top; 258 | }, 259 | "Language": function(node, obj) { 260 | obj.language = this.getChildValue(node); 261 | } 262 | } 263 | }, 264 | 265 | /** 266 | * Property: writers 267 | * As a compliment to the readers property, this structure contains public 268 | * writing functions grouped by namespace alias and named like the 269 | * node names they produce. 270 | */ 271 | writers: { 272 | "ows": { 273 | "BoundingBox": function(options, nodeName) { 274 | console.log('ows:BoundingBox'); 275 | console.log(options); 276 | console.log(nodeName); 277 | var node = this.createElementNSPlus(nodeName || "ows:BoundingBox", { 278 | attributes: { 279 | crs: options.projection 280 | } 281 | }); 282 | this.writeNode("ows:LowerCorner", options, node); 283 | this.writeNode("ows:UpperCorner", options, node); 284 | return node; 285 | }, 286 | "LowerCorner": function(options) { 287 | var node = this.createElementNSPlus("ows:LowerCorner", { 288 | value: options.bounds.left + " " + options.bounds.bottom }); 289 | return node; 290 | }, 291 | "UpperCorner": function(options) { 292 | var node = this.createElementNSPlus("ows:UpperCorner", { 293 | value: options.bounds.right + " " + options.bounds.top }); 294 | return node; 295 | }, 296 | "Identifier": function(identifier) { 297 | var node = this.createElementNSPlus("ows:Identifier", { 298 | value: identifier }); 299 | return node; 300 | }, 301 | "Title": function(title) { 302 | var node = this.createElementNSPlus("ows:Title", { 303 | value: title }); 304 | return node; 305 | }, 306 | "Abstract": function(abstractValue) { 307 | var node = this.createElementNSPlus("ows:Abstract", { 308 | value: abstractValue }); 309 | return node; 310 | }, 311 | "OutputFormat": function(format) { 312 | var node = this.createElementNSPlus("ows:OutputFormat", { 313 | value: format }); 314 | return node; 315 | } 316 | } 317 | }, 318 | 319 | CLASS_NAME: "OpenLayers.Format.OWSCommon.v1" 320 | 321 | }); 322 | -------------------------------------------------------------------------------- /wps/www/OpenLayers/Format/OWSCommon/v1_0_0.js: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for 2 | * full list of contributors). Published under the 2-clause BSD license. 3 | * See license.txt in the OpenLayers distribution or repository for the 4 | * full text of the license. */ 5 | 6 | /** 7 | * @requires OpenLayers/Format/OWSCommon/v1.js 8 | */ 9 | 10 | /** 11 | * Class: OpenLayers.Format.OWSCommon.v1_0_0 12 | * Parser for OWS Common version 1.0.0. 13 | * 14 | * Inherits from: 15 | * - 16 | */ 17 | OpenLayers.Format.OWSCommon.v1_0_0 = OpenLayers.Class(OpenLayers.Format.OWSCommon.v1, { 18 | 19 | /** 20 | * Property: namespaces 21 | * {Object} Mapping of namespace aliases to namespace URIs. 22 | */ 23 | namespaces: { 24 | ows: "http://www.opengis.net/ows", 25 | xlink: "http://www.w3.org/1999/xlink" 26 | }, 27 | 28 | /** 29 | * Property: readers 30 | * Contains public functions, grouped by namespace prefix, that will 31 | * be applied when a namespaced node is found matching the function 32 | * name. The function will be applied in the scope of this parser 33 | * with two arguments: the node being read and a context object passed 34 | * from the parent. 35 | */ 36 | readers: { 37 | "ows": OpenLayers.Util.applyDefaults({ 38 | "ExceptionReport": function(node, obj) { 39 | obj.success = false; 40 | obj.exceptionReport = { 41 | version: node.getAttribute('version'), 42 | language: node.getAttribute('language'), 43 | exceptions: [] 44 | }; 45 | this.readChildNodes(node, obj.exceptionReport); 46 | } 47 | }, OpenLayers.Format.OWSCommon.v1.prototype.readers.ows) 48 | }, 49 | 50 | /** 51 | * Property: writers 52 | * As a compliment to the readers property, this structure contains public 53 | * writing functions grouped by namespace alias and named like the 54 | * node names they produce. 55 | */ 56 | writers: { 57 | "ows": OpenLayers.Format.OWSCommon.v1.prototype.writers.ows 58 | }, 59 | 60 | CLASS_NAME: "OpenLayers.Format.OWSCommon.v1_0_0" 61 | 62 | }); 63 | -------------------------------------------------------------------------------- /wps/www/OpenLayers/Format/OWSCommon/v1_1_0.js: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for 2 | * full list of contributors). Published under the 2-clause BSD license. 3 | * See license.txt in the OpenLayers distribution or repository for the 4 | * full text of the license. */ 5 | 6 | /** 7 | * @requires OpenLayers/Format/OWSCommon/v1.js 8 | */ 9 | 10 | /** 11 | * Class: OpenLayers.Format.OWSCommon.v1_1_0 12 | * Parser for OWS Common version 1.1.0. 13 | * 14 | * Inherits from: 15 | * - 16 | */ 17 | OpenLayers.Format.OWSCommon.v1_1_0 = OpenLayers.Class(OpenLayers.Format.OWSCommon.v1, { 18 | 19 | /** 20 | * Property: namespaces 21 | * {Object} Mapping of namespace aliases to namespace URIs. 22 | */ 23 | namespaces: { 24 | ows: "http://www.opengis.net/ows/1.1", 25 | xlink: "http://www.w3.org/1999/xlink" 26 | }, 27 | 28 | /** 29 | * Property: readers 30 | * Contains public functions, grouped by namespace prefix, that will 31 | * be applied when a namespaced node is found matching the function 32 | * name. The function will be applied in the scope of this parser 33 | * with two arguments: the node being read and a context object passed 34 | * from the parent. 35 | */ 36 | readers: { 37 | "ows": OpenLayers.Util.applyDefaults({ 38 | "ExceptionReport": function(node, obj) { 39 | obj.exceptionReport = { 40 | version: node.getAttribute('version'), 41 | language: node.getAttribute('xml:lang'), 42 | exceptions: [] 43 | }; 44 | this.readChildNodes(node, obj.exceptionReport); 45 | }, 46 | "AllowedValues": function(node, parameter) { 47 | parameter.allowedValues = {}; 48 | this.readChildNodes(node, parameter.allowedValues); 49 | }, 50 | "AnyValue": function(node, parameter) { 51 | parameter.anyValue = true; 52 | }, 53 | "DataType": function(node, parameter) { 54 | parameter.dataType = this.getChildValue(node); 55 | }, 56 | "Range": function(node, allowedValues) { 57 | allowedValues.range = {}; 58 | this.readChildNodes(node, allowedValues.range); 59 | }, 60 | "MinimumValue": function(node, range) { 61 | range.minValue = this.getChildValue(node); 62 | }, 63 | "MaximumValue": function(node, range) { 64 | range.maxValue = this.getChildValue(node); 65 | }, 66 | "Identifier": function(node, obj) { 67 | obj.identifier = this.getChildValue(node); 68 | }, 69 | "SupportedCRS": function(node, obj) { 70 | obj.supportedCRS = this.getChildValue(node); 71 | } 72 | }, OpenLayers.Format.OWSCommon.v1.prototype.readers["ows"]) 73 | }, 74 | 75 | /** 76 | * Property: writers 77 | * As a compliment to the readers property, this structure contains public 78 | * writing functions grouped by namespace alias and named like the 79 | * node names they produce. 80 | */ 81 | writers: { 82 | "ows": OpenLayers.Util.applyDefaults({ 83 | "Range": function(range) { 84 | var node = this.createElementNSPlus("ows:Range", { 85 | attributes: { 86 | 'ows:rangeClosure': range.closure 87 | } 88 | }); 89 | this.writeNode("ows:MinimumValue", range.minValue, node); 90 | this.writeNode("ows:MaximumValue", range.maxValue, node); 91 | return node; 92 | }, 93 | "MinimumValue": function(minValue) { 94 | var node = this.createElementNSPlus("ows:MinimumValue", { 95 | value: minValue 96 | }); 97 | return node; 98 | }, 99 | "MaximumValue": function(maxValue) { 100 | var node = this.createElementNSPlus("ows:MaximumValue", { 101 | value: maxValue 102 | }); 103 | return node; 104 | }, 105 | "Value": function(value) { 106 | var node = this.createElementNSPlus("ows:Value", { 107 | value: value 108 | }); 109 | return node; 110 | } 111 | }, OpenLayers.Format.OWSCommon.v1.prototype.writers["ows"]) 112 | }, 113 | 114 | CLASS_NAME: "OpenLayers.Format.OWSCommon.v1_1_0" 115 | 116 | }); 117 | -------------------------------------------------------------------------------- /wps/www/OpenLayers/Format/WCSGetCoverage.js: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for 2 | * full list of contributors). Published under the 2-clause BSD license. 3 | * See license.txt in the OpenLayers distribution or repository for the 4 | * full text of the license. */ 5 | 6 | /** 7 | * @requires OpenLayers/Format/XML.js 8 | * @requires OpenLayers/Format/OWSCommon/v1_1_0.js 9 | */ 10 | 11 | /** 12 | * Class: OpenLayers.Format.WCSGetCoverage version 1.1.0 13 | * 14 | * Inherits from: 15 | * - 16 | */ 17 | OpenLayers.Format.WCSGetCoverage = OpenLayers.Class(OpenLayers.Format.XML, { 18 | 19 | /** 20 | * Property: namespaces 21 | * {Object} Mapping of namespace aliases to namespace URIs. 22 | */ 23 | namespaces: { 24 | ows: "http://www.opengis.net/ows/1.1", 25 | wcs: "http://www.opengis.net/wcs/1.1", 26 | xlink: "http://www.w3.org/1999/xlink", 27 | xsi: "http://www.w3.org/2001/XMLSchema-instance" 28 | }, 29 | 30 | /** 31 | * Property: regExes 32 | * Compiled regular expressions for manipulating strings. 33 | */ 34 | regExes: { 35 | trimSpace: (/^\s*|\s*$/g), 36 | removeSpace: (/\s*/g), 37 | splitSpace: (/\s+/), 38 | trimComma: (/\s*,\s*/g) 39 | }, 40 | 41 | /** 42 | * Constant: VERSION 43 | * {String} 1.1.2 44 | */ 45 | VERSION: "1.1.2", 46 | 47 | /** 48 | * Property: schemaLocation 49 | * {String} Schema location 50 | */ 51 | schemaLocation: "http://www.opengis.net/wcs/1.1 http://schemas.opengis.net/wcs/1.1/wcsGetCoverage.xsd", 52 | 53 | /** 54 | * Constructor: OpenLayers.Format.WCSGetCoverage 55 | * 56 | * Parameters: 57 | * options - {Object} An optional object whose properties will be set on 58 | * this instance. 59 | */ 60 | 61 | /** 62 | * Method: write 63 | * 64 | * Parameters: 65 | * options - {Object} Optional object. 66 | * 67 | * Returns: 68 | * {String} A WCS GetCoverage request XML string. 69 | */ 70 | write: function(options) { 71 | var node = this.writeNode("wcs:GetCoverage", options); 72 | this.setAttributeNS( 73 | node, this.namespaces.xsi, 74 | "xsi:schemaLocation", this.schemaLocation 75 | ); 76 | return OpenLayers.Format.XML.prototype.write.apply(this, [node]); 77 | }, 78 | 79 | /** 80 | * Property: writers 81 | * As a compliment to the readers property, this structure contains public 82 | * writing functions grouped by namespace alias and named like the 83 | * node names they produce. 84 | */ 85 | writers: { 86 | "wcs": { 87 | "GetCoverage": function(options) { 88 | var node = this.createElementNSPlus("wcs:GetCoverage", { 89 | attributes: { 90 | version: options.version || this.VERSION, 91 | service: 'WCS' 92 | } 93 | }); 94 | this.writeNode("ows:Identifier", options.identifier, node); 95 | this.writeNode("wcs:DomainSubset", options.domainSubset, node); 96 | this.writeNode("wcs:Output", options.output, node); 97 | return node; 98 | }, 99 | "DomainSubset": function(domainSubset) { 100 | var node = this.createElementNSPlus("wcs:DomainSubset", {}); 101 | this.writeNode("ows:BoundingBox", domainSubset.boundingBox, node); 102 | if (domainSubset.temporalSubset) { 103 | this.writeNode("wcs:TemporalSubset", domainSubset.temporalSubset, node); 104 | } 105 | return node; 106 | }, 107 | "TemporalSubset": function(temporalSubset) { 108 | var node = this.createElementNSPlus("wcs:TemporalSubset", {}); 109 | for (var i=0, len=temporalSubset.timePeriods.length; i} A WFST format of the given version. 16 | */ 17 | OpenLayers.Format.WFST = function(options) { 18 | options = OpenLayers.Util.applyDefaults( 19 | options, OpenLayers.Format.WFST.DEFAULTS 20 | ); 21 | var cls = OpenLayers.Format.WFST["v"+options.version.replace(/\./g, "_")]; 22 | if(!cls) { 23 | throw "Unsupported WFST version: " + options.version; 24 | } 25 | return new cls(options); 26 | }; 27 | 28 | /** 29 | * Constant: OpenLayers.Format.WFST.DEFAULTS 30 | * {Object} Default properties for the WFST format. 31 | */ 32 | OpenLayers.Format.WFST.DEFAULTS = { 33 | "version": "1.0.0" 34 | }; 35 | -------------------------------------------------------------------------------- /wps/www/OpenLayers/Format/WFST/v1_1_0.js: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for 2 | * full list of contributors). Published under the 2-clause BSD license. 3 | * See license.txt in the OpenLayers distribution or repository for the 4 | * full text of the license. */ 5 | 6 | /** 7 | * @requires OpenLayers/Format/WFST/v1.js 8 | * @requires OpenLayers/Format/Filter/v1_1_0.js 9 | * @requires OpenLayers/Format/OWSCommon/v1_0_0.js 10 | */ 11 | 12 | /** 13 | * Class: OpenLayers.Format.WFST.v1_1_0 14 | * A format for creating WFS v1.1.0 transactions. Create a new instance with the 15 | * constructor. 16 | * 17 | * Inherits from: 18 | * - 19 | * - 20 | */ 21 | OpenLayers.Format.WFST.v1_1_0 = OpenLayers.Class( 22 | OpenLayers.Format.Filter.v1_1_0, OpenLayers.Format.WFST.v1, { 23 | 24 | /** 25 | * Property: version 26 | * {String} WFS version number. 27 | */ 28 | version: "1.1.0", 29 | 30 | /** 31 | * Property: schemaLocations 32 | * {Object} Properties are namespace aliases, values are schema locations. 33 | */ 34 | schemaLocations: { 35 | "wfs": "http://schemas.opengis.net/wfs/1.1.0/wfs.xsd" 36 | }, 37 | 38 | /** 39 | * Constructor: OpenLayers.Format.WFST.v1_1_0 40 | * A class for parsing and generating WFS v1.1.0 transactions. 41 | * 42 | * To read additional information like hit count (numberOfFeatures) from 43 | * the FeatureCollection, call the method 44 | * with {output: "object"} as 2nd argument. Note that it is possible to 45 | * just request the hit count from a WFS 1.1.0 server with the 46 | * resultType="hits" request parameter. 47 | * 48 | * Parameters: 49 | * options - {Object} Optional object whose properties will be set on the 50 | * instance. 51 | * 52 | * Valid options properties: 53 | * featureType - {String} Local (without prefix) feature typeName (required). 54 | * featureNS - {String} Feature namespace (optional). 55 | * featurePrefix - {String} Feature namespace alias (optional - only used 56 | * if featureNS is provided). Default is 'feature'. 57 | * geometryName - {String} Name of geometry attribute. Default is 'the_geom'. 58 | */ 59 | initialize: function(options) { 60 | OpenLayers.Format.Filter.v1_1_0.prototype.initialize.apply(this, [options]); 61 | OpenLayers.Format.WFST.v1.prototype.initialize.apply(this, [options]); 62 | }, 63 | 64 | /** 65 | * Method: readNode 66 | * Shorthand for applying one of the named readers given the node 67 | * namespace and local name. Readers take two args (node, obj) and 68 | * generally extend or modify the second. 69 | * 70 | * Parameters: 71 | * node - {DOMElement} The node to be read (required). 72 | * obj - {Object} The object to be modified (optional). 73 | * first - {Boolean} Should be set to true for the first node read. This 74 | * is usually the readNode call in the read method. Without this being 75 | * set, auto-configured properties will stick on subsequent reads. 76 | * 77 | * Returns: 78 | * {Object} The input object, modified (or a new one if none was provided). 79 | */ 80 | readNode: function(node, obj, first) { 81 | // Not the superclass, only the mixin classes inherit from 82 | // Format.GML.v3. We need this because we don't want to get readNode 83 | // from the superclass's superclass, which is OpenLayers.Format.XML. 84 | return OpenLayers.Format.GML.v3.prototype.readNode.apply(this, arguments); 85 | }, 86 | 87 | /** 88 | * Property: readers 89 | * Contains public functions, grouped by namespace prefix, that will 90 | * be applied when a namespaced node is found matching the function 91 | * name. The function will be applied in the scope of this parser 92 | * with two arguments: the node being read and a context object passed 93 | * from the parent. 94 | */ 95 | readers: { 96 | "wfs": OpenLayers.Util.applyDefaults({ 97 | "FeatureCollection": function(node, obj) { 98 | obj.numberOfFeatures = parseInt(node.getAttribute( 99 | "numberOfFeatures")); 100 | OpenLayers.Format.WFST.v1.prototype.readers["wfs"]["FeatureCollection"].apply( 101 | this, arguments); 102 | }, 103 | "TransactionResponse": function(node, obj) { 104 | obj.insertIds = []; 105 | obj.success = false; 106 | this.readChildNodes(node, obj); 107 | }, 108 | "TransactionSummary": function(node, obj) { 109 | // this is a limited test of success 110 | obj.success = true; 111 | }, 112 | "InsertResults": function(node, obj) { 113 | this.readChildNodes(node, obj); 114 | }, 115 | "Feature": function(node, container) { 116 | var obj = {fids: []}; 117 | this.readChildNodes(node, obj); 118 | container.insertIds.push(obj.fids[0]); 119 | } 120 | }, OpenLayers.Format.WFST.v1.prototype.readers["wfs"]), 121 | "gml": OpenLayers.Format.GML.v3.prototype.readers["gml"], 122 | "feature": OpenLayers.Format.GML.v3.prototype.readers["feature"], 123 | "ogc": OpenLayers.Format.Filter.v1_1_0.prototype.readers["ogc"], 124 | "ows": OpenLayers.Format.OWSCommon.v1_0_0.prototype.readers["ows"] 125 | }, 126 | 127 | /** 128 | * Property: writers 129 | * As a compliment to the readers property, this structure contains public 130 | * writing functions grouped by namespace alias and named like the 131 | * node names they produce. 132 | */ 133 | writers: { 134 | "wfs": OpenLayers.Util.applyDefaults({ 135 | "GetFeature": function(options) { 136 | var node = OpenLayers.Format.WFST.v1.prototype.writers["wfs"]["GetFeature"].apply(this, arguments); 137 | options && this.setAttributes(node, { 138 | resultType: options.resultType, 139 | startIndex: options.startIndex, 140 | count: options.count 141 | }); 142 | return node; 143 | }, 144 | "Query": function(options) { 145 | options = OpenLayers.Util.extend({ 146 | featureNS: this.featureNS, 147 | featurePrefix: this.featurePrefix, 148 | featureType: this.featureType, 149 | srsName: this.srsName 150 | }, options); 151 | var prefix = options.featurePrefix; 152 | var node = this.createElementNSPlus("wfs:Query", { 153 | attributes: { 154 | typeName: (prefix ? prefix + ":" : "") + 155 | options.featureType, 156 | srsName: options.srsName 157 | } 158 | }); 159 | if(options.featureNS) { 160 | node.setAttribute("xmlns:" + prefix, options.featureNS); 161 | } 162 | if(options.propertyNames) { 163 | for(var i=0,len = options.propertyNames.length; i 16 | */ 17 | OpenLayers.Format.WPSCapabilities = OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC, { 18 | 19 | /** 20 | * APIProperty: defaultVersion 21 | * {String} Version number to assume if none found. Default is "1.0.0". 22 | */ 23 | defaultVersion: "1.0.0", 24 | 25 | /** 26 | * Constructor: OpenLayers.Format.WPSCapabilities 27 | * Create a new parser for WPS Capabilities. 28 | * 29 | * Parameters: 30 | * options - {Object} An optional object whose properties will be set on 31 | * this instance. 32 | */ 33 | 34 | /** 35 | * APIMethod: read 36 | * Read capabilities data from a string, and return information about 37 | * the service. 38 | * 39 | * Parameters: 40 | * data - {String} or {DOMElement} data to read/parse. 41 | * 42 | * Returns: 43 | * {Object} Info about the WPS 44 | */ 45 | 46 | CLASS_NAME: "OpenLayers.Format.WPSCapabilities" 47 | 48 | }); 49 | -------------------------------------------------------------------------------- /wps/www/OpenLayers/Format/WPSCapabilities/v1_0_0.js: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for 2 | * full list of contributors). Published under the 2-clause BSD license. 3 | * See license.txt in the OpenLayers distribution or repository for the 4 | * full text of the license. */ 5 | 6 | /** 7 | * @requires OpenLayers/Format/WPSCapabilities.js 8 | * @requires OpenLayers/Format/OWSCommon/v1_1_0.js 9 | */ 10 | 11 | /** 12 | * Class: OpenLayers.Format.WPSCapabilities.v1_0_0 13 | * Read WPS Capabilities version 1.0.0. 14 | * 15 | * Inherits from: 16 | * - 17 | */ 18 | OpenLayers.Format.WPSCapabilities.v1_0_0 = OpenLayers.Class( 19 | OpenLayers.Format.XML, { 20 | 21 | /** 22 | * Property: namespaces 23 | * {Object} Mapping of namespace aliases to namespace URIs. 24 | */ 25 | namespaces: { 26 | ows: "http://www.opengis.net/ows/1.1", 27 | wps: "http://www.opengis.net/wps/1.0.0", 28 | xlink: "http://www.w3.org/1999/xlink" 29 | }, 30 | 31 | /** 32 | * Property: regExes 33 | * Compiled regular expressions for manipulating strings. 34 | */ 35 | regExes: { 36 | trimSpace: (/^\s*|\s*$/g), 37 | removeSpace: (/\s*/g), 38 | splitSpace: (/\s+/), 39 | trimComma: (/\s*,\s*/g) 40 | }, 41 | 42 | /** 43 | * Constructor: OpenLayers.Format.WPSCapabilities.v1_0_0 44 | * Create a new parser for WPS capabilities version 1.0.0. 45 | * 46 | * Parameters: 47 | * options - {Object} An optional object whose properties will be set on 48 | * this instance. 49 | */ 50 | initialize: function(options) { 51 | OpenLayers.Format.XML.prototype.initialize.apply(this, [options]); 52 | }, 53 | 54 | /** 55 | * APIMethod: read 56 | * Read capabilities data from a string, and return info about the WPS. 57 | * 58 | * Parameters: 59 | * data - {String} or {DOMElement} data to read/parse. 60 | * 61 | * Returns: 62 | * {Object} Information about the WPS service. 63 | */ 64 | read: function(data) { 65 | if(typeof data == "string") { 66 | data = OpenLayers.Format.XML.prototype.read.apply(this, [data]); 67 | } 68 | if(data && data.nodeType == 9) { 69 | data = data.documentElement; 70 | } 71 | var capabilities = {}; 72 | this.readNode(data, capabilities); 73 | return capabilities; 74 | }, 75 | 76 | /** 77 | * Property: readers 78 | * Contains public functions, grouped by namespace prefix, that will 79 | * be applied when a namespaced node is found matching the function 80 | * name. The function will be applied in the scope of this parser 81 | * with two arguments: the node being read and a context object passed 82 | * from the parent. 83 | */ 84 | readers: { 85 | "wps": { 86 | "Capabilities": function(node, obj) { 87 | this.readChildNodes(node, obj); 88 | }, 89 | "ProcessOfferings": function(node, obj) { 90 | obj.processOfferings = {}; 91 | this.readChildNodes(node, obj.processOfferings); 92 | }, 93 | "Process": function(node, processOfferings) { 94 | var processVersion = this.getAttributeNS(node, this.namespaces.wps, "processVersion"); 95 | var process = {processVersion: processVersion}; 96 | this.readChildNodes(node, process); 97 | processOfferings[process.identifier] = process; 98 | }, 99 | "Languages": function(node, obj) { 100 | obj.languages = []; 101 | this.readChildNodes(node, obj.languages); 102 | }, 103 | "Default": function(node, languages) { 104 | var language = {isDefault: true}; 105 | this.readChildNodes(node, language); 106 | languages.push(language); 107 | }, 108 | "Supported": function(node, languages) { 109 | var language = {}; 110 | this.readChildNodes(node, language); 111 | languages.push(language); 112 | } 113 | }, 114 | "ows": OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers["ows"] 115 | }, 116 | 117 | CLASS_NAME: "OpenLayers.Format.WPSCapabilities.v1_0_0" 118 | 119 | }); 120 | -------------------------------------------------------------------------------- /wps/www/OpenLayers/Format/WPSDescribeProcess.js: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for 2 | * full list of contributors). Published under the 2-clause BSD license. 3 | * See license.txt in the OpenLayers distribution or repository for the 4 | * full text of the license. */ 5 | 6 | /** 7 | * @requires OpenLayers/Format/XML.js 8 | * @requires OpenLayers/Format/OWSCommon/v1_1_0.js 9 | */ 10 | 11 | /** 12 | * Class: OpenLayers.Format.WPSDescribeProcess 13 | * Read WPS DescribeProcess responses. 14 | * 15 | * Inherits from: 16 | * - 17 | */ 18 | OpenLayers.Format.WPSDescribeProcess = OpenLayers.Class( 19 | OpenLayers.Format.XML, { 20 | 21 | /** 22 | * Constant: VERSION 23 | * {String} 1.0.0 24 | */ 25 | VERSION: "1.0.0", 26 | 27 | /** 28 | * Property: namespaces 29 | * {Object} Mapping of namespace aliases to namespace URIs. 30 | */ 31 | namespaces: { 32 | wps: "http://www.opengis.net/wps/1.0.0", 33 | ows: "http://www.opengis.net/ows/1.1", 34 | xsi: "http://www.w3.org/2001/XMLSchema-instance" 35 | }, 36 | 37 | /** 38 | * Property: schemaLocation 39 | * {String} Schema location 40 | */ 41 | schemaLocation: "http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsAll.xsd", 42 | 43 | /** 44 | * Property: defaultPrefix 45 | */ 46 | defaultPrefix: "wps", 47 | 48 | /** 49 | * Property: regExes 50 | * Compiled regular expressions for manipulating strings. 51 | */ 52 | regExes: { 53 | trimSpace: (/^\s*|\s*$/g), 54 | removeSpace: (/\s*/g), 55 | splitSpace: (/\s+/), 56 | trimComma: (/\s*,\s*/g) 57 | }, 58 | 59 | /** 60 | * Constructor: OpenLayers.Format.WPSDescribeProcess 61 | * 62 | * Parameters: 63 | * options - {Object} An optional object whose properties will be set on 64 | * this instance. 65 | */ 66 | 67 | /** 68 | * APIMethod: read 69 | * Parse a WPS DescribeProcess and return an object with its information. 70 | * 71 | * Parameters: 72 | * data - {String} or {DOMElement} data to read/parse. 73 | * 74 | * Returns: 75 | * {Object} 76 | */ 77 | read: function(data) { 78 | if(typeof data == "string") { 79 | data = OpenLayers.Format.XML.prototype.read.apply(this, [data]); 80 | } 81 | if(data && data.nodeType == 9) { 82 | data = data.documentElement; 83 | } 84 | var info = {}; 85 | this.readNode(data, info); 86 | return info; 87 | }, 88 | 89 | /** 90 | * Property: readers 91 | * Contains public functions, grouped by namespace prefix, that will 92 | * be applied when a namespaced node is found matching the function 93 | * name. The function will be applied in the scope of this parser 94 | * with two arguments: the node being read and a context object passed 95 | * from the parent. 96 | */ 97 | readers: { 98 | "wps": { 99 | "ProcessDescriptions": function(node, obj) { 100 | obj.processDescriptions = {}; 101 | this.readChildNodes(node, obj.processDescriptions); 102 | }, 103 | "ProcessDescription": function(node, processDescriptions) { 104 | var processVersion = this.getAttributeNS(node, this.namespaces.wps, "processVersion"); 105 | var processDescription = { 106 | processVersion: processVersion, 107 | statusSupported: (node.getAttribute("statusSupported") === "true"), 108 | storeSupported: (node.getAttribute("storeSupported") === "true") 109 | }; 110 | this.readChildNodes(node, processDescription); 111 | processDescriptions[processDescription.identifier] = processDescription; 112 | }, 113 | "DataInputs": function(node, processDescription) { 114 | processDescription.dataInputs = []; 115 | this.readChildNodes(node, processDescription.dataInputs); 116 | }, 117 | "ProcessOutputs": function(node, processDescription) { 118 | processDescription.processOutputs = []; 119 | this.readChildNodes(node, processDescription.processOutputs); 120 | }, 121 | "Output": function(node, processOutputs) { 122 | var output = {}; 123 | this.readChildNodes(node, output); 124 | processOutputs.push(output); 125 | }, 126 | "ComplexOutput": function(node, output) { 127 | output.complexOutput = {}; 128 | this.readChildNodes(node, output.complexOutput); 129 | }, 130 | "LiteralOutput": function(node, output) { 131 | output.literalOutput = {}; 132 | this.readChildNodes(node, output.literalOutput); 133 | }, 134 | "Input": function(node, dataInputs) { 135 | var input = { 136 | maxOccurs: parseInt(node.getAttribute("maxOccurs")), 137 | minOccurs: parseInt(node.getAttribute("minOccurs")) 138 | }; 139 | this.readChildNodes(node, input); 140 | dataInputs.push(input); 141 | }, 142 | "BoundingBoxData": function(node, input) { 143 | input.boundingBoxData = {}; 144 | this.readChildNodes(node, input.boundingBoxData); 145 | }, 146 | "CRS": function(node, obj) { 147 | if (!obj.CRSs) { 148 | obj.CRSs = {}; 149 | } 150 | obj.CRSs[this.getChildValue(node)] = true; 151 | }, 152 | "LiteralData": function(node, input) { 153 | input.literalData = {}; 154 | this.readChildNodes(node, input.literalData); 155 | }, 156 | "ComplexData": function(node, input) { 157 | input.complexData = {}; 158 | this.readChildNodes(node, input.complexData); 159 | }, 160 | "Default": function(node, complexData) { 161 | complexData["default"] = {}; 162 | this.readChildNodes(node, complexData["default"]); 163 | }, 164 | "Supported": function(node, complexData) { 165 | complexData["supported"] = {}; 166 | this.readChildNodes(node, complexData["supported"]); 167 | }, 168 | "Format": function(node, obj) { 169 | var format = {}; 170 | this.readChildNodes(node, format); 171 | if (!obj.formats) { 172 | obj.formats = {}; 173 | } 174 | obj.formats[format.mimeType] = true; 175 | }, 176 | "MimeType": function(node, format) { 177 | format.mimeType = this.getChildValue(node); 178 | } 179 | }, 180 | "ows": OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers["ows"] 181 | }, 182 | 183 | CLASS_NAME: "OpenLayers.Format.WPSDescribeProcess" 184 | 185 | }); 186 | -------------------------------------------------------------------------------- /wps/www/wps.css: -------------------------------------------------------------------------------- 1 | #processing-form-container label.checkbox.inline.disabled { 2 | color: #ccc; 3 | } 4 | 5 | #processing-results > div.menu-content { 6 | background-color: transparent; /* remove color for atlas */ 7 | font-size: 12px; 8 | } 9 | 10 | #processing-log-table tr td div.progress{ 11 | width:50px; 12 | } 13 | #processing-log-table tr td div.progress div.bar { 14 | animation: slide 5000ms infinite linear; 15 | } 16 | #processing-log-table tr td div.progress div.bar-hidden { 17 | background-color: transparent; 18 | background-image: none; 19 | animation: slide-hidden 5000ms infinite linear; 20 | } 21 | 22 | #processing-log-list{ 23 | list-style: none; 24 | margin-left: 0; 25 | } 26 | 27 | #processing-log-list .title{ 28 | cursor: pointer; 29 | } 30 | 31 | #processing-log-list li .title:before{ 32 | content: "\2023"; 33 | margin-right: 5px; 34 | font-size: 1.5em; 35 | vertical-align: middle; 36 | } 37 | 38 | #processing-log-list li.expanded .title:before{ 39 | display: inline-block; 40 | transform: rotate(90deg); 41 | } 42 | 43 | #processing-log-list li .processing-log-list-results{ 44 | display: none; 45 | } 46 | 47 | #processing-log-list li.expanded .processing-log-list-results{ 48 | display: block; 49 | } 50 | 51 | #processing-log-list li .processing-log-list-results input[type="checkbox"] { 52 | margin: 0; 53 | align-self: baseline; 54 | accent-color: var(--color-contrasted-elements); 55 | flex: 0 0 18px; 56 | height: 18px; 57 | width: 18px; 58 | } 59 | 60 | #processing-log-list li .processing-log-list-results label { 61 | font-size: 12px; 62 | } 63 | 64 | #processing-results-all{ 65 | display: flex; 66 | box-sizing: border-box; 67 | width: 100%; 68 | background-color: rgb(240, 240, 240); 69 | margin: 5px 0px; 70 | padding: 0px 5px; 71 | } 72 | 73 | #processing-results-all > div{ 74 | padding: 2px; 75 | } 76 | 77 | #processing-results-all > div + div{ 78 | flex: 1 1 0px; 79 | border-left: solid 1px lightgray; 80 | } 81 | 82 | #processing-log-failed { 83 | border: 1px solid #F00; 84 | border-radius: 4px; 85 | padding: 0 5px; 86 | } 87 | 88 | #processing-results-list > div { 89 | padding: 0 5px; 90 | } 91 | 92 | #processing-results-list h4.title, 93 | #processing-log-failed h4.title { 94 | background-color: #f9f9f9; 95 | padding: 5px 0; 96 | font-size: 20px; 97 | } 98 | 99 | #processing-log-failed-info { 100 | display: flex; overflow: auto; 101 | } 102 | 103 | #processing-log-failed-info > div { 104 | margin:0 5px; width: 50%; 105 | } 106 | 107 | #processing-results-plot, 108 | #processing-results-list .processing-results-plot-table{ 109 | display: flex; 110 | overflow: auto; 111 | } 112 | 113 | #processing-results-plot > div, 114 | #processing-results-list .processing-results-plot-table > div{ 115 | flex: 1; 116 | overflow: auto; 117 | } 118 | 119 | #bottom-dock{ 120 | width:auto; 121 | } 122 | 123 | @keyframes slide { 124 | 0% { width: 0%; } 125 | 50% { width: 100%; } 126 | 100% { width: 0%; } 127 | } 128 | 129 | @keyframes slide-hidden { 130 | 0% { width: 0%; } 131 | 50% { width: 0%; } 132 | 100% { width: 100%; } 133 | } 134 | --------------------------------------------------------------------------------