U
    TGˆh1  ã                   @   sÜ  d Z dZdZddlZddlZddlmZ ddlmZ ddl	m
Z
mZmZmZ ddlmZmZmZmZmZmZmZmZ dd	lmZmZ dd
lmZ ddlmZ d7e
eef eeddœdd„Z dd„ Z!eeee dœdd„Z"eeee dœdd„Z#ee$edœdd„Z%eee
df dœdd„Z&eddee'ee
df dœd d!„ƒZ(e
ee
df d"œd#d$„Z)e
eee
df d%œd&d'„Z*eee d(œd)d*„Z+eed(œd+d,„Z,ee-d(œd-d.„Z.ee-d(œd/d0„Z/eeed1œd2d3„Z0ee$eed4œd5d6„Z1dS )8zCopyright 2021, 3LizzGPL version 3zinfo@3liz.orgé    N)Ú	lru_cache)ÚPath)ÚDictÚOptionalÚTupleÚUnion)ÚQgisÚQgsExpressionÚ
QgsFeatureÚ	QgsFieldsÚQgsMapLayerÚ
QgsProjectÚQgsVectorDataProviderÚQgsVectorLayer)ÚQgsRequestHandlerÚQgsServerResponse)ÚLogger)Úto_booléÈ   )ÚdataÚresponseÚcodeÚreturnc                 C   s:   |  |¡ | dd¡ t d| › ¡ | t | ¡¡ dS )z Write data as JSON response. zContent-Typezapplication/jsonzSending JSON response : N)ÚsetStatusCodeÚ	setHeaderr   ÚinfoÚwriteÚjsonÚdumps)r   r   r   © r   ú4/var/www/lizmap/lizmap/plugins/lizmap_server/core.pyÚwrite_json_response   s    
r!   c                 C   s6   |   d|   dd¡¡}|sdS t||ƒ}|s.dS d|fS )z; Trying to find the layer in the URL in the given project. ÚLAYERÚlayerÚ )FNT)ÚgetÚfind_vector_layer)ÚparamsÚprojectÚ
layer_namer#   r   r   r    Úfind_vector_layer_from_params$   s    
r*   )r)   r(   r   c                 C   sÐ   d}|  ¡  ¡ D ]r}| ¡ | kr(|} q„t ¡ dk rJ| ¡ | krJ|} q„n$t ¡ dkrn| ¡  ¡ | krn|} q„| ¡ | kr|} q„q|s¨t 	d| › d| 
¡ › d¡ dS | ¡ sÌt 	d| › d| 
¡ › d¡ |S )z/ Find layer with name, short name or layer ID. Ni„  zThe layer 'z%' has not been found in the project 'ú'z5' has been found but it is not valid in the project ')Ú	mapLayersÚvaluesÚnamer   Ú
versionIntÚ	shortNameÚserverPropertiesÚidr   ÚwarningÚfileNameÚisValid)r)   r(   Úfoundr#   r   r   r    Ú
find_layer4   s0    ÿÿr7   c                 C   s*   t | |ƒ}|sdS | ¡ tjjks&dS |S )z6 Find vector layer with name, short name or layer ID. N)r7   Útyper   Ú	LayerTypeÚVectorLayer)r)   r(   r#   r   r   r    r&   Y   s    
r&   )ÚfeatureÚpk_attributesr   c                    s(   |st ˆ  ¡ ƒS d ‡ fdd„|D ƒ¡S )z Build server feature ID. ú@@c                    s   g | ]}t ˆ  |¡ƒ‘qS r   )ÚstrÚ	attribute)Ú.0Zpk©r;   r   r    Ú
<listcomp>j   s     z"get_server_fid.<locals>.<listcomp>)r>   r2   Újoin)r;   r<   r   rA   r    Úget_server_fide   s    rD   )Úqgis_project_pathr   c                 C   sf   t ƒ }tj | ¡sdS | d }tj |¡s8| d¡ dS t|ƒ ¡ j}| d|› d|› ¡ t||ƒS )z2 Get the lizmap config based on QGIS project path Nz.cfgzLizmap config does not existz	Fetching z) cfg file with last modified timestamp : )	r   ÚosÚpathÚexistsr   r   ÚstatÚst_mtimeÚ_get_lizmap_config)rE   ÚloggerÚconfig_pathÚlast_modifiedr   r   r    Úget_lizmap_configm   s    
rO   éd   )Úmaxsize)rM   rN   r   c                 C   sª   |}t ƒ }t| dƒŒ}z>t | ¡ ¡}|sD| d¡ W W 5 Q R £ dS |W W  5 Q R £ S  tk
rš } z(| d¡ | |¡ W Y ¢W 5 Q R £ dS d}~X Y nX W 5 Q R X dS )z> Get the lizmap config based on QGIS project path with cache. ÚrzLizmap config is emptyNzLizmap config not well formed)	r   Úopenr   ÚloadsÚreadr3   Ú	ExceptionÚcriticalÚlog_exception)rM   rN   Ú_rL   Zcfg_fileZcfgÚer   r   r    rK   …   s    


rK   )Úconfigr   c                 C   sP   | sdS t ƒ }d| ks| d s,| d¡ dS | d }t|tƒsL| d¡ dS |S )z Get layers Lizmap config NÚlayerszLizmap config has no layersz Layers lizmap config is not dict)r   r3   Ú
isinstanceÚdict)r[   rL   Z
cfg_layersr   r   r    Úget_lizmap_layers_config   s    


r_   )r[   r)   r   c                 C   sÐ   | rt | tƒsdS |r t |tƒs$dS tƒ }d| ks:| d sH| d¡ dS | d }||ks`|| sv| d|› d¡ dS || }t |tƒsž| d|› d¡ dS d|ks¶d	|ks¶d
|krÌ| d|› d¡ dS |S )z# Get loginFilteredLayers for layer NZloginFilteredLayersz(Lizmap config has no loginFilteredLayerszLayer z has no loginFilteredLayerszloginFilteredLayers for layer z is not dictZlayerIdZfilterAttributeZfilterPrivatez not well formed)r]   r^   r>   r   r   r3   )r[   r)   rL   Zlogin_filtered_layersZcfg_layer_login_filterr   r   r    Úget_lizmap_layer_login_filter·   s0    

ÿþr`   )Úhandlerr   c                 C   sÖ   g }t ƒ }|  ¡ }|r^| d¡ | d¡}|dk	rhdd„ | d¡D ƒ}| dd |¡› ¡ n
| d¡ t|ƒd	kr|t|ƒS | d
¡ |  ¡ }|rÎ| d¡}|dk	rÎdd„ | d¡D ƒ}| dd |¡› ¡ t|ƒS )z0 Get Lizmap user groups provided by the request úRequest headers providedzX-Lizmap-User-GroupsNc                 S   s   g | ]}|  ¡ ‘qS r   ©Ústrip©r@   Úgr   r   r    rB   ï   s     z%get_lizmap_groups.<locals>.<listcomp>ú,z(Lizmap user groups in request headers : úNo request headers providedr   z(No lizmap user groups in request headersZLIZMAP_USER_GROUPSc                 S   s   g | ]}|  ¡ ‘qS r   rc   re   r   r   r    rB      s     z#Lizmap user groups in parameters : )	r   ÚrequestHeadersr   r%   ÚsplitrC   ÚlenÚtupleÚparameterMap)ra   ÚgroupsrL   ÚheadersZuser_groupsr'   r   r   r    Úget_lizmap_groupsá   s(    




rp   c                 C   sš   d}t ƒ }|  ¡ }|rH| d¡ | d¡}|dk	rR|}| d|› ¡ n
| d¡ |rZ|S | d¡ |  ¡ }|r–| d¡}|dk	r–|}| d	|› ¡ |S )
ú/ Get Lizmap user login provided by the request r$   rb   zX-Lizmap-UserNz'Lizmap user login in request headers : rh   z'No lizmap user login in request headersZLIZMAP_USERz"Lizmap user login in parameters : )r   ri   r   r%   rm   )ra   ZloginrL   ro   Ú
user_loginr'   r   r   r    Úget_lizmap_user_login  s(    




rs   c                 C   sª   d}t ƒ }|  ¡ }|rF| d¡ | d¡}|dk	rPt|ƒ}| d¡ n
| d¡ |dk	r\|S | d¡ |  ¡ }|r¦| d¡}|dk	r˜t|ƒ}| d¡ nd	}| d
¡ |S )rq   Nrb   zX-Lizmap-Override-Filterz)Lizmap override filter in request headersrh   z,No lizmap override filter in request headersZLIZMAP_OVERRIDE_FILTERz$Lizmap override filter in parametersFz'No lizmap override filter in parameters)r   ri   r   r%   r   rm   )ra   ÚoverriderL   ro   Zoverride_filterr'   r   r   r    Úget_lizmap_override_filter+  s,    





ru   c                 C   s’   t ƒ }|  ¡ }|r@| d¡}|dk	r@t|ƒ}| d|› ¡ |S | d¡ |  ¡ }|r„| d¡}|dk	r„t|ƒ}| d|› ¡ |S | d¡ dS )	z3 Check if headers are defining an editing context. zX-Lizmap-Edition-ContextNz5Lizmap editing context is found in request headers : z+No editing context found in request headersZLIZMAP_EDITION_CONTEXTz0Lizmap editing context is found in parameters : zDNo lizmap editing context filter in parameters : default value falseF)r   ri   r%   r   r   rm   )ra   rL   ro   Zediting_contextÚresultr'   r   r   r    Úis_editing_contextR  s$    



rw   )Ú
feature_idÚdata_providerr   c                 C   s6   t jdkr"ddlm} | | |¡S t| | ¡ | ¡ ƒS )zT Fetch the QGIS server feature ID expression according to the current QGIS version. i~  r   )ÚQgsServerFeatureId)r   ÚQGIS_VERSION_INTÚqgis.serverrz   ZgetExpressionFromServerFidÚ_server_feature_id_expressionÚpkAttributeIndexesÚfields)rx   ry   rz   r   r   r    Úserver_feature_id_expressionl  s    
r€   )rx   r<   r   r   c                 C   sf   t |ƒdkrdS d}|  d¡}t|ƒD ]:\}}|dkr>|d7 }| |¡ ¡ }|t ||| ¡7 }q&|S )z~ Port of QgsServerFeatureId::getExpressionFromServerFid for QGIS < 3.24

    The value "@@" is hardcoded in the CPP file.
    r   r$   r=   z AND )rk   rj   Ú	enumerateÚatr.   r	   ZcreateFieldEqualityExpression)rx   r<   r   Ú
expressionZ	pk_valuesÚiZpk_valueÚ
field_namer   r   r    r}   w  s    
r}   )r   )2Ú__copyright__Ú__license__Ú	__email__r   rF   Ú	functoolsr   Úpathlibr   Útypingr   r   r   r   Ú	qgis.corer   r	   r
   r   r   r   r   r   r|   r   r   Úlizmap_server.loggerr   Úlizmap_server.toolsr   r>   Úintr!   r*   r7   r&   ÚlistrD   rO   ÚfloatrK   r_   r`   rp   rs   Úboolru   rw   r€   r}   r   r   r   r    Ú<module>   s6   (
%*&$'