|
1 # |
|
2 # Copyright (c) 2008-2015 Thierry Florac <tflorac AT ulthar.net> |
|
3 # All Rights Reserved. |
|
4 # |
|
5 # This software is subject to the provisions of the Zope Public License, |
|
6 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. |
|
7 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED |
|
8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS |
|
10 # FOR A PARTICULAR PURPOSE. |
|
11 # |
|
12 |
|
13 __docformat__ = 'restructuredtext' |
|
14 |
|
15 |
|
16 # import standard library |
|
17 |
|
18 # import interfaces |
|
19 from hypatia.interfaces import ICatalog |
|
20 from pyams_content.component.links.interfaces import IBaseLink, IInternalLink, IExternalLink |
|
21 from pyams_content.shared.common.interfaces import IWfSharedContent |
|
22 from pyams_form.interfaces.form import IFormContextPermissionChecker |
|
23 from zope.lifecycleevent.interfaces import IObjectAddedEvent, IObjectModifiedEvent, IObjectRemovedEvent |
|
24 |
|
25 # import packages |
|
26 from hypatia.catalog import CatalogQuery |
|
27 from hypatia.query import Eq, Any |
|
28 from persistent import Persistent |
|
29 from pyams_catalog.query import CatalogResultSet |
|
30 from pyams_content.workflow import VISIBLE_STATES |
|
31 from pyams_sequence.utility import get_last_version |
|
32 from pyams_utils.adapter import adapter_config, ContextAdapter |
|
33 from pyams_utils.registry import get_utility |
|
34 from pyams_utils.traversing import get_parent |
|
35 from pyams_utils.url import absolute_url |
|
36 from pyramid.events import subscriber |
|
37 from pyramid.threadlocal import get_current_registry |
|
38 from zope.lifecycleevent import ObjectModifiedEvent |
|
39 from zope.container.contained import Contained |
|
40 from zope.interface import implementer |
|
41 from zope.schema.fieldproperty import FieldProperty |
|
42 |
|
43 |
|
44 @implementer(IBaseLink) |
|
45 class BaseLink(Persistent, Contained): |
|
46 """Base link persistent class""" |
|
47 |
|
48 title = FieldProperty(IBaseLink['title']) |
|
49 description = FieldProperty(IBaseLink['description']) |
|
50 |
|
51 |
|
52 @adapter_config(context=IBaseLink, provides=IFormContextPermissionChecker) |
|
53 class BaseLinkPermissionChecker(ContextAdapter): |
|
54 """Base link permission checker""" |
|
55 |
|
56 @property |
|
57 def edit_permission(self): |
|
58 content = get_parent(self.context, IWfSharedContent) |
|
59 return IFormContextPermissionChecker(content).edit_permission |
|
60 |
|
61 |
|
62 @subscriber(IObjectAddedEvent, context_selector=IBaseLink) |
|
63 def handle_added_link(event): |
|
64 """Handle added link""" |
|
65 content = get_parent(event.object, IWfSharedContent) |
|
66 if content is not None: |
|
67 get_current_registry().notify(ObjectModifiedEvent(content)) |
|
68 |
|
69 |
|
70 @subscriber(IObjectModifiedEvent, context_selector=IBaseLink) |
|
71 def handle_modified_link(event): |
|
72 """Handle modified link""" |
|
73 content = get_parent(event.object, IWfSharedContent) |
|
74 if content is not None: |
|
75 get_current_registry().notify(ObjectModifiedEvent(content)) |
|
76 |
|
77 |
|
78 @subscriber(IObjectRemovedEvent, context_selector=IBaseLink) |
|
79 def handle_removed_link(event): |
|
80 """Handle removed link""" |
|
81 content = get_parent(event.object, IWfSharedContent) |
|
82 if content is not None: |
|
83 get_current_registry().notify(ObjectModifiedEvent(content)) |
|
84 |
|
85 |
|
86 @implementer(IInternalLink) |
|
87 class InternalLink(BaseLink): |
|
88 """Internal link persistent class""" |
|
89 |
|
90 reference = FieldProperty(IInternalLink['reference']) |
|
91 |
|
92 def get_target(self, state=None): |
|
93 catalog = get_utility(ICatalog) |
|
94 params = Eq(catalog['oid'], self.reference) |
|
95 if state: |
|
96 if not isinstance(state, (list, tuple)): |
|
97 state = (state, ) |
|
98 params &= Any(catalog['workflow_state'], state) |
|
99 results = list(CatalogResultSet(CatalogQuery(catalog).query(params))) |
|
100 if results: |
|
101 return results[0] |
|
102 else: |
|
103 results = list(map(get_last_version, CatalogResultSet(CatalogQuery(catalog).query(params)))) |
|
104 if results: |
|
105 return results[0] |
|
106 |
|
107 def get_editor_url(self): |
|
108 return 'oid://{0}'.format(self.reference) |
|
109 |
|
110 def get_url(self, request, view_name=None): |
|
111 target = self.get_target(state=VISIBLE_STATES) |
|
112 if target is not None: |
|
113 return absolute_url(target, request, view_name) |
|
114 else: |
|
115 return '' |
|
116 |
|
117 |
|
118 @implementer(IExternalLink) |
|
119 class ExternalLink(BaseLink): |
|
120 """external link persistent class""" |
|
121 |
|
122 url = FieldProperty(IExternalLink['url']) |
|
123 language = FieldProperty(IExternalLink['language']) |
|
124 |
|
125 def get_editor_url(self): |
|
126 return self.url |
|
127 |
|
128 def get_url(self, request, view_name=None): |
|
129 return self.url |