You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
**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.
13
13
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.
16
16
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.
18
18
19
-
:::{note}
19
+
```{note}
20
20
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.
25
26
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.
27
32
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.
32
33
33
34
## Primary marker behaviors
34
35
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`.
37
37
38
38
```xml
39
39
<plone:behavior
@@ -43,23 +43,23 @@ For example:
43
43
/>
44
44
```
45
45
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
+
48
49
49
50
## Supplementary marker behaviors
50
51
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`.
54
54
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.
56
56
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.
58
58
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
61
61
62
-
The ZCML registration looks like this:
62
+
The ZCML registration would be the following.
63
63
64
64
```xml
65
65
<plone:behavior
@@ -71,12 +71,12 @@ The ZCML registration looks like this:
71
71
/>
72
72
```
73
73
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
-
We’ll 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.
78
78
79
-
The *reviewers.py* module contains the following:
79
+
The {file}`reviewers.py` module contains the following.
80
80
81
81
```python
82
82
"""Behavior to enable certain users to nominate reviewers
@@ -106,21 +106,21 @@ class IReviewers(model.Schema):
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:
233
227
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`.
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