src/pyams_content/component/links/__init__.py
changeset 1351 045be80a5645
parent 1258 49da29eef086
equal deleted inserted replaced
1350:1bbc829453f9 1351:045be80a5645
     8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
     9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
    10 # FOR A PARTICULAR PURPOSE.
    10 # FOR A PARTICULAR PURPOSE.
    11 #
    11 #
    12 
    12 
    13 __docformat__ = 'restructuredtext'
       
    14 
       
    15 from html import escape
    13 from html import escape
    16 
    14 
    17 from pyramid.encode import url_quote
    15 from pyramid.encode import url_quote, urlencode
    18 from zope.interface import implementer
    16 from pyramid.events import subscriber
       
    17 from zope.interface import alsoProvides, implementer, directlyProvidedBy, noLongerProvides
       
    18 from zope.lifecycleevent import IObjectAddedEvent, IObjectModifiedEvent
    19 from zope.schema.fieldproperty import FieldProperty
    19 from zope.schema.fieldproperty import FieldProperty
    20 from zope.schema.vocabulary import SimpleTerm, SimpleVocabulary
    20 from zope.schema.vocabulary import SimpleTerm, SimpleVocabulary
    21 
    21 
    22 from pyams_content import _
       
    23 from pyams_content.component.association import AssociationItem
    22 from pyams_content.component.association import AssociationItem
    24 from pyams_content.component.association.interfaces import IAssociationContainer, IAssociationContainerTarget, \
    23 from pyams_content.component.association.interfaces import IAssociationContainer, \
    25     IAssociationInfo
    24     IAssociationContainerTarget, IAssociationInfo
    26 from pyams_content.component.links.interfaces import IBaseLink, IExternalLink, IInternalLink, IMailtoLink
    25 from pyams_content.component.links.interfaces import IBaseLink, IExternalLink, IInternalLink, \
       
    26     IInternalLinkCustomInfoTarget, IMailtoLink, IInternalLinkCustomInfo, ICustomInternalLinkTarget
    27 from pyams_content.features.checker import BaseContentChecker
    27 from pyams_content.features.checker import BaseContentChecker
    28 from pyams_content.features.checker.interfaces import ERROR_VALUE, IContentChecker
    28 from pyams_content.features.checker.interfaces import ERROR_VALUE, IContentChecker
    29 from pyams_content.interfaces import IBaseContent
    29 from pyams_content.interfaces import IBaseContent
    30 from pyams_content.reference.pictograms.interfaces import IPictogramTable
    30 from pyams_content.reference.pictograms.interfaces import IPictogramTable
    31 from pyams_i18n.interfaces import II18n
    31 from pyams_i18n.interfaces import II18n
    40 from pyams_utils.vocabulary import vocabulary_config
    40 from pyams_utils.vocabulary import vocabulary_config
    41 from pyams_utils.zodb import volatile_property
    41 from pyams_utils.zodb import volatile_property
    42 from pyams_workflow.interfaces import IWorkflow, IWorkflowPublicationInfo
    42 from pyams_workflow.interfaces import IWorkflow, IWorkflowPublicationInfo
    43 
    43 
    44 
    44 
       
    45 __docformat__ = 'restructuredtext'
       
    46 
       
    47 from pyams_content import _
       
    48 
       
    49 
    45 #
    50 #
    46 # Links vocabulary
    51 # Links vocabulary
    47 #
    52 #
    48 
    53 
    49 @vocabulary_config(name='PyAMS content links')
    54 @vocabulary_config(name='PyAMS content links')
    53     def __init__(self, context=None):
    58     def __init__(self, context=None):
    54         terms = []
    59         terms = []
    55         target = get_parent(context, IAssociationContainerTarget)
    60         target = get_parent(context, IAssociationContainerTarget)
    56         if target is not None:
    61         if target is not None:
    57             terms = [SimpleTerm(link.__name__, title=IAssociationInfo(link).inner_title)
    62             terms = [SimpleTerm(link.__name__, title=IAssociationInfo(link).inner_title)
    58                      for link in IAssociationContainer(target).values() if IBaseLink.providedBy(link)]
    63                      for link in IAssociationContainer(target).values() if
       
    64                      IBaseLink.providedBy(link)]
    59         super(ContentLinksVocabulary, self).__init__(terms)
    65         super(ContentLinksVocabulary, self).__init__(terms)
    60 
    66 
    61 
    67 
    62 #
    68 #
    63 # Base link persistent class
    69 # Base link persistent class
   104     @property
   110     @property
   105     def label(self):
   111     def label(self):
   106         request = check_request()
   112         request = check_request()
   107         translate = request.localizer.translate
   113         translate = request.localizer.translate
   108         return II18n(self.context).query_attribute('title', request) or \
   114         return II18n(self.context).query_attribute('title', request) or \
   109             '({0})'.format(translate(self.context.icon_hint).lower())
   115                '({0})'.format(translate(self.context.icon_hint).lower())
   110 
   116 
   111 
   117 
   112 #
   118 #
   113 # Internal links
   119 # Internal links
   114 #
   120 #
   155     def get_url(self, request=None, view_name=None):
   161     def get_url(self, request=None, view_name=None):
   156         target = self.get_target()
   162         target = self.get_target()
   157         if target is not None:
   163         if target is not None:
   158             if request is None:
   164             if request is None:
   159                 request = check_request()
   165                 request = check_request()
       
   166             params = None
       
   167             if IInternalLinkCustomInfoTarget.providedBy(target):
       
   168                 custom_info = IInternalLinkCustomInfo(self, None)
       
   169                 if custom_info is not None:
       
   170                     params = custom_info.get_url_params()
       
   171                     if params:
       
   172                         params = urlencode(params)
   160             if self.force_canonical_url:
   173             if self.force_canonical_url:
   161                 return canonical_url(target, request, view_name)
   174                 return canonical_url(target, request, view_name, query=params)
   162             else:
   175             else:
   163                 return relative_url(target, request, view_name=view_name)
   176                 return relative_url(target, request, view_name=view_name, query=params)
   164         else:
   177         else:
   165             return ''
   178             return ''
       
   179 
       
   180 
       
   181 @subscriber(IObjectAddedEvent, context_selector=IInternalLink)
       
   182 def handle_new_internal_link(event):
       
   183     """Check if link target is providing custom info"""
       
   184     link = event.object
       
   185     target = link.target
       
   186     if target is not None:
       
   187         info = IInternalLinkCustomInfoTarget(target, None)
       
   188         if info is not None:
       
   189             alsoProvides(link, info.internal_link_marker_interface)
       
   190 
       
   191 
       
   192 @subscriber(IObjectModifiedEvent, context_selector=IInternalLink)
       
   193 def handle_updated_internal_link(event):
       
   194     """Check when modified if new link target is providing custom info"""
       
   195     link = event.object
       
   196     # remove previous provided interfaces
       
   197     ifaces = tuple([iface for iface in directlyProvidedBy(link)
       
   198                     if issubclass(iface, IInternalLinkCustomInfo)])
       
   199     for iface in ifaces:
       
   200         noLongerProvides(link, iface)
       
   201     target = link.target
       
   202     if target is not None:
       
   203         info = IInternalLinkCustomInfoTarget(target, None)
       
   204         if info is not None:
       
   205             alsoProvides(link, info.internal_link_marker_interface)
   166 
   206 
   167 
   207 
   168 @adapter_config(context=IInternalLink, provides=IAssociationInfo)
   208 @adapter_config(context=IInternalLink, provides=IAssociationInfo)
   169 class InternalLinkAssociationInfoAdapter(BaseLinkInfoAdapter):
   209 class InternalLinkAssociationInfoAdapter(BaseLinkInfoAdapter):
   170     """Internal link association info adapter"""
   210     """Internal link association info adapter"""
   204         if content is not None:
   244         if content is not None:
   205             workflow = IWorkflow(content, None)
   245             workflow = IWorkflow(content, None)
   206             if workflow is not None:
   246             if workflow is not None:
   207                 target = self.context.get_target(state=workflow.published_states)
   247                 target = self.context.get_target(state=workflow.published_states)
   208                 if target is None:
   248                 if target is None:
   209                     output.append(translate(ERROR_VALUE).format(field=IInternalLink['reference'].title,
   249                     output.append(
   210                                                                 message=translate(_("target is not published"))))
   250                         translate(ERROR_VALUE).format(field=IInternalLink['reference'].title,
       
   251                                                       message=translate(
       
   252                                                           _("target is not published"))))
   211         return output
   253         return output
   212 
   254 
   213 
   255 
   214 #
   256 #
   215 # External links
   257 # External links