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 |
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 |
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 |