
    Bha                        d Z ddlZddlmZ ddlmZ ddlmZ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 ddl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m Z  ddl!m"Z" ddl#m$Z$ ddl%m&Z& ddl'm(Z( ddl)m*Z* ddl+m,Z, ddl-m.Z. ddl/m0Z0 ddl1m2Z2m3Z3 ddl4m5Z5 ddl6m7Z7 ddl8m9Z9 d Z:d Z;ejx                  dddddddddddddddddejz                  d dej|                  fd!       Z?ejx                  dddddddddddeejz                  ej|                  fd"       Z@dddddddddddeejz                  ej|                  fd#ZAejx                  d-d$       ZB	 	 	 	 	 	 	 	 	 	 	 	 d.d&ZCedddddddd%dddfd'ZDd( ZEd/d)ZFd* ZGd0d+ZHd, ZIy)1aR  
Python APIs for creating CMS content. This is done in :mod:`cms.api` and not
on the models and managers, because the direct API via models and managers is
slightly counterintuitive for developers.

The api for both Pages and Plugins has changed significantly since django CMS
Version 4.

Also, the functions defined in this module do sanity checks on arguments.

.. warning:: None of the functions in this module does any security or permission
             checks. They verify their input values to be sane wherever
             possible, however permission checks should be implemented manually
             before calling any of these functions.

.. info:: Due to potential circular dependency issues, it's recommended
          to import the api in the functions that uses its function.

          e.g. use:

          ::

              def my_function():
                  from cms.api import api_function

                  api_function(...)

          instead of:

          ::

              from cms.api import api_function


              def my_function():
                  api_function(...)

    N)get_user_model)Site)
FieldErrorValidationError)IntegrityErrortransaction)slugify)get_template)	constants)CMSApp)apphook_pool)TEMPLATE_INHERITANCE_MAGIC)PageContent)Page)ACCESS_PAGE_AND_DESCENDANTSGlobalPagePermissionPagePermissionPageUser)Placeholder)	CMSPlugin)CMSPluginBase)plugin_pool)get_current_site)RemovedInDjangoCMS51Warning)get_cms_setting)get_language_list)get_available_slugget_clean_username)_thread_locals)copy_plugins_to_placeholder)	menu_poolc                 V   t        j                          t        | t              r]	 | j                  t         j
                  j                         D cg c]  }|j                   c}v sJ 	 | j                  j                  }n\t        | d      rt        | t              r| j                  S t        | t              r	 | t         j
                  v sJ 	 | }nt        d      t         j
                  |   j                  r|st        d      |S c c}w # t        $ r  w xY w# t        $ r  w xY w)zT
    Verifies the apphook given is valid and returns the normalized form (name)
    
__module__z)apphook must be string or CMSApp instancez-apphook with app_name must define a namespace)r   discover_apps
isinstancer   	__class__appsvaluesAssertionError__name__hasattr
issubclassstr	TypeErrorapp_namer   )apphook	namespaceappapphook_names       7/home/dcms/DCMS/lib/python3.12/site-packages/cms/api.py_verify_apphookr5   O   s     '6"	$$,BSBSBZBZB\(]3(]]]] ((11	,	'Jw,G	GS	!	l///// CDD&//	MNN! )^ 		  		s)   +D D
$D ;D 
D DD(c                 d   t        | d      rNt        | t              r>| j                  }| t        j
                  j                         v sJ | j                  } || fS t        | t              r$	 t	        j                  |       j                  }|| fS t        d      # t        $ r t        d      w xY w)zh
    Verifies the given plugin_type is valid and returns a tuple of
    (plugin_model, plugin_type)
    r#   z4plugin_type must be CMSPluginBase subclass or string)r+   r,   r   modelr   pluginsr(   r*   r%   r-   
get_pluginKeyErrorr.   )plugin_typeplugin_models     r4   _verify_plugin_typer=   i   s    
 {L)jm.T"((k1188::::!** $$ 
K	%	T&11+>DDL
 $$ NOO  	TRSS	Ts   ,B B/z
python-apiF
last-childc                 (   |||t        j                  dt        d       |t        k(  s+|t	        d      D cg c]  }|d   	 c}v sJ t        |       |st               }nt        |t              sJ |t        |      v s)J t	        d      j                  |j                               |
rt        |
t              sJ |r.t        j                  dd	      }|D cg c]  }|d   	 }}||v sJ t        j                   t        j"                  t        j$                  f}||v sJ |d
v sJ |rt'        ||      }nd}|	r+t        |	t)                     r|	t*        _        t/        |	      }	ndt*        _        |r=t        j0                  j3                  ||      j5                         rt7        d|z        t        |
|	|	||||||	      }|j9                  |       |j;                          t=        || |||	|||||||||       t*        `|S c c}w c c}w )a	  
    Creates a :class:`cms.models.Page` instance and returns it. Also
    creates a :class:`cms.models.PageContent` instance for the specified
    language.

    .. warning::
        Since version 4 the parameters published, publication_date, and publication_end_date
        do not change the behaviour of this function. If they are supplied a warning is raised.

    :param str title: Title of the page
    :param str template: Template to use for this page. Must be in :setting:`CMS_TEMPLATES`
    :param str language: Language code for this page. Must be in :setting:`django:LANGUAGES`
    :param str menu_title: Menu title for this page
    :param str slug: Slug for the page, by default uses a slugified version of *title*
    :param apphook: Application to hook on this page, must be a valid apphook
    :type apphook: str or :class:`cms.app_base.CMSApp` sub-class
    :param str apphook_namespace: Name of the apphook namespace
    :param str redirect: URL redirect
    :param str meta_description: Description of this page for SEO
    :param created_by: User that is creating this page
    :type created_by: str of :class:`django.contrib.auth.models.User` instance
    :param parent: Parent page of this page
    :type parent: :class:`cms.models.Page` instance
    :param bool in_navigation: Whether this page should be in the navigation or not
    :param bool soft_root: Whether this page is a soft root or not
    :param str reverse_id: Reverse ID of this page (for template tags)
    :param str navigation_extenders: Menu to attach to this page. Must be a valid menu
    :param site: Site to put this page on
    :type site: :class:`django.contrib.sites.models.Site` instance
    :param bool login_required: Whether users must be logged in or not to view this page
    :param limit_visibility_in_menu: Limits visibility of this page in the menu
    :type limit_visibility_in_menu: :data:`VISIBILITY_ALL` or :data:`VISIBILITY_USERS` or :data:`VISIBILITY_ANONYMOUS`
    :param str position: Where to insert this node if *parent* is given, must be ``'first-child'`` or ``'last-child'``
    :param str   overwrite_url: Overwritten path for this page
    :param int xframe_options: X Frame Option value for Clickjacking protection
    :param str page_title: Overridden page title for HTML title tag
    NziThis API function no longer accepts a "published", "publication_date", or "publication_end_date" argument   
stacklevel	TEMPLATESr   	LANGUAGEScms_enabledT)r>   first-childleftright)
reverse_idsitez.A page with the reverse_id="%s" already exist.)	parent
created_by
changed_byrI   navigation_extendersapplication_urlsapplication_namespacelogin_requiredrJ   )position)languagetitle
menu_titleslugrL   redirectmeta_descriptionpageoverwrite_url	soft_rootin_navigationtemplatelimit_visibility_in_menuxframe_options)warningswarnUserWarningr   r   r
   r   r%   r   r   getpkr   r!   get_menus_by_attributer   VISIBILITY_ALLVISIBILITY_USERSVISIBILITY_ANONYMOUSr5   r   r   userr   objectsfilterexistsr   add_to_treesavecreate_page_content)rT   r]   rS   rU   rV   r0   apphook_namespacerW   rX   rL   rK   publication_datepublication_end_dater\   r[   rI   rN   	publishedrJ   rQ   r^   rR   rZ   r_   tpl	raw_menusmenumenusaccepted_limitationsrO   rY   s                                  r4   create_pagery      sH   @  0 <@T@`.		
 11ok.JKsCFKKKKX !$%%% (..Y0L0P0PQUQXQX0YY. &$'''44]DI	%./Ta//#u,,, &44i6P6PR[RpRpq#';;;; EEEE *74EF j^-=>('
3
"<<*4@GGIMPZZ[[1)/%
D 	h'IIK)##!9%" 	K[ L$ 0s   H
Hc                    |t         k(  s+|t        d      D cg c]  }|d   	 c}v sJ t        |       t        |t              sJ | t        |j                        v sJ t        j                  t        j                  t        j                  f}||v sJ |s2|j                  t        |      |       }t        |j                  ||       }|r|j                  d      }
n|
|j                  ||       }
|r*t        |t!                     r|t"        _        t'        |      }	 ddlm}  ||j                  |
| |j,                         |j2                  j5                  || t7        ||
t9        |                    t;        t"        d	d
      }t<        j>                  jA                  |      jC                  | |||	||||||||||      }|jE                          |jG                          |S c c}w # t.        $ r}t1        |      d}~ww xY w)aG  
    Creates a :class:`cms.models.PageContent` instance and returns it.

    ``parent`` is only used if slug=None.

    :param str language: Language code for this page. Must be in :setting:`django:LANGUAGES`
    :param str title: Title of the page
    :param page: The page for which to create this title
    :type page: :class:`cms.models.Page` instance
    :param str menu_title: Menu title for this page
    :param str slug: Slug for the page, by default uses a slugified version of *title*
    :param str redirect: URL redirect
    :param str meta_description: Description of this page for SEO
    :param parent: Used for automated slug generation
    :type parent: :class:`cms.models.Page` instance
    :param str overwrite_url: Overwritten path for this page
    :param str page_title: Overridden page title for HTML title tag

    rC   r   /N)validate_url_uniqueness)exclude_page)rV   pathmanaged)rY   rS   defaultsri   zunknown user)rS   rT   rU   
page_titlerW   rX   rY   rL   rM   r[   r\   r]   r^   r_   )$r   r   r
   r%   r   r   site_idr   rf   rg   rh   get_path_for_slugr	   r   rJ   stripr   r   ri   r   cms.forms.validatorsr|   rK   r   r   urlsupdate_or_createdictboolgetattrr   rj   	with_usercreaterescan_placeholders_clear_internal_cache)rS   rT   rY   rU   rV   rW   rX   rK   rZ   r   r~   rL   r[   r\   r]   r^   r_   rt   rx   baser|   eri   page_contents                           r4   ro   ro     s   P 11ok.JKsCFKKKKX dD!!! (6666 &44i6P6PR[RpRpq#';;;; %%genh?!$))T8<""3'	%%dH5j^-=>('
3
 @		4T 	II]++
   >6>:D&&006==)#!9% > L  $$& C L>   Q s   G'&G, ,	H5H  Hc                 p    t        j                  dt        d       t        | ||f|||||||	|
||||||dS )zx
    .. warning ::
        ``create_title`` has been renamed to ``create_page_content`` as of django CMS version 4.
    zGcms.api.create_title has been renamed to cms.api.create_page_content().r@   rA   )rU   rV   rW   rX   rK   rZ   r   r~   rL   r[   r\   r]   r^   r_   )r`   ra   r   ro   )rS   rT   rY   rU   rV   rW   rX   rK   rZ   r   r~   rL   r[   r\   r]   r^   r_   s                    r4   create_titler     sb    . MMQ#
  )##!9%#     c                 x   t        | t              sJ t        |      \  }}|r|dk(  r!| j                  ||d      }|j                  }n|dk(  r!| j                  ||d      }|j                  }n|dk(  r|j
                  }|j                  }nc|dk(  r-|j
                  dz   |j                         z   }|j                  }n1t        d	|z        |d
v sJ |dk(  r| j                  |d      }nd}d}t        || |||      }	| j                  |	      }	 |di |}
|	j                  |
       |
j                          |
S )a  
    Adds a plugin to a placeholder and returns it.

    :param placeholder: Placeholder to add the plugin to
    :type placeholder: :class:`cms.models.placeholdermodel.Placeholder` instance
    :param plugin_type: What type of plugin to add
    :type plugin_type: str or :class:`cms.plugin_base.CMSPluginBase` sub-class, must be a valid plugin
    :param str language: Language code for this plugin, must be in :setting:`django:LANGUAGES`
    :param str position: Position to add this plugin to the placeholder. Allowed positions are ``"last-child"``
                         (default), ``"first-child"``, ``"left"``, ``"right"``.
    :param target: Parent plugin. Must be plugin instance
    :param data: Data for the plugin type instance
    r>   last)rK   insert_orderrF   firstrG   rH      zposition not supported: %s)rF   r>   )r   N)r;   placeholderrR   rS   	parent_id )r%   r   r=   get_next_plugin_positionrd   rR   r   _get_descendants_count	Exceptionr   
add_pluginset_base_attrrn   )r   r;   rS   rR   targetdatar<   new_posr   plugin_baseplugins              r4   r   r     sa     k;/// !4K @L+|#!::8Fag:hG		I&!::8Fah:iG		IooG((I oo)F,I,I,KKG((I88CDD8888|#!::8RX:YGG	K ((5K!D!Ff%
KKMMr   Tc                    ddl m} |rt        | |ddddddddddd      S t        | t	                     sJ ||||||||	|
||d}d|_        d|_        t        |       }t	               j                  j                  D cg c]  }|j                   c}D ]  }t        ||t        ||              |j                          |j                           |||       |S c c}w )a  
    Creates a page user for the user provided and returns that page user.

    :param created_by: The user that creates the page user
    :type created_by: :class:`django.contrib.auth.models.User` instance
    :param user: The user to create the page user from
    :type user: :class:`django.contrib.auth.models.User` instance
    :param bool can_*: Permissions to give the user
    :param bool grant_all: Grant all permissions to the user
    r   )save_permissionsT)can_add_pagecan_view_pagecan_change_pagecan_delete_pagecan_publish_pagecan_add_pageusercan_change_pageusercan_delete_pageusercan_add_pagepermissioncan_change_pagepermissioncan_delete_pagepermission)rL   )cms.admin.formsr   create_page_userr%   r   is_staff	is_activer   _metalocal_fieldsnamesetattrr   rn   )rL   ri   r   r   r   r   r   r   r   r   r   r   r   	grant_allr   r   	page_userffields                      r4   r   r     s    4 1
D$dD$PTVZ\`bfhlnrss j."2333 %&**,,22"8%>%>D DMDNJ/I"0"2"8"8"E"EFQ!&&F 8	5'$"678IIKNNT9%K Gs   >Cc           	      .   |xr | }|xs ||xs ||xs ||xs ||xs ||xs ||	xs ||xs |d}t        d| ||d|}|j                          |rAt        d||
d|}|j                          |j                  j	                  t                      |S )a  
    Assigns a user to a page and gives them some permissions. Returns the
    :class:`cms.models.PagePermission` object that gets
    created.

    :param page: The page to assign the user to
    :type page: :class:`cms.models.Page` instance
    :param user: The user to assign to the page
    :type user: :class:`django.contrib.auth.models.User` instance
    :param grant_on: Controls which pages are affected
    :type grant_on: :data:`cms.models.ACCESS_PAGE`, :data:`cms.models.ACCESS_CHILDREN`,
    :data:`cms.models.ACCESS_DESCENDANTS` or :data:`cms.models.ACCESS_PAGE_AND_DESCENDANTS`
    :param can_*: Permissions to grant
    :param bool grant_all: Grant all permissions to the user
    )can_add
can_change
can_deletecan_publishcan_change_advanced_settingscan_change_permissionscan_move_pagecan_view)rY   ri   grant_on)ri   can_recover_pager   )r   rn   r   sitesaddr   )rY   ri   r   r   r   r   r   r   r   r   r   r   r   global_permissionr   page_permissions                   r4   assign_user_to_pager   .  s    @ 3"33I'i -I -I"/i(D(Q	"8"EI&3))		D %U$THUPTUO.dDK[d_cd!!"2"45r   c                 <    t        j                  dt        d       yz
    .. warning::

        Publishing pages has been removed from django CMS core in version 4 onward.

        For publishing functionality see `djangocms-versioning: <https://github.com/django-cms/djangocms-versioning>`_
    This API function has been removed. For publishing functionality use a package that adds publishing, such as: djangocms-versioning.r@   rA   Nr`   ra   rb   )rY   ri   rS   s      r4   publish_pager   c       MM	5	r   c                 <    t        j                  dt        d       yr   r   )include_unpublishedrS   rJ   s      r4   publish_pagesr   s  r   r   c                 <    t        j                  dt        d       y)z
    .. warning::

       The concept of draft pages has been removed from django CMS core in version 4 onward.

       For draft functionality see `djangocms-versioning: <https://github.com/django-cms/djangocms-versioning>`_
    r   r@   rA   Nr   )rY   s    r4   get_page_draftr     r   r   c                     d}| j                  |      }|D ]\  }|r!|j                  |      j                         r&t        |j                  |            }t	        |||      }|t        |      z  }^ |S )a  
    Copy the plugins to another language in the same page for all the page
    placeholders.

    By default, plugins are copied only if placeholder has no plugin for the
    target language; use ``only_empty=False`` to change this.

    .. warning: This function skips permissions checks

    :param page: the page to copy
    :type page: :class:`cms.models.pagemodel.Page` instance
    :param string source_language: The source language code,
     must be in :setting:`django:LANGUAGES`
    :param string target_language: The source language code,
     must be in :setting:`django:LANGUAGES`
    :param bool only_empty: if False, plugin are copied even if
     plugins exists in the target language (on a placeholder basis).
    :return int: number of copied plugins
    r   )rS   )get_placeholdersget_pluginsrl   listr    len)	rY   source_languagetarget_language
only_emptycopiedplaceholdersr   r8   copied_pluginss	            r4   copy_plugins_to_languager     s    ( F((9L# * !8!8/!8!R!Y!Y![;22O2LMG8+XghNc.))F* Mr   c                     ddl m} | j                  }| j                  }|r|j	                  ||      S t
        j                  j                  |       }|j                  ||      S )a2  
    Check whether a user has the permission to change the page.

    This will work across all permission-related setting, with a unified interface
    to permission checking.

    :param request: The request object from which the user will be taken.
    :type request: :class:`HttpRequest` instance

    r   )page_permissions)		cms.utilsr   ri   current_pageuser_can_change_pager   rj   get_currentuser_can_change_all_pages)requestr   ri   r   rJ   s        r4   r   r     sX     +<<D''L44T<HH<<##G,D55dDAAr   )r>   N)TTTTTTTTTTTF)FNN)T)J__doc__r`   django.contrib.authr   django.contrib.sites.modelsr   django.core.exceptionsr   r   	django.dbr   r   django.template.defaultfiltersr	   django.template.loaderr
   cmsr   cms.app_baser   cms.apphook_poolr   cms.constantsr   
cms.modelsr   cms.models.pagemodelr   cms.models.permissionmodelsr   r   r   r   cms.models.placeholdermodelr   cms.models.pluginmodelr   cms.plugin_baser   cms.plugin_poolr   r   r   cms.utils.compat.warningsr   cms.utils.confr   cms.utils.i18nr   cms.utils.pager   r   cms.utils.permissionsr   cms.utils.pluginsr    menus.menu_poolr!   r5   r=   atomicrf   X_FRAME_OPTIONS_INHERITry   ro   r   r   r   r   r   r   r   r   r   r   r   r4   <module>r
     s  %N  . , > 1 2 /   ) 4 " %  4 , ) ' & A * , A 0 9 %4%0 
 		&55441V Vr 
 		'&5544#i i` 		'&5544#.b 6 6x ""8| )!& 2j   @Br   