
    Bh]                        d dl 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 d dl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mZmZmZ d dlmZ d dlm Z m!Z!m"Z" d dl#m$Z$ ejJ                  ejL                  fZ'ejJ                  ejP                  fZ)d Z*ddZ+dee   dee   fdZ, G d de"      Z- G d de       Z. e$j^                  e.        G d de!      Z0 e$jb                  e0        G d de!      Z2 e$jb                  e2       y)    N)defaultdict)	GeneratorIterable)Optional)SimpleLazyObject)	constants)apphook_pool)PagePageContentPagePermissionPageUrl)get_object_preview_urlget_toolbar_from_request)get_cms_setting)get_fallback_languagesget_public_languageshide_untranslatedis_valid_site_language)user_can_view_all_pages)MenuModifierNavigationNode)	menu_poolc                     ddl }ddlm} |j                  d|d       t	        | |D cg c]  }|j                          c}|      }t        |D ch c]  }|j                   c}      S c c}w c c}w )zCThis function is deprecated. Use get_visible_page_contents instead.r   NRemovedInDjangoCMS51WarningzFget_visible_nodes is deprecated, use get_visible_page_contents instead   
stacklevel)warningscms.utils.compat.warningsr   warnget_visible_page_contentsget_content_objlistpage)requestpagessiter    r   r&   page_contentspage_contents           =/home/dcms/DCMS/lib/python3.12/site-packages/cms/cms_menus.pyget_visible_nodesr-      sp     EMMP#  
 .g[`7aSW8L8L8N7acghM}E|""EFF 8bEs   A+
A0c                     ddl }ddlm} |j                  d|d       t	        |       }|r|g|z   n|g|_        |rt        t        d            nd}|j                  |j                  |      |      S )	zPThis function is deprecated. Use CMSMenu.get_menu_node_for_page_content instead.r   Nr   zaget_menu_node_for_page is deprecated, use CMSMenu's get_menu_node_for_page_content method insteadr   r   id)preview_url)
r    r!   r   r"   CMSMenu	languagesr   r   get_menu_node_for_page_contentr$   )	rendererr&   language	fallbacksendpointr    r   menur1   s	            r,   get_menu_node_for_pager:   ,   sx    EMMk#  
 8D/8hZ)+xjDN?G():;TK..t/C/CH/M[f.gg    r*   returnc                    	
 t        d      }|dk(  xs |dk(  xr  j                  j                   j                  j                  ssg S t	         j                  |      r|S t        d      sr|S g S t
        j                  j                  |D ch c]  }|j                  j                   c}d      		D ci c]  }|j                  | c} j                  j                  t         fd       j                  j                  dt        d	t        f	fd

t        
fd|D              S c c}w c c}w )z
    This code is a many-pages-at-once version of cms.utils.page_permissions.user_can_view_page.
    `pages` contains all published pages.
    
PUBLIC_FORallstaff
PERMISSIONT)page_id__incan_viewc                  d    t         j                  j                  j                  dd            S )NpkT)flat)	frozensetusergroupsvalues_list)r'   s   r,   <lambda>z+get_visible_page_contents.<locals>.<lambda>[   s(    9W\\5H5H5T5TUY`d5T5e+f r;   r&   r<   c                 L   | j                   v r7t        j                  j                  j	                  | j                      |        d}D ]Q  }|j                         j                  | j                        s-s y|j                  k(  s|j                  v r yd}S xr | S )NFT)
rE   r   r&   fieldset_cached_valueget_page_permission_tuplecontainspathuser_idgroup_id)	r&   
restrictedpermcan_see_unrestrictedis_auth_userrestriction_maprestrictionsuser_groupsrR   s	      r,   user_can_see_pagez4get_visible_page_contents.<locals>.user_can_see_page^   s    77o%%%66tww7OQUV
  	"D--/88C# <<7*dmm{.J!
	" $6J6r;   c              3   H   K   | ]  } |j                         s|  y wN)r&   ).0r+   r[   s     r,   	<genexpr>z,get_visible_page_contents.<locals>.<genexpr>p   s      gBST`TeTeBfgs   "")r   rH   is_staffis_authenticatedr   r   objectsfilterr&   rE   page_idr   r
   boolr%   )r'   r*   r)   
public_forr+   rU   rV   rW   rX   rY   r[   rZ   rR   s   `     @@@@@@@r,   r#   r#   >   s'   
 !.J%.c:3H3bW\\MbMb<<((1E 	w||T2<( !5}<"<!))00>KLl\&&))L 1 L 7CCdt||T)COllooG"#fgK<<00L7 7 7 7$ gggg7 M Ds   D>Ec                   F     e Zd ZdZddddedee   f fdZdefdZ xZ	S )	CMSNavigationNodez
    Represents a CMS Navigation Node for a Page object in the page tree.

    Attributes:
        path: The path of the node.
        language: The language used for the node (optional).
    N)rQ   r6   rQ   r6   c                    || _         |ddl}ddlm} |j	                  d|d       || _        t        |   |i | y)a  
        Initializes a CMSNavigationNode instance.

        :param *args: Positional arguments.
        :param path: The path of the node.
        :param language: The language used for the node. Optional.
        :param **kwargs: Keyword arguments.
        Nr   r   z^The 'path' attribute of CMSNavigationNode is deprecated and will be removed in Django CMS 4.3.r   r   )rQ   r    r!   r   r"   r6   super__init__)selfrQ   r6   argskwargsr    r   	__class__s          r,   rk   zCMSNavigationNode.__init__|   sL     	MMMp+  
 !$)&)r;   r<   c                 h    	 |j                   j                  | j                  k(  S # t        $ r Y yw xY wNF)current_pagerE   r0   AttributeError)rl   r'   s     r,   is_selectedzCMSNavigationNode.is_selected   s4    	''**dgg55 		s   "% 	11)
__name__
__module____qualname____doc__strr   rk   re   rt   __classcell__ro   s   @r,   rh   rh   s   s2     +/$ *C *(3- *.d r;   rh   c            	       z     e Zd ZdZ fdZdee   deeddf   fdZ	 	 ddede	e
   d	edefd
Zdee   fdZ xZS )r2   zSubclass of :class:`menus.base.Menu`. Its :meth:`~menus.base.Menu.get_nodes()` creates a list of NavigationNodes
    based on a site's :class:`cms.models.pagemodel.Page` objects.
    c                 :   t         |   |       |j                  }|j                  j                  }t        ||      rd}t        ||      }nd}d}|r2|rg }nt        ||      }|g|D cg c]
  }||k7  s	| c}z   | _        yt        |      | _        yc c}w )z`
        Initializes a CMSMenu instance.

        :param renderer: The renderer object.
        )site_idTFN)
rj   rk   request_languager)   rE   r   r   r   r3   r   )	rl   r5   langsite_pk_valid_language_hide_untranslatedr7   _langro   s	           r,   rk   zCMSMenu.__init__   s     	"((--""!$8"O!24!A#O!& "	24I	"V)&UuPT}u&UUDN 2':DN	 'Vs   -
B8Br*   r<   Nc              #     K   t        | j                        }d}d}|D ]  }|rG||j                  k7  r8| | j                  j                  |j                        }|}|j                  }L| j                  j                  |j                        |k  su| j                  j                  |j                        }|}|j                  } |r| yyw)zGenerator that returns only those page content objects passed that contain the first language
        present in the languages list.N)lenr3   r&   indexr6   )rl   r*   
lang_indextranslationr&   r+   s         r,   select_langzCMSMenu.select_lang   s      (
) 		)Lt|'8'88!!!^^11,2G2GH
*#((%%l&;&;<zI!^^11,2G2GH
*#((		)  s   BC=Cr+   r1   cutc                    |j                   }|j                  }d|j                  |j                  |j                  |j
                  |t        v |t        v d}g }|j                  r|j                  | j                  j                  v r|j                  |j                         n[|j                   d|j                   | j                  j                  v r*|j                  |j                   d|j                          |j                  rk|j                  | j                  d   k(  rOt!        j"                  |j                        }|r.|j%                  |j'                  || j                  d                |D 	cg c]6  }	t)        |	d      r|	j*                   d|j                   nt-        |	d|	      8 c}	|d<   |r&t/        j0                  dd	|j                   d	|      }
n|j3                  |j                  
      }
t5        |j6                  xs |j8                  |
|j                  |rdn|j                   j:                  ||j<                  |j                  | j                  d   k7  r|j                        S d      S c c}	w )a  
        Transform a CMS page content object into a navigation node.

        :param page: The page to transform.
        :param languages: The list of the current language plus fallbacks used to render the menu.
        :param preview_url: If given, serves as a "pattern" for a preview url with the assumption that "/0/" is replaced
            by the actual page content pk. Default is None.
        :param cut: If True the parent_id is set to None. Default is False.
        :returns: A CMSNavigationNode instance.
        T)is_page	soft_rootauth_required
reverse_idis_homevisible_for_authenticatedvisible_for_anonymous:r   get_instancesru   navigation_extendersz(/0/)/r6   N)titleurlr0   	parent_idattrvisibler6   )r&   limit_visibility_in_menur   login_requiredr   r   VISIBLE_FOR_AUTHENTICATEDVISIBLE_FOR_ANONYMOUSr   r5   menusappendrE   application_urlsr6   r3   r	   get_apphookextend	get_menushasattrru   getattrresubget_absolute_urlrh   
menu_titler   r   in_navigation)rl   r+   r1   r   r&   
visibilityr   	extendersappextr   s              r,   r4   z&CMSMenu.get_menu_node_for_page_content   sI        "::
%//!00//||)37P)P%/3H%H
 	$$((DMM,?,??  !:!:;--.ay9T]]=P=PP  D$=$=#>ay!IJ
   \%:%:dnnQ>O%O**4+@+@AC  tT^^A5F!GH
 !(
 ,33+Hs||nAdggY'gVY[egjNkk(
#$  &&Aloo%6a"8+FC''1F1F'GC ))?\-?-?ww!d|'8'8'B'B ../;/D/DWXHY/Yl++
 	
 `d
 	
(
s   9;Jc                 J   | j                   j                  }t        |      }|j                  s|j                  rt
        j                  j                         }nt
        j                  }|j                  | j                        j                  d      j                  |      j                  d      j                  ddddd	d
dddddddd      }|j                  s|j                  r&t        t        d            }dt
        dt
        fd}nud}t        j                  j                  d |D        d |D              }t!        t"              |D ]  }	|	|	j$                     |	j&                  <     dt
        dt
        ffd}t)        |||      }t+        d |D        d      }
|
xr |
j,                   }|
r|
j.                  j0                  nd}| j3                  |      D cg c]7  }| j5                   ||      ||j.                  j6                  |k(  xr |      9 c}S c c}w )a  
        Returns a list of NavigationNode objects representing the navigation nodes to be displayed in the menu.
        This method is performance-critical since the number of page content objects can be
        large.

        :param self: The instance of the class.
        :param request: The HTTP request object.
        :return: A list of NavigationNode objects representing the navigation nodes.
        :rtype: list[NavigationNode]

        ..   note::

            * The method retrieves the necessary data from the database to build the navigation nodes for the menu.
            * The behavior of the method depends on whether the edit mode or preview mode is active in the toolbar.
            * If either edit mode or preview mode is active, the method retrieves all current page content objects
              visible in the admin for the current page.
            * If neither edit mode nor preview mode is active, the method retrieves only public page content objects.
            * The retrieved page contents are filtered based on the specified languages, sorted by page path,
              and filtered by site.
            * Only specific fields of the page content objects are selected to optimize performance.
            * If either edit mode or preview mode is active, a preview URL is constructed for a "virtual" non-existing
              page content with id=0 to avoid too many calls to ``revert`` the admin URL.
            * The method includes a nested function for prefetching URLs and filling the URL cache.
            * The visibility of the page contents is further filtered based on authentication and permissions.
            * The homepage is determined based on the page contents and marked for cutting if necessary.
            * The menu node for each page content is created using the get_menu_node_for_page_content method of the
              instance.
            * The prefetch_urls function is called for each page content to fill the URL cache and provide necessary
              data for creating the menu node.
            * The select_lang method is used to filter the page contents based on the specified language preferences.
        )language__in
page__path)
page__siter&   rd   r6   r   r   r   r   r   page__site_idpage__parent_idpage__is_homepage__login_requiredpage__reverse_idpage__navigation_extenderspage__application_urlsr   r/   r+   r<   c                     | S r]    )r+   s    r,   prefetch_urlsz(CMSMenu.get_nodes.<locals>.prefetch_urls^  s    ##r;   Nc              3   4   K   | ]  }|j                     y wr]   r   r^   r+   s     r,   r_   z$CMSMenu.get_nodes.<locals>.<genexpr>c  s     Vl33Vs   c              3   H   K   | ]  }|j                   j                    y wr]   )r&   rE   r   s     r,   r_   z$CMSMenu.get_nodes.<locals>.<genexpr>d  s     Tl\..11Ts    ")r   rB   c                 \    j                  | j                        | j                  _        | S r]   )getrd   r&   
urls_cache)r+   filtered_urlss    r,   r   z(CMSMenu.get_nodes.<locals>.prefetch_urlsk  s*     0=/@/@AUAU/V!!,##r;   c              3   N   K   | ]  }|j                   j                  s|  y wr]   )r&   r   r   s     r,   r_   z$CMSMenu.get_nodes.<locals>.<genexpr>s  s     al|GXGXG`G`\as   %%)r1   r   )r5   r)   r   edit_mode_activepreview_mode_activer   admin_managercurrent_contentrb   rc   r3   order_byselect_relatedonlyr   r   r   dictrd   r6   r#   nextr   r&   rE   r   r4   r   )rl   r'   r)   toolbartranslations_qsr*   r1   r   prefetched_urlspage_urlhomecut_homepagehomepage_pkr+   r   s                 @r,   	get_nodeszCMSMenu.get_nodes  s   @ }}!!*73##w'B'B)77GGIO *11O """?Xl#VtV$^F#T*!&",( 	, ##w'B'B 11BCK$K $K $ K%oo44VVTmT 5 O
 (-M+ NEMh../0A0ABN$K $K $ 2'=$Oamacgh 6D$6$6 6&*diill !% 0 0 ?
  //l+' %%//;>O< 0 
 	
 
s   !<H rq   )ru   rv   rw   rx   rk   r   r   r   r   r   ry   re   rh   r4   r%   r   r   rz   r{   s   @r,   r2   r2      s    ;<+)> 9[Z^`dMdCe . &*	F
!F
 c]F
 	F

 
F
Pg
D$8 g
r;   r2   c                       e Zd Zd Zy)NavExtenderc                    |r|S t        d |D        d       }g }|D ]  }	|	j                  j                  dd       }
|
s"|
D ]  }||vr|j                  |       |D ]  }|j                  |k(  s|j
                  r |	|k(  r|	j                  sd |_        d |_        @|	j                  |_        |	j                  |_        |	|_        |	j                  j                  |          g }| j                  j                  j                         D ]U  }t        |d   d      s|d   j                  s#|d   |vs+|D ]&  }	|	j                  |d   k(  s|j                  |	       ( W |rC|rA|r?|j                  s3d|_        |j                   |j#                         k(  rd|_        nd|_        |D ]  }	|j'                  |	        |S )Nc              3   Z   K   | ]#  }|j                   j                  d d      s | % yw)r   FN)r   r   )r^   ns     r,   r_   z%NavExtender.modify.<locals>.<genexpr>  s!     F1Iu)EQFs   !++r      cms_enabledr   TF)r   r   r   r   	namespacer   r   parent_namespaceparentr0   childrenr5   r   itemsr   r   	path_infor   selectedremove)rl   r'   nodesr   root_idpost_cut
breadcrumbr   extsnoder   r   extnoderemovedr9   s                  r,   modifyzNavExtender.modify  s   L FFM 	>D		&<dCI$ >C$C(#( >",,3G<M<M#t|DLL;? 81548GG 1;?>> 815 $ 4 4W =>	>	>&  MM''--/ 	-DtAw.473F3F4PQ7Z^K^! -D~~a0t,-	-
 d4<<#$$(=(=(??$(DM$)DM 	DLL	r;   N)ru   rv   rw   r   r   r;   r,   r   r     s    .r;   r   c                   (    e Zd ZdZd Zd Zd Zd Zy)SoftRootCutteru  
    A soft root is a page that acts as the root for a menu navigation tree.

    Typically, this will be a page that is the root of a significant new
    section on your site.

    When the soft root feature is enabled, the navigation menu for any page
    will start at the nearest soft root, rather than at the real root of
    the site’s page hierarchy.

    This feature is useful when your site has deep page hierarchies (and
    therefore multiple levels in its navigation trees). In such a case, you
    usually don’t want to present site visitors with deep menus of nested
    items.

    For example, you’re on the page -Introduction to Bleeding-?, so the menu
    might look like this:

        * School of Medicine
            * Medical Education
            * Departments
                * Department of Lorem Ipsum
                * Department of Donec Imperdiet
                * Department of Cras Eros
                * Department of Mediaeval Surgery
                    * Theory
                    * Cures
                    * Bleeding
                        * Introduction to Bleeding <this is the current page>
                        * Bleeding - the scientific evidence
                        * Cleaning up the mess
                        * Cupping
                        * Leaches
                        * Maggots
                    * Techniques
                    * Instruments
                * Department of Curabitur a Purus
                * Department of Sed Accumsan
                * Department of Etiam
            * Research
            * Administration
            * Contact us
            * Impressum

    which is frankly overwhelming.

    By making "Department of Mediaeval Surgery" a soft root, the menu
    becomes much more manageable:

        * Department of Mediaeval Surgery
            * Theory
            * Cures
                * Bleeding
                    * Introduction to Bleeding <current page>
                    * Bleeding - the scientific evidence
                    * Cleaning up the mess
                * Cupping
                * Leaches
                * Maggots
            * Techniques
            * Instruments
    c                    |s|r|S d }g }|D ].  }	|	j                   r|	}|	j                  r|j                  |	       0 |rM|j                  j	                  dd      r|j                         }d |_        |g|z   }|S | j                  ||      }|S Nr   F)r   r   r   r   r   get_descendants"find_ancestors_and_remove_children)
rl   r'   r   r   r   r   r   r   
root_nodesr   s
             r,   r   zSoftRootCutter.modify  s     wL
 	(D}};;!!$'		( }}  e4 002"&!
U*  ??%Pr;   c                     |j                   D ]1  }|j                  j                  dd      s | j                  ||       3 |S r   )r   r   r   remove_childrenrl   r   r   childs       r,   find_and_remove_childrenz'SoftRootCutter.find_and_remove_children  s>    ]] 	3Ezz~~k51$$UE2	3 r;   c                 z    |j                   D ]%  }|j                  |       | j                  ||       ' g |_         y r]   )r   r   r   r   s       r,   r   zSoftRootCutter.remove_children  s:    ]] 	/ELL  .	/ r;   c                    |j                   r|j                   j                  j                  dd      r<|j                   j                         }d|j                   _         |j                   g|z   }nI| j	                  |j                   |      }n,|D ]'  }||k7  s	|j                   r| j                  ||       ) |j                  D ]  }||k7  s	| j                  ||        |S )z8
        Check ancestors of node for soft roots
        r   FN)r   r   r   r   r   r   r   )rl   r   r   newnoder   s        r,   r   z1SoftRootCutter.find_ancestors_and_remove_children$  s     ;;{{##K7335%)"-??US  Bd?7>>11'5AB ]] 	<E}--eU;	< r;   N)ru   rv   rw   rx   r   r   r   r   r   r;   r,   r   r     s    =~:r;   r   rq   )3r   collectionsr   collections.abcr   r   typingr   django.utils.functionalr   cmsr   cms.apphook_poolr	   
cms.modelsr
   r   r   r   cms.toolbar.utilsr   r   cms.utils.confr   cms.utils.i18nr   r   r   r   cms.utils.page_permissionsr   
menus.baser   r   r   menus.menu_poolr   VISIBILITY_ALLVISIBILITY_USERSr   VISIBILITY_ANONYMOUSr   r-   r:   r#   rh   r2   register_menur   register_modifierr   r   r;   r,   <module>r     s   	 # /  4  ) A A N *  ? 5 5 % &44i6P6PP !00)2P2PP G h$2hh{6K 2hV^_jVk 2hj$ $Nf
d f
R 	    /( /d 	  K ({X {| 	  N +r;   