Skip to content

Commit de8f3ab

Browse files
committed
Tidy providing-marker-interfaces.md
1 parent 27c63e9 commit de8f3ab

File tree

1 file changed

+64
-64
lines changed

1 file changed

+64
-64
lines changed

plone.app.dexterity/behaviors/providing-marker-interfaces.md

Lines changed: 64 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,39 @@
11
---
22
myst:
33
html_meta:
4-
"description": ""
5-
"property=og:description": ""
6-
"property=og:title": ""
7-
"keywords": ""
4+
"description": "How to use behaviors to set marker interfaces on instances of a given content type in Plone"
5+
"property=og:description": "How to use behaviors to set marker interfaces on instances of a given content type in Plone"
6+
"property=og:title": "How to use behaviors to set marker interfaces on instances of a given content type in Plone"
7+
"keywords": "Plone, behaviors, content types, marker interfaces"
88
---
99

1010
# Providing marker interfaces
1111

12-
**How to use behaviors to set marker interfaces on instances of a given type.**
12+
This chapter describes how to use behaviors to set marker interfaces on instances of a given content type.
1313

14-
Sometimes, it is useful for objects that provide a particular behavior to also provide a specific marker interface.
15-
For example, you can register a viewlet for a particular marker and use a behavior to enable that marker on all instances of a particular content type.
14+
Sometimes it is useful for objects that provide a particular behavior to also provide a specific marker interface.
15+
For example, you can register a viewlet for a particular marker, and use a behavior to enable that marker on all instances of a particular content type.
1616
The viewlet will then only show up when the behavior is enabled.
17-
The same principle can be applied to event handlers, views and other components.
17+
The same principle can be applied to event handlers, views, and other components.
1818

19-
:::{note}
19+
```{note}
2020
There is usually no need to use markers to enable a custom adapter since a standard behavior is already a conditional adapter.
21-
However, in certain cases, you may want to provide one or more adapters to an interface that is not the behavior interface.
22-
E.g. to use a particular extension point provided by another component.
23-
In this case, it may easier to set a marker interface and provide an adapter from this marker.
24-
:::
21+
However, in certain cases, you may want to provide one or more adapters to an interface that is not the behavior interface, such as to use a particular extension point provided by another component.
22+
In this case, it may be easier to set a marker interface and provide an adapter from this marker.
23+
```
24+
25+
`plone.behavior`'s marker support can be used in two ways.
2526

26-
*plone.behavior’s* marker support can be used in two ways:
27+
- As the behavior interface itself.
28+
In this case, there is no behavior adapter factory.
29+
The behavior interface and the marker interface are one and the same.
30+
- As a supplement to a standard behavior adapter.
31+
In this case, a factory is provided, and the behavior interface (which the behavior adapter factory implements) is different to the marker interface.
2732

28-
- As the behavior interface itself. In this case, there is no behavior adapter factory.
29-
The behavior interface and the marker interface are one and the same.
30-
- As a supplement to a standard behavior adapter.
31-
In this case, a factory is provided, and the behavior interface (which the behavior adapter factory implements) is different to the marker interface.
3233

3334
## Primary marker behaviors
3435

35-
In the first case, where the behavior interface and the marker interface are the same, you can simply use the *\<plone:behavior />\*directive without a \*factory*.
36-
For example:
36+
In the first case, where the behavior interface and the marker interface are the same, you can simply use the `<plone:behavior />` directive without a `factory`.
3737

3838
```xml
3939
<plone:behavior
@@ -43,23 +43,23 @@ For example:
4343
/>
4444
```
4545

46-
One could imagine a viewlet based on [plone.pony] registered for the *IWantAPony* marker interface.
47-
If the behavior is enabled for a particular object, *IWantAPony.providedBy(object)* would be true.
46+
One could imagine a viewlet based on [`plone.pony`](https://pypi.org/project/plone.pony/) registered for the `IWantAPony` marker interface.
47+
If the behavior is enabled for a particular object, `IWantAPony.providedBy(object)` would be true.
48+
4849

4950
## Supplementary marker behaviors
5051

51-
In the second case, we want to provide a behavior interface with a behavior adapter factory as usual (e.g. with some form fields and a
52-
custom storage or a few methods implemented in an adapter), but we also need a custom marker.
53-
Here, we use both the *provides* and *marker* attributes to *\<plone:behavior />* to reference the two interfaces, as well as a *factory*.
52+
In the second case, we want to provide a behavior interface with a behavior adapter factory as usual, such as with some form fields and a custom storage or a few methods implemented in an adapter, but we also need a custom marker.
53+
Here we use both the `provides` and `marker` attributes to `<plone:behavior />` to reference the two interfaces, as well as a `factory`.
5454

55-
To a more interesting example, here is a behavior from a project that lets content authors with particular permissions (*iz.EditOfficialReviewers* and *iz.EditUnofficialReviewers*), nominate the official and any unofficial reviewers for a given content item.
55+
To a more interesting example, here is a behavior from a project that lets content authors with particular permissions (`iz.EditOfficialReviewers` and `iz.EditUnofficialReviewers`), nominate the "official" and any "unofficial" reviewers for a given content item.
5656
The behavior provides the necessary form fields to support this.
57-
It also sets a marker interface that enables
57+
It also sets a marker interface that enables the following.
5858

59-
- an *ILocalRoleProvider* adapter to automatically grant local roles to the chosen reviewers,
60-
- a custom indexer that lists the reviewers.
59+
- an `ILocalRoleProvider` adapter to automatically grant local roles to the chosen reviewers
60+
- a custom indexer that lists the reviewers
6161

62-
The ZCML registration looks like this:
62+
The ZCML registration would be the following.
6363

6464
```xml
6565
<plone:behavior
@@ -71,12 +71,12 @@ The ZCML registration looks like this:
7171
/>
7272
```
7373

74-
Notice the use of the *AnnotationStorage* factory.
75-
This is a re-usable factory that can be used to easily create behaviors from schema interfaces that store their values in annotations.
76-
Well describe this in more detail later.
77-
We could just as easily have provided our own factory in this example.
74+
Notice the use of the `AnnotationStorage` factory.
75+
This is a reusable factory that can be used to create behaviors from schema interfaces that store their values in annotations.
76+
We'll describe this in more detail later.
77+
We also could have provided our own factory in this example.
7878

79-
The *reviewers.py* module contains the following:
79+
The {file}`reviewers.py` module contains the following.
8080

8181
```python
8282
"""Behavior to enable certain users to nominate reviewers
@@ -106,21 +106,21 @@ class IReviewers(model.Schema):
106106
"""
107107

108108
directives.fieldset(
109-
'ownership',
110-
label=_('Ownership'),
109+
"ownership",
110+
label=_("Ownership"),
111111
fields=(
112-
'official_reviewers',
113-
'unofficial_reviewers'
112+
"official_reviewers",
113+
"unofficial_reviewers"
114114
),
115115
)
116116

117117
directives.widget(official_reviewers=AutocompleteMultiFieldWidget)
118-
directives.write_permission(official_reviewers='iz.EditOfficialReviewers')
118+
directives.write_permission(official_reviewers="iz.EditOfficialReviewers")
119119
official_reviewers = schema.Tuple(
120-
title=_('Official reviewers'),
120+
title=_("Official reviewers"),
121121
description=_(
122-
'People or groups who may review this item in an official '
123-
'capacity.'
122+
"People or groups who may review this item in an official "
123+
"capacity."
124124
),
125125
value_type=schema.Choice(
126126
title=_("Principal"),
@@ -131,12 +131,12 @@ class IReviewers(model.Schema):
131131
)
132132

133133
directives.widget(unofficial_reviewers=AutocompleteMultiFieldWidget)
134-
directives.write_permission(unofficial_reviewers='iz.EditUnofficialReviewers')
134+
directives.write_permission(unofficial_reviewers="iz.EditUnofficialReviewers")
135135
unofficial_reviewers = schema.Tuple(
136-
title=_('Unofficial reviewers'),
136+
title=_("Unofficial reviewers"),
137137
description=_(
138-
'People or groups who may review this item in a supplementary '
139-
'capacity'
138+
"People or groups who may review this item in a supplementary "
139+
"capacity"
140140
),
141141
value_type=schema.Choice(
142142
title=_("Principal"),
@@ -173,9 +173,9 @@ class ReviewerLocalRoles(object):
173173
return ()
174174

175175
if principal_id in c.official_reviewers:
176-
return ('Reviewer', 'OfficialReviewer',)
176+
return ("Reviewer", "OfficialReviewer",)
177177
elif principal_id in c.unofficial_reviewers:
178-
return ('Reviewer',)
178+
return ("Reviewer",)
179179

180180
return ()
181181

@@ -192,17 +192,17 @@ class ReviewerLocalRoles(object):
192192

193193
for principal_id in c.official_reviewers:
194194
seen.add(principal_id)
195-
yield (principal_id, ('Reviewer', 'OfficialReviewer'),)
195+
yield (principal_id, ("Reviewer", "OfficialReviewer"),)
196196

197197
for principal_id in c.unofficial_reviewers:
198198
if principal_id not in seen:
199-
yield (principal_id, ('Reviewer',),)
199+
yield (principal_id, ("Reviewer",),)
200200

201201

202202
@implementer(IIndexer)
203203
@adapter(IReviewersMarker, IZCatalog)
204204
class ReviewersIndexer(object):
205-
"""Catalog indexer for the 'reviewers' index.
205+
"""Catalog indexer for the "reviewers" index.
206206
"""
207207

208208
def __init__(self, context, catalog):
@@ -214,24 +214,24 @@ class ReviewersIndexer(object):
214214
return tuple(set(official + unofficial))
215215
```
216216

217-
Note that the *iz.EditOfficialReviewers* and *iz.EditUnofficialReviewers* permissions are defined and granted elsewhere.
217+
Note that the `iz.EditOfficialReviewers` and `iz.EditUnofficialReviewers` permissions are defined and granted elsewhere.
218218

219-
We need to register these components in *configure.zcml*:
219+
We need to register these components in {file}`configure.zcml`.
220220

221221
```xml
222222
<adapter factory=".reviewers.ReviewerLocalRoles" name="iz.behaviors.reviewers" />
223223
<adapter factory=".reviewers.ReviewersIndexer" name="reviewers" />
224224
```
225225

226-
This is quite a complex behavior, but hopefully you can see what’s going on:
227-
228-
- There is a standard schema interface, which includes form hints using *plone.autoform.directives* and is marked as an *IFormFieldProvider*.
229-
It uses *plone.formwidget.autocomplete* and *plone.principalsource* to implement the fields.
230-
- We define a marker interface (*IReviewersMarker*) and register this with the *marker* attribute of the *\<plone:behavior />* directive.
231-
- We define and register an adapter from this marker to *ILocalRoles* from *borg.localrole*.
232-
- Similarly, we register a multi-adapter to *IIndexer*, as provided by *plone.indexer*.
226+
This is a quite complex behavior, but hopefully you can see what's going on:
233227

234-
Although this behavior provides a lot of functionality, it is no more difficult for integrators to use than any other:
235-
they would simply list the behavior interface (*iz.behaviors.reviewers.IReviewers* in this case) in the FTI, and all this functionality comes to life. This is the true power of behaviors: developers can bundle up complex functionality into re-usable behaviors, which can then be enabled on a per-type basis by integrators (or the same developers in lazier moments).
228+
- There is a standard schema interface, which includes form hints using `plone.autoform.directives` and is marked as an `IFormFieldProvider`.
229+
It uses `plone.formwidget.autocomplete` and `plone.principalsource` to implement the fields.
230+
- We define a marker interface (`IReviewersMarker`) and register this with the `marker` attribute of the `<plone:behavior />` directive.
231+
- We define and register an adapter from this marker to `ILocalRoles` from `borg.localrole`.
232+
- Similarly, we register a multi-adapter to `IIndexer`, as provided by `plone.indexer`.
236233

237-
[plone.pony]: http://pypi.python.org/pypi/plone.pony
234+
Although this behavior provides a lot of functionality, it is no more difficult for integrators to use than any other.
235+
They would list the behavior interface (`iz.behaviors.reviewers.IReviewers` in this case) in the FTI, and all this functionality comes to life.
236+
This is the true power of behaviors.
237+
Developers can bundle up complex functionality into reusable behaviors, which can then be enabled on a per-type basis by integrators or the same developers in lazier moments.

0 commit comments

Comments
 (0)