
    h)N                        d dl Z d dlmZ d dlmZ d dlmZ d dlmZm	Z	 d dl
mZ d dlmZ d dlmZ d d	lmZmZmZ d
dl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%m&Z& 	 d dl'm(Z(  ed      Z* ed      Z+ ed      Z, ed      Z-d Z. G d dej^                        Z0 G d dejb                        Z2 G d dejb                        Z3y# e)$ r dZ(Y lw xY w)    N)settings)GenericForeignKey)ContentType)modelstransaction)timezone)localize)gettext_lazy)FSMFieldcan_proceed
transition   )	constantsversionables)
Conditionsdraft_is_lockeddraft_is_not_lockedin_stateis_not_lockeduser_can_changeuser_can_publishuser_can_unlock)ALLOW_DELETING_VERSIONSLOCK_VERSIONS)send_post_version_operationsend_pre_version_operation)emit_content_changezVersion is not a draftz5Action Denied. The latest version is locked by {user}z4Action Denied. The draft version is locked by {user}z1You do not have permission to perform this actionc                 r    t         rt        j                  | |||       y t        j                  | |||       y N)r   r   SET_NULLPROTECT)	collectorfieldsub_objsusings       K/home/dcms/DCMS/lib/python3.12/site-packages/djangocms_versioning/models.pyallow_deleting_versionsr'   &   s)    	5(E:y%59    c                   $    e Zd Zd Zd Zd Zd Zy)VersionQuerySetc                     t        |d      r|j                  S t        j                  |      }| j	                  |j
                  |j                        }||j                  j                  d<   ||_        |S )zHReturns Version object corresponding to provided content object
        _version_cache)	object_idcontent_type__incontent)	hasattrr,   r   for_contentgetpkcontent_types_statefields_cache)selfcontent_objectversionableversions       r&   get_for_contentzVersionQuerySet.get_for_content.   ss     >#34!000"..~>(($''+:S:S  
 2@##I.(/%r(   c                 j    t        j                  |      } | j                  |fi |j                  |iS )zRReturns a list of Version objects for the provided grouper
        object
        )r   for_grouperfilter_by_grouping_valuesgrouper_field_name)r7   grouper_objectr9   s      r&   filter_by_grouperz!VersionQuerySet.filter_by_grouper;   s?     #..~>-t--
'::NK
 	
r(   c                 `     |j                   di |}| j                  ||j                        S )zqReturns a list of Version objects for the provided grouping
        values (unique grouper version list)
        object_id__inr.    )for_grouping_valuesfilterr4   )r7   r9   kwargscontent_objectss       r&   r>   z)VersionQuerySet.filter_by_grouping_valuesD   s:     :+99CFC{{)K<U<U  
 	
r(   c                     t        j                  |      }|j                  |      }| j                  ||j                        S )zReturns a list of Version objects for grouping values taken
        from provided content object. In other words:
        it uses the content instance property values as filter parameters
        rC   )r   r1   for_content_grouping_valuesrG   r4   )r7   r/   r9   rI   s       r&   !filter_by_content_grouping_valuesz1VersionQuerySet.filter_by_content_grouping_valuesM   sE    
 #..w7%AA'J{{)K<U<U  
 	
r(   N)__name__
__module____qualname__r;   rA   r>   rL   rE   r(   r&   r*   r*   -   s    

	
r(   r*   c            	           e Zd Z ej                  d ed            Z ej                  ej                   ed            Z	 ej                  ej                  ej                   ed            Z ej                  dd	
      Z ej                  eej                  d      Z ej&                         Z edd      Z eej2                  ej4                   ed      d      Z ej                  ej                  ej8                  dd ed      d      Z ej                  ddde ed            Ze jC                         Z" G d d      Z#d Z$d Z%d Z&d Z'd: fd	Z( fdZ)d  Z*e+d!        Z,d" Z-e+d#        Z.e/j`                  d$        Z1 e2 e3e4       e5ej2                  g ed%             e6e7      g      Z8d& Z9d' Z: e;eej2                  ejx                  e8jz                  (      d)        Z> e2 e?e4       e5ej2                  g ed%            g      Z@d* ZAd+ ZB e;eej2                  ej                  e@jz                  (      d,        ZD e2 e?e4       e5ej                  g ed-             eEeF      g      ZGd. ZHd;d/ZI e;eej                  ej                  eGjz                  (      d0        ZKd1eLfd2ZMd1eLfd3ZNd4eOd1eLfd5ZP e2 e5ej2                  geQ       eEeF       eRe4      g      ZS e2 e3e4       e5ejx                  ej                  g ed6             eEeF      g      ZT e2 e5ej2                  geQ       e6e7      g      ZU e2 e5ej2                  ej                  g ed7             eEeF      g      ZV e2 e5ej2                  geQ       e6 ed8            g      ZW e2 e5ej2                  ej                  geQ       eX ed9            g      ZY xZZS )<VersionTCreated)auto_now_addverbose_nameModified)defaultrT   author)	on_deleterT      #)
max_lengthrT   cms_versions)rX   related_namecontent_typer-   status)rV   choicesrT   	protectedNz	locked bylocking_users)rX   nullrV   rT   r]   r7   source)rc   blankrX   rT   c                       e Zd ZdZdZy)Version.Meta)r^   r-   ))delete_versionlockzCan unlock verisionN)rM   rN   rO   unique_togetherpermissionsrE   r(   r&   Metarg      s    7
r(   rk   c                      d| j                    S )Nz	Version #r3   r7   s    r&   __str__zVersion.__str__   s    477)$$r(   c                     t        d      j                  | j                  t        t        j
                        | j                     t        | j                  t        j                              S )Nz"Version #{number} ({state} {date}))numberstatedate)_formatrq   dictr   VERSION_STATESrr   r	   createdr   DATETIME_FORMATrn   s    r&   rT   zVersion.verbose_name   sR    56==;;y//0<$,,(@(@A > 
 	
r(   c                     t        d      j                  | j                  t        t        j
                        | j                           S )NzVersion #{number} ({state}))rq   rr   )rt   ru   rq   rv   r   rw   rr   rn   s    r&   
short_namezVersion.short_name   s=    ./66;;d9+C+C&DTZZ&P 7 
 	
r(   c                 P    | j                   rt        d      d| j                   iz  S y)NzLocked by %(user)suser )	locked_byrt   rn   s    r&   locked_messagezVersion.locked_message   s&    >>)*fdnn-EEEr(   c                    d }| j                   }| j                  j                  j                  } |||j                  j                        }| d|j                  i} |j
                  j                  di |j                         }| j                  j                          t        
| !  ||      }	d|	d   d<   |dk(  r|j                          d|	d   d<   |	S )	z[Deleting a version deletes the grouper
        as well if we are deleting the last version.c                 v    | j                   j                  D ]   }t        |dd       |k(  s|j                  c S  y )Nrelated_model)_metafieldsgetattrname)ContentModelGrouperModelr#   s      r&   get_grouper_namez(Version.delete.<locals>.get_grouper_name   s8    %++22 &5/48LH ::%&r(   __pk)r%   keep_parentsFr   lastTrE   )
grouperr/   r   modelr3   _original_managerrG   countdeletesuper)r7   r%   r   r   r   r   grouper_name	querydictr   deleted	__class__s             r&   r   zVersion.delete   s    	&
 ,,||))//'gmm6I6IJ$~T*GJJ7	5..55B	BHHJ'.u<.H"
6A:NN!%GAJvr(   c                    | j                    }|r0t        t        j                  |       }| j	                         | _        | j                   A| j                  t        j                  k(  r$t        rB| j                  6| j                  | _	        n$| j                  t        j                  k7  rd | _	        t        | 0  d	i | | j                  t        j                  k(  r	|r| j                  j                  | j                        j!                  dd      }t"        j$                  j'                  | j                         j)                  t        j                  || j*                        }|D ]  }|j-                  | j                          | j                  j.                  }|r ||        t1        t        j                  |        t2        rt3        | j                  |       y y y )
Nr:   r3   Tflatrm   rr   rD   r^   r:   token)rx   rE   )r3   r   r   OPERATION_DRAFTmake_version_numberrq   rr   DRAFTr   r   
created_byr   saver9   rK   r/   values_listrQ   objectsexcluderG   r^   archiveon_draft_creater   r   )	r7   rH   rx   action_tokenpks_for_grouping_values
to_archiver:   r   r   s	           r&   r   zVersion.save   s   gg+5))4L 224DK77?tzzY__<!7!%ZZ9??*!DNv ::(*.*:*:*V*VLL++d+. ( %__444@GG#//"9!%!2!2 H 

  * 5GOODOO45"&"2"2"B"B"#D)+--t< ##DLL'B #' )r(   c                     t         j                  j                  | j                        j	                  d      j                         }|syt        |j                        dz   S )z:
        Create a version number for each version
        z-pkr   )rQ   r   rL   r/   order_byfirstintrq   )r7   latest_versions     r&   r   zVersion.make_version_number   sM     OO==dllKXe_UW 	 >(()A--r(   c                 @    t        j                  | j                        S )z[Helper property to get the versionable for the content type
        of the version
        )r   r1   r/   rn   s    r&   r9   zVersion.versionable   s    
 ''55r(   c                     | j                   j                  }| j                   `t        j                  |       }||j                   _        || j                   _        | j                  j
                  |_        |S )z_Returns a copy of current Version object, but as an instance
        of its correct proxy model)r5   r6   copydeepcopyr9   version_model_proxyr   )r7   cachenew_objs      r&   convert_to_proxyzVersion.convert_to_proxy   s\     ((KK$--%&+##(  ,,@@r(   c                 V    t        | j                  | j                  j                        S )z;Helper property to get the grouper for the version
        )r   r/   r9   r?   rn   s    r&   r   zVersion.grouper   s!     t||T%5%5%H%HIIr(   c                     t        j                  | j                        j                  } || j                        }t	        j
                  j                  d|| |dt        rd|ini }|S )a  Creates a new Version object, with a copy of the related
        content object.
        Allows customization of how the content object will be copied
        when specified in cms_config.py

        This method needs to be run in a transaction due to the fact that if
        models are partially created in the copy method a version is not attached.
        It needs to be that if anything goes wrong we should roll back the entire task.
        We shouldn't leave this to package developers to know to add this feature
        because not doing so leaves the db and versioning in a corrupt state where
        content models exist without a version.
        )r/   rd   r   r   rE   )r   r1   r/   copy_functionrQ   r   creater   )r7   r   r   new_contentnew_versions        r&   r   zVersion.copy  se     %00>LL#DLL1oo,, 

,9Z(r
 r(   zVersion is not in draft statec                 ,    t        | j                        S r   )r   _set_archivern   s    r&   can_be_archivedzVersion.can_be_archived%      4,,--r(   c                    t        t        j                  |       }| j                  |       t	        j
                         | _        | j                          t        j                  j                  | t        j                  t        j                  |       | j                  j                  }|r ||        t        t        j                  | |       t         rt!        | j"                         yy)zChange state to ARCHIVEDr   r:   	old_state	new_stater}   r   N)r   r   OPERATION_ARCHIVEr   r   nowmodifiedr   StateTrackingr   r   r   ARCHIVEDr9   
on_archiver   r   r/   )r7   r}   r   r   s       r&   r   zVersion.archive(  s     2''
 	$ 		$$oo((	 	% 	
 %%00
t#''\	
 - r(   )r#   rd   target
permissionc                      y)a	  State machine transition method for moving version
        from DRAFT to ARCHIVED state.

        Please refrain from modifying data in this method, as
        state change is not guaranteed to be saved (making it
        possible to be left with inconsistent data)NrE   r7   r}   s     r&   r   zVersion._set_archiveA       	r(   c                 ,    t        | j                        S r   )r   _set_publishrn   s    r&   can_be_publishedzVersion.can_be_publishedW  r   r(   c                 8   t        t        j                  |       }| j                  |       t	        j
                         | _        | j                          t        j                  j                  | t        j                  t        j                  |       | j                  j                  | j                        j!                  dd      }t"        j                  j%                  | j&                        j)                  t        j                  || j*                        }|D ]  }|j-                  ||         | j                  j.                  }|r ||        t1        t        j                  | |t3        |      	       t4        rt5        | j                         y
y
)zLChange state to PUBLISHED and unpublish currently
        published versionsr   r   r3   Tr   rm   r   )to_be_published)r:   r   unpublishedN)r   r   OPERATION_PUBLISHr   r   r   r   r   r   r   r   r   	PUBLISHEDr9   rK   r/   r   rQ   r   r3   rG   r^   	unpublish
on_publishr   listr   )r7   r}   r   r   to_unpublishr:   r   s          r&   publishzVersion.publishZ  sV    2''
 	$ 		$$oo))	 	% 	
 #'"2"2"N"NLL#

+d+
& 	  ..$''.:AA%%1** B 

 $ 	:GdD9	:%%00
t#''\*		
 - r(   c                      y)a
  State machine transition method for moving version
        from DRAFT to PUBLISHED state.

        Please refrain from modifying data in this method, as
        state change is not guaranteed to be saved (making it
        possible to be left with inconsistent data)NrE   r   s     r&   r   zVersion._set_publish  r   r(   z!Version is not in published statec                 ,    t        | j                        S r   )r   _set_unpublishrn   s    r&   can_be_unpublishedzVersion.can_be_unpublished  s    4..//r(   c                    t        t        j                  | |      }| j                  |       t	        j
                         | _        | j                          t        j                  j                  | t        j                  t        j                  |       | j                  j                  }|r ||        t        t        j                  | ||       t         rt!        | j"                         yy)zChange state to UNPUBLISHED)r:   r   r   )r:   r   r   N)r   r   OPERATION_UNPUBLISHr   r   r   r   r   r   r   r   r   UNPUBLISHEDr9   on_unpublishr   r   r/   )r7   r}   r   r   r   s        r&   r   zVersion.unpublish  s     2))4
 	D! 		$$))++	 	% 	
 ''44#))+		
 - r(   c                      y)a  State machine transition method for moving version
        from PUBLISHED to UNPUBLISHED state.

        Please refrain from modifying data in this method, as
        state change is not guaranteed to be saved (making it
        possible to be left with inconsistent data)NrE   r   s     r&   r   zVersion._set_unpublish  r   r(   returnc                 &    | j                  d|      S )z
        Check if the given user has permission to publish.

        Args:
            user (User): The user to check for permission.

        Returns:
            bool: True if the user has publish permission, False otherwise.
        r   _has_permissionr   s     r&   has_publish_permissionzVersion.has_publish_permission  s     ##It44r(   c                 &    | j                  d|      S )a  
        Check whether the given user has permission to change the object.

        Parameters:
            user (User): The user for which permission needs to be checked.

        Returns:
            bool: True if the user has permission to change the object, False otherwise.
        changer   r   s     r&   has_change_permissionzVersion.has_change_permission  s     ##Hd33r(   permc                    |dk(  r1t        | j                  d      r| j                  j                  |      S t        | j                  d      r| j                  j                  |      S t        | j                  d      r| j                  j	                  |      S |j                  | j                  j                   d| j                  j                         S )a   
        Check if the user has the specified permission for the content by
        checking the content's has_publish_permission, has_placeholder_change_permission,
        or has_change_permission methods.

        Falls back to Djangos change permission for the content object.
        r   r   r   !has_placeholder_change_permissionz.change_)	r0   r/   r   r   r   has_permr^   	app_labelr   )r7   r   r}   s      r&   r   zVersion._has_permission  s     97O!P<<66t<<4<<!89<<55d;;4<<!DE<<AA$GG}} 1 1 ; ;<HTEVEVE\E\D]^__r(   z/Version is not in archived or unpublished statez*Version is not in draft or published statezVersion is already lockedzDraft version is not locked)NFr   )[rM   rN   rO   r   DateTimeFieldrt   rx   r   r   r   
ForeignKeyr   AUTH_USER_MODELr!   r   	CharFieldrq   r   r^   PositiveIntegerFieldr-   r   r/   r   r   r   rw   rr   r    r   r'   rd   r*   
as_managerr   rk   ro   rT   r{   r   r   r   r   propertyr9   r   r   r   atomicr   r   r   permission_error_messager   r   lock_error_messagecheck_archiver   r   r   r   as_boolr   r   check_publishr   r   r   r   r   lock_draft_error_messagecheck_unpublishr   r   r   r   boolr   r   strr   not_draft_errorr   check_modifycheck_revertcheck_discardcheck_edit_redirect
check_lockr   check_unlock__classcell__)r   s   @r&   rQ   rQ   Y   s   "f""1Y<PG#v##HLLq}UH"""  FNN8J V#>F$6$$..#L
 ,++-I<G((x[	E "!!  //{^$I V)x[F ((*G
 
%



0*CX. 6 6
 J J
  , 45ioo&*I(JK,-	
M..2 !! ((	 56ioo&*I(JK	
M.'.R "" ((	 !12)%%&*M(NO45" O0.8 ""$$"**	
5d 
5
4T 
4`C `$ `( ioo&8 8945	
L 45##Y%:%:;CD   89	
	L ioo&8,-	
M %)"5"56>?   89	
 ioo&8!789	
J iooy':':;_MA;<=	
Lr(   rQ   c                   6   e Zd Z ej                  eej                        Z ej                  d      Z	 ej                  dej                        Z ej                  dej                        Z ej                  ej                   ej                        Zy)r   )rX   T)rS   d   )r[   r`   N)rM   rN   rO   r   r   rQ   CASCADEr:   r   rs   r   r   rw   r   r   r   r   r}   rE   r(   r&   r   r   !  s~    f6>>BG6T2D   C9Q9QRI   C9Q9QRI6X55PDr(   r   )4r   django.confr   "django.contrib.contenttypes.fieldsr   "django.contrib.contenttypes.modelsr   	django.dbr   r   django.utilsr   django.utils.formatsr	   django.utils.translationr
   rt   
django_fsmr   r   r   r~   r   r   
conditionsr   r   r   r   r   r   r   r   confr   r   
operationsr   r    djangocms_internalsearch.helpersr   ImportErrorr  r   r  r   r'   QuerySetr*   ModelrQ   r   rE   r(   r&   <module>r      s       @ : ) ! ) 6 8 8 %	 	 	 9 OD
 ,-NO ST PQ :)
foo )
XEfll EPQFLL QK  s   (C CC