Skip to content

Commit 8700a71

Browse files
committed
revise extending
1 parent c6db2a7 commit 8700a71

3 files changed

Lines changed: 98 additions & 67 deletions

File tree

docs/mastering-plone/add-ons.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,15 @@ myst:
33
html_meta:
44
"description": "Extending Plone with features via existing backend add-ons"
55
"property=og:description": "Extending Plone with features via existing backend add-ons"
6-
"property=og:title": "Extending Plone with add-on packages"
6+
"property=og:title": "Extend Plone with add-on packages"
77
"keywords": "Plone, Volto, add-on, customizing"
88
---
99

1010
(add-ons-label)=
1111

12-
# Extending Plone with add-on packages
12+
# Extend Plone with add-on packages
1313

14-
```{card}
15-
Backend chapter
14+
```{card} Backend chapter
1615
1716
For frontend add-ons see chapter {ref}`volto-addon-label`.
1817

docs/mastering-plone/configuring_customizing.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ myst:
33
html_meta:
44
"description": "What you can do through the web without touching the code"
55
"property=og:description": "What you can do through the web without touching the code"
6-
"property=og:title": "Configuring Plone 'through the web'"
6+
"property=og:title": "Configure Plone 'through the web'"
77
"keywords": "Plone, configuration"
88
---
99

1010
(configuring-customizing-label)=
1111

12-
# Configuring Plone "through the web"
12+
# Configure Plone "through the web"
1313

1414
(customizing-controlpanel-label)=
1515

docs/mastering-plone/extending.md

Lines changed: 93 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -3,65 +3,67 @@ myst:
33
html_meta:
44
"description": "Plone architecture and concepts"
55
"property=og:description": "Plone architecture and concepts"
6-
"property=og:title": "Extending Plone"
6+
"property=og:title": "Extend and customize Plone"
77
"keywords": "Plone, architecture, zcml, Generic Setup"
88
---
99

1010
(extending-label)=
1111

12-
# Extending Plone
12+
# Extend and customize Plone
1313

1414
```{card} Backend chapter
1515
16-
In this part you will:
17-
18-
- Get an overview over the technologies used to extend Plone
16+
In this part you will get an overview over the technologies used to extend the Plone backend.
1917
2018
Topics covered:
2119
22-
- Overriding Python components
20+
- Extension packages
2321
- Component architecture
2422
- ZCML
2523
- GenericSetup
2624
```
2725

28-
As a developer you want to go further than simply configuring Plone, you want to extend and customize it.
26+
As a developer you want to go further than simply configuring Plone.
27+
You want to extend and customize it.
2928
Plone is built to be extended.
3029
Extendability is not an afterthought but is the core of Plone and the systems it is based on.
31-
Instead it is the core of its architecture.
3230

33-
> Plone consists of a Python backend and a React frontend.
34-
> They are connected via the REST API.
35-
> Thus you have two different layers that you can customize.
31+
How do you extend Plone?
3632

37-
Therefore we create two different extension packages to customize and extend Plone:
33+
This depends on what type of extension you want to create.
3834

39-
1. One is a Python package that holds for example content types, behaviors and configuration.
40-
2. The other is a JavaScript package that hold views, styling and customization of the frontend.
35+
```{only} not presentation
36+
- You can create extensions with new types of objects to add to your Plone site. Usually these are content types.
37+
- You can create an extension that changes or extends functionality. For example to change the way Plone displays search results, or to make pictures searchable by adding a transformer from image to text.
38+
```
4139

42-
Sometimes it is easy to know, which layer needs to be customized to achieve a certain result.
40+
For most projects you combine multiple kinds of methods to extend Plone.
4341

44-
- All styling and JavaScript-based interaction is customized on the Volto side of Plone.
45-
- Content types and other persistent data is customized or created in a Python package.
4642

47-
For more complex use cases you will need to add code to both parts of our customization story.
48-
For example a content type is defined in the Python package and its visualization is defined in the JavaScript package.
43+
(extending-packages-label)=
4944

45+
## Extension packages
5046

51-
(extending-technologies-label)=
47+
Plone consists of a Python backend and a React frontend.
48+
They are connected via the REST API.
49+
Thus you have two different layers that you can customize.
5250

53-
## Extension technologies
51+
Therefore we create two different extension packages to customize and extend Plone.
52+
(These are similar to add-ons, but they are located in the project repository.)
5453

55-
How do you extend Plone?
54+
1. One is a Python package that holds for example content types, behaviors and configuration.
55+
(For the training project, this is located in {file}`backend/src/ploneconf/site`.)
56+
2. The other is a JavaScript package that hold views, styling and customization of the frontend.
57+
(For the training project, this is located in {file}`frontend/packages/volto-ploneconf-site`.)
5658

57-
This depends on what type of extension you want to create.
59+
Sometimes it is easy to know which layer needs to be customized to achieve a certain result.
5860

59-
```{only} not presentation
60-
- You can create extensions with new types of objects to add to your Plone site. Usually these are content types.
61-
- You can create an extension that changes or extends functionality. For example to change the way Plone displays search results, or to make pictures searchable by adding a transformer from image to text.
62-
```
61+
- All styling and JavaScript-based interaction is customized on the frontend side of Plone.
62+
- Content types and other persistent data are customized or created in a Python package.
63+
64+
For more complex use cases you will need to add code to both parts of our customization story.
65+
For example a content type is defined in the Python package and its visualization is defined in the JavaScript package.
6366

64-
For most projects you combine multiple kinds of methods to extend Plone.
6567

6668

6769
(extending-technologies-component-architecture-label)=
@@ -75,62 +77,82 @@ For most projects you combine multiple kinds of methods to extend Plone.
7577
- Powerful and flexible
7678
```
7779

78-
```{only} not presentation
79-
The best way to extend Plone is via *Components*.
80-
81-
A bit of history is in order.
80+
````{only} not presentation
8281
83-
When Zope started, object-oriented design was **the** silver bullet.
82+
Plone uses a component architecture to provide loose coupling between different parts of the system.
8483
85-
Object-oriented design is good at modeling inheritance, but breaks down when an object has multiple aspects that are part of multiple taxonomies.
84+
What does that mean?
85+
There is a central registry of components that can fulfill predefined contracts, called interfaces.
86+
If some code wants to make a call to another part of Plone, it should not do so directly.
87+
Instead, it should ask the registry for a component that can provide the interface it is designed to use.
8688
87-
Some object-oriented programming languages like Python handle this through multiple inheritance. But it's not a good way to do it. Zope objects have more than 10 base classes. Too many namespaces makes code that's hard to maintain. Where did that method/attribute come from?
89+
There are several kinds of components:
8890
89-
After a while, XML and Components became the next silver bullet (Does anybody remember J2EE?).
91+
* *Utilities* provide a standalone service.
92+
* *Adapters* provide a new way to access an existing object.
93+
* *Subscribers* execute actions in response to events triggered on a different object.
9094
91-
Based on their experiences with Zope in the past, Zope developers thought that a component system configured via XML might be the way to go to keep the code more maintainable.
95+
For example, there is an interface `INameFromTitle` which defines how to get the title for a content item.
96+
(Get an adapter which is registered for the `INameFromTitle` interface, and get its `title` attribute.)
97+
If you as a developer want to change how the title is calculated for a specific content type, you can register an `INameFromTitle` adapter for that content type.
9298
93-
Before Zope Components functionality was often extended by a practice called Monkey Patching: Changing code in other modules by importing and then modifying it at runtime.
99+
This is the basis for Plone's extensibility.
100+
Add-on packages can easily change core Plone functionality by adding or replacing components in the registry, without needing to directly change the code that uses those components.
94101
95-
Monkey Patching, like subclassing via multiple inheritance, does not scale. Multiple plugins might overwrite each other, you would explain to people that they have to reorder the imports, and then, suddenly, you will be forced to import feature A before B, B before C and C before A, or else your application won't work.
102+
```{tip}
103+
Many of the interfaces used by Plone core are defined in the `plone.base` package.
104+
You can explore them here: https://github.com/plone/plone.base/tree/main/src/plone/base/interfaces
96105
97-
As the new concepts were radically different from the old Zope concepts, the Zope developers renamed the new project to Zope 3.
98-
But it did not gain traction, was eventually renamed to Bluebream and then died out.
106+
However, Plone is made up of many packages, so there are also a lot of interfaces defined elsewhere.
107+
```
99108
100-
But the component architecture itself is quite successful and the Zope developers extracted it into the Zope Toolkit. The Zope toolkit is part of Zope, and Plone developers use it extensively.
109+
```{note}
110+
Earlier versions of Zope and Plone relied more on other ways of composing software, such as object-oriented inheritance.
111+
But this led to very complicated objects that were difficult to reason about and override.
101112
102-
This is what you want to use.
113+
Over time, many parts have been updated to use the component architecture.
114+
But there are still some inner parts which use inheritance.
115+
Sometimes it is necessary to use more invasive techniques like monkey-patching to override core Plone functionality.
103116
```
104117
118+
````
119+
120+
105121
(extending-components-label)=
106122

107-
## Configuring Zope Components with ZCML
123+
## Configure Zope Components with ZCML
108124

109125
```{only} presentation
110126
- zcml (Zope Component Markup Language) is used to register components
111127
- components are distingushed by interfaces (contracts) that they require or provide
112128
```
113129

114-
```{only} not presentation
115-
ZCML, the Zope Configuration Mark-up Language is an XML based language used to configure Zope Components. With ZCML you declare utilities, adapters and browser views.
130+
````{only} not presentation
131+
The Zope Configuration Markup Language (ZCML) is an XML-based language used to configure Zope components.
132+
With ZCML you register utilities, adapters and browser views using ZCML.
116133
117134
Components are distinguished from one another by the interfaces (formal definitions of functionality) that they require or provide.
118135
119-
During startup, Zope reads all these ZCML statements, validates that there are not two declarations trying to register the same components and registers everything. All components are registered by interfaces required and provided. Components with the same interfaces may optionally also be named.
136+
During startup, Zope reads all these ZCML statements, validates that there are not two declarations trying to register the same components, and registers everything.
137+
All components are registered by interfaces required and provided.
138+
Components with the same interfaces may optionally also be named.
120139
121-
It may seem a little cumbersome that you have to register all components. But thanks to ZCML, you hardly ever have a hard time to find what and where extensions or customizations are defined. ZCML files are like a phone book.
140+
```{tip}
141+
ZCML is only processed at startup time.
142+
If you make changes to a `.zcml` file, you have to restart the backend in order for the changes to take effect.
122143
```
123144
124-
```{eval-rst}
125-
.. epigraph::
126-
127-
Explicit is better than implicit
128-
129-
-- The Zen of Python
145+
It may seem a little cumbersome that you have to register all components.
146+
But thanks to ZCML, you hardly ever have a hard time to find what and where extensions or customizations are defined.
147+
ZCML files are like a phone book.
148+
````
130149

150+
```{epigraph}
151+
Explicit is better than implicit
152+
153+
-- The Zen of Python
131154
```
132155

133-
134156
(extending-technologies-generic-setup-label)=
135157

136158
## GenericSetup
@@ -141,15 +163,24 @@ It may seem a little cumbersome that you have to register all components. But th
141163
```
142164

143165
```{only} not presentation
144-
The next thing is {py:mod}`Products.GenericSetup`.
166+
Another tool for configuring Plone using XML files is {term}`GenericSetup`.
167+
168+
GenericSetup organizes XML configuration files in a _profile_.
169+
When the profile is applied, it will update persistent settings stored in the database.
145170
146-
*GenericSetup* lets you define persistent configuration in XML files. *GenericSetup* parses the XML files and updates the persistent configuration according to the configuration. This is a step you have to run on your own!
171+
Unlike ZCML, GenericSetup profiles are not read automatically.
172+
You have to apply the profile on your own, usually by installing or upgrading an add-on.
173+
When you do this, GenericSetup reads the XML files and updates the persistent configuration accordingly.
147174
148-
You will see many objects in Zope or the ZMI that you can customize through the web. If they are well behaving, they can export their configuration via *GenericSetup* and import it again.
175+
GenericSetup profiles are a useful way to programmatically configure the same things that can be changed through the web in a control panel.
176+
You will see many objects in Zope or the ZMI that you can customize through the web.
177+
If they are well behaving, they can export their configuration via GenericSetup and import it again.
149178
150-
Typically you use *GenericSetup* to change workflows or add new content type definitions.
179+
For example, you can use GenericSetup to change workflows or add new content type definitions.
151180
152-
GenericSetup profiles may also be built into Python packages. Every package that is listed on the add-on package list inside a Plone installation has a GS profile that details how it fits into Plone. Packages that are part of Plone itself may have GS profiles, but are excluded from the active/inactive listing.
181+
GenericSetup profiles may also be built into Python packages.
182+
Every package that is listed in the Add-ons control panel in Site Setup has a GenericSetup profile that defines how it fits into Plone.
183+
(Packages that are part of Plone itself may also have GenericSetup profiles, but are not shown in the Add-ons control panel unless they are optional.)
153184
```
154185

155186
Examples of a profile of an add-on in `profile/default/`
@@ -168,7 +199,8 @@ Examples of a profile of an add-on in `profile/default/`
168199
</metadata>
169200
```
170201

171-
Most settings are stored in a tool called `portal_registry`. Since it has great import/export handlers for GenericSetup it can be configured with {file}`registry/main.xml`:
202+
Most settings are stored in a tool called `portal_registry`.
203+
Since it has great import/export handlers for GenericSetup, it can be configured with {file}`registry/main.xml`:
172204

173205
{file}`registry/main.xml`:
174206

0 commit comments

Comments
 (0)