PluginProbe
Gutenberg / 14.7.0
Gutenberg v14.7.0
24.0.0 23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 12.6.0 All 403 releases
← All changes | lib/README.md +80 -138 23.3.0 → 14.7.0 View file →
@@ -1,203 +1,145 @@
1 1 # Gutenberg PHP
2 2
3 -This documentation is intended for developers who are contributing to the PHP code in the Gutenberg plugin, and pertains to files in the `lib` directory.
4 -
5 -The Gutenberg plugin is continuously enhancing existing features and creating new ones. Some features, once considered stable and useful, are merged into Core (the WordPress source code) during a WordPress release. Others remain in the plugin forever or are eventually removed as the minimum supported WordPress version changes.
6 -
7 -During a WordPress release, new features, bugfixes and other changes are "synced" between the Gutenberg plugin and WordPress Core. Consistent naming and directory structures make this process easier by preventing naming conflicts and compartmentalizing release-specific code.
8 -
9 -The following documentation is intended to act as a guide only. If you're unsure about naming or where to place new PHP files, please don't hesitate to ping other contributors on GitHub or ask in the #core-editor channel on [WordPress Slack](https://make.wordpress.org/chat/).
10 -
11 3 ## File structure
12 4
13 -To make it easier for contributors to identify features that should be merged into Core and those that can be deleted, Gutenberg uses the following file structure for its PHP code:
5 +Gutenberg adds features to WordPress Core using PHP hooks and filters. Some
6 +features, once considered stable and useful, are merged into Core during a Core
7 +release. Some features remain in the plugin forever or are removed.
14 8
15 -- `lib/experimental` - Experimental features that exist only in the plugin. They should not be merged into Core.
16 -- `lib/compat/wordpress-X.Y` - Stable features that are intended to be merged into Core in a future `X.Y` release, or that were previously merged to Core in the `X.Y` release and remain in the plugin for backwards compatibility when running the plugin on older versions of WordPress.
17 -- `lib/compat/plugin` - Features for backwards compatibility for the plugin consumers. These files don't need to be merged into Core and should have a timeline for when they should be removed from the plugin.
9 +To make it easier for contributors to know which features need to be merged to
10 +Core and which features can be deleted, Gutenberg uses the following file
11 +structure for its PHP code:
18 12
19 -Files at the root of `/lib` are generally considered to contain "evergreen" code. Such code is both fundamental to the proper functioning of the plugin, and also so often updated that versioning it between WordPress releases is not practical. Changes to these files are merged into Core as required.
13 +- `lib/experimental` - Experimental features that exist only in the plugin. They
14 + are not ready to be merged to Core.
15 +- `lib/stable` - Stable features that exist only in the plugin. They could one
16 + day be merged to Core, but not yet.
17 +- `lib/compat/wordpress-X.Y` - Stable features that are intended to be merged to
18 + Core in the future X.Y release, or that were previously merged to Core in the
19 + X.Y release and remain in the plugin for backwards compatibility when running
20 + the plugin on older versions of WordPress.
21 +- `lib/compat/plugin` - Features for backwards compatibility for the plugin consumers. These files don't need to be merged to Core and should have a timeline for when they should be removed from the plugin.
20 22
21 23 ## Best practices
22 24
23 -There are a few best practices that should be observed when adding new files to the Gutenberg plugin.
25 +### Prefer the `wp` prefix
24 26
25 -### Using `gutenberg` suffixes/prefixes vs. `wp` prefixes
27 +For features that may be merged to Core, it's best to use a `wp_` prefix for functions or a `WP_` prefix for classes.
26 28
27 -To avoid naming conflicts with WordPress Core and other plugins, the Gutenberg plugin uses the `gutenberg` identifier in many of its PHP classes and function names, e.g., `WP_Theme_JSON_Gutenberg` and `gutenberg_get_block_editor_settings`.
29 +This applies to both experimental and stable features.
28 30
29 -This is especially so for classes and functions whose functionality is ubiquitous and constantly being updated — so-called "evergreen" code. Anything related to `WP_Theme_JSON_Gutenberg` is a good example of this: this class controls the way Gutenberg processes and outputs global styles and much more, and its methods are called in many places. In every aspect of plugin functionality, we want plugin users to have access to the latest versions of these files, even if they are running an older version of WordPress.
31 +Using the `wp_` prefix avoids us having to rename functions and classes from `gutenberg_` to `wp_` if the feature is merged to Core.
30 32
31 -```php
32 -/**
33 -* Returns something useful.
34 -*
35 -* @since 6.2.0 Updates to something even more useful.
36 -* @since 6.3.0 Now more useful than ever.
37 -*
38 -* @return string Something useful.
39 -*/
40 -function gutenberg_get_something_useful() {
41 - // ...
42 -}
43 -```
33 +Functions that are intended solely for the plugin, e.g., plugin infrastructure, should use the `gutenberg_` prefix.
44 34
45 -When porting new functions into Core, the function must be renamed to use the `wp_` prefix for functions or a `WP_` prefix for classes.
35 +#### Feature that might be merged to Core
46 36
47 37 ```php
48 -/**
49 -* Returns something useful.
50 -*
51 -* @since 6.2.0 Updates to something even more useful.
52 -* @since 6.3.0 Now more useful than ever.
53 -*
54 -* @return string Something useful.
55 -*/
56 -function wp_get_something_useful() {
57 - // ...
58 -}
38 +function wp_get_navigation( $slug ) { ... }
59 39 ```
60 40
61 -Plugin code that is stable and expected to be merged "as-is" into Core in the near future can use the `wp_` prefix for functions or a `WP_` prefix for classes.
41 +#### Plugin infrastructure that will never be merged to Core
62 42
63 -#### Avoiding duplicate declarations
64 -
65 -When doing so, care must be taken to ensure that no duplicate declarations to create functions or classes exist between Gutenberg and WordPress core code. A quick codebase search will also help you know if your new names are unique.
66 -
67 -Wrapping such code in `class_exists()` and `function_exists()` checks should be used to ensure it executes in the plugin up until it is merged to Core, or when running the plugin on older versions of WordPress.
68 -
69 43 ```php
70 -if ( ! function_exists( 'wp_a_new_and_stable_feature' ) ) {
71 - /**
72 - * A very new and stable feature.
73 - *
74 - * @return string Something useful.
75 - */
76 - function wp_a_new_and_stable_feature() {
77 - // ...
78 - }
79 -}
44 +function gutenberg_get_navigation( $slug ) { ... }
80 45 ```
81 46
82 -Or for classes:
47 +### Group PHP code by _feature_
83 48
84 -```php
85 -/**
86 - * WP_A_Stable_Class class
87 - *
88 - * @package WordPress
89 - * @since 6.3.0
90 - */
91 -if ( ! class_exists( 'WP_A_Stable_Class' ) ) {
92 - // Do not invert this pattern with an early `return`.
93 - // See below for details...
94 - class WP_A_Stable_Class { ... }
95 -}
96 -```
49 +Developers should organize PHP into files or folders by _feature_, not by _component_.
97 50
98 -Wrapping code in `class_exists()` and `function_exists()` is usually inappropriate for evergreen code, or any plugin code that we expect to undergo constant change between WordPress releases, because it would prevent the latest versions of the code from being used. For example, the statement `class_exists( 'WP_Theme_JSON' )` would return `true` because the class already exists in Core.
51 +When defining a function that will be hooked, developers should call `add_action` and `add_filter` immediately after the function declaration.
99 52
100 -The `return` operator is considered an anti-pattern in the context provided below because it [does not halt](https://www.php.net/manual/en/function.return.php#112515) the parsing of the PHP script and can cause [unexpected side effects](https://github.com/WordPress/gutenberg/pull/58429#issuecomment-1916670097):
101 -```php
102 -/**
103 - * ANTI-PATTERN
104 - * DO NOT COPY!
105 - *
106 - */
107 -if ( class_exists( 'WP_A_Stable_Class' ) ) {
108 - return; // do not do this.
109 -}
110 -```
53 +These two practices make it easier for PHP code to start in one folder (e.g., `lib/experimental`) and eventually move to another using a simple `git mv`.
111 54
112 -When to use which prefix is a judgement call, but the general rule is that if you're unsure, use the `gutenberg` prefix because it will less likely give rise to naming conflicts.
55 +#### Good
113 56
114 -#### When not to use plugin-specific prefixes/suffixes
57 +```php
58 +// lib/experimental/navigation.php
115 59
116 -The above recommendations in relation to plugin-specific prefixes/suffixes are relevant only to files in the `lib` directory and only in the Gutenberg plugin.
60 +function wp_get_navigation( $slug ) { ... }
117 61
118 -`Gutenberg` prefixes/suffixes _should not_ be used in Core PHP code. When syncing `/lib` files to Core, plugin-specific prefixes/suffixes are generally replaced with their `WP_` or `wp_` equivalents manually.
62 +function wp_register_navigation_cpt() { ... }
119 63
120 -Accordingly, unless required to run plugin-only code, you should avoid using plugin-specific prefixes/suffixes in any block PHP code. Core blocks in the plugin are [published as NPM packages](https://github.com/WordPress/gutenberg/blob/trunk/docs/contributors/code/release/README.md#packages-releases-to-npm-and-wordpress-core-updates), which Core consumes as NPM dependencies.
64 +add_action( 'init', 'wp_register_navigation_cpt' );
65 +```
121 66
122 -See [block naming conventions](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library#naming-convention-for-php-functions) for more information on block naming conventions.
67 +#### Not so good
123 68
124 -As always, get in touch with your fellow contributors if you're unsure.
69 +```php
70 +// lib/experimental/functions.php
125 71
126 -### Documentation and annotations
72 +function wp_get_navigation( $slug ) { ... }
127 73
128 -For every class, method and function in the plugin, refer to the [WordPress PHP documentation standards](https://developer.wordpress.org/coding-standards/inline-documentation-standards/php/) when documenting your code.
74 +// lib/experimental/post-types.php
129 75
130 -It's particularly important to observe annotation standards, and `@since` descriptions that specify the target WordPress version, so that all contributors can easily identify what needs to be (or what already has been) merged to Core and when.
76 +function wp_register_navigation_cpt() { ... }
131 77
132 -Developers should also write a brief note about _how_ their feature should be merged to Core, for example, which Core file or function should be patched.
78 +// lib/experimental/init.php
79 +add_action( 'init', 'wp_register_navigation_cpt' );
80 +```
133 81
134 -Notes can be included in the doc comment.
82 +### Wrap functions and classes with `! function_exists` and `! class_exists`
135 83
136 -This helps future developers know what to do when merging Gutenberg features into Core.
84 +Developers should take care to not define functions and classes that are already defined.
137 85
138 -```php
139 -/**
140 - * Returns a navigation object for the given slug.
141 - *
142 - * Should live in `wp-includes/navigation.php` when merged to Core.
143 - *
144 - * @since 6.3.0
145 - *
146 - * @param string $slug
147 - * @return WP_Navigation
148 - */
149 -function wp_get_navigation( $slug ) { ... }
150 -```
86 +When writing new functions and classes, it's good practice to use `! function_exists` and `! class_exists`.
151 87
152 -### Group PHP code by _feature_
88 +If Core has defined a symbol once and then Gutenberg defines it a second time, fatal errors will occur.
153 89
154 -Developers should organize PHP into files or folders by _feature_, not by _component_.
90 +Wrapping functions and classes avoids such errors if the feature is merged to Core.
155 91
156 -When defining a function that will be hooked, developers should call `add_action` and `add_filter` immediately after the function declaration.
157 -
158 -These two practices make it easier for PHP code to start in one folder (e.g., `lib/experimental`) and eventually move to another using a simple `git mv`.
159 -
160 92 #### Good
161 93
162 94 ```php
163 -// lib/experimental/navigation.php
95 +// lib/experimental/navigation/navigation.php
164 96
165 -function wp_get_navigation( $slug ) { ... }
97 +if ( ! function_exists( 'wp_get_navigation' ) ) {
98 + function wp_get_navigation( $slug ) { ... }
99 +}
166 100
167 -function wp_register_navigation_cpt() { ... }
101 +// lib/experimental/navigation/class-wp-navigation.php
168 102
169 -add_action( 'init', 'wp_register_navigation_cpt' );
103 +if ( class_exists( 'WP_Navigation' ) ) {
104 + return;
105 +}
106 +
107 +class WP_Navigation { ... }
170 108 ```
171 109
172 110 #### Not so good
173 111
174 112 ```php
175 -// lib/experimental/functions.php
113 +// lib/experimental/navigation/navigation.php
176 114
177 115 function wp_get_navigation( $slug ) { ... }
178 116
179 -// lib/experimental/post-types.php
117 +// lib/experimental/navigation/class-gutenberg-navigation.php
180 118
181 -function wp_register_navigation_cpt() { ... }
182 -
183 -// lib/experimental/init.php
184 -add_action( 'init', 'wp_register_navigation_cpt' );
119 +class WP_Navigation { ... }
185 120 ```
186 121
187 -### Requiring files in lib/load.php
122 +Furthermore, a quick codebase search will also help you know if your new method is unique.
188 123
189 -Should the load order allow it, try to group imports according to WordPress release, then feature. It'll help everyone to quickly recognise the files that belong to specific WordPress releases.
124 +### Note how your feature should look when merged to Core
190 125
191 -Existing comments in `lib/load.php` should act as a guide.
126 +Developers should write a brief note about how their feature should be merged to Core, for example, which Core file or function should be patched.
192 127
193 -## When to sync changes to Gutenberg PHP with Core and vice versa
128 +Notes can be included in the doc comment.
194 129
195 -On open Gutenberg PRs, changes to certain files are flagged as requiring syncing (also called "backporting") to WordPress Core, for example, PHP files in `/lib` and PHP unit tests.
130 +This helps future developers know what to do when merging Gutenberg features into Core.
196 131
197 -The CI checks will indicate whether you need to create a Core PR. If you do, you'll need to create a corresponding markdown file and place it within the appropriate release subdirectory in the [Core backport changelog](https://github.com/WordPress/gutenberg/tree/trunk/backport-changelog/).
132 +#### Good
198 133
199 -For more information, please refer to the [Core backport changelog documentation](https://github.com/WordPress/gutenberg/tree/trunk/backport-changelog/readme.md).
200 -
201 -So too, if you've made changes in WordPress Core to code that also lives in the Gutenberg plugin, these changes will need to be synced to Gutenberg. The relevant Gutenberg GitHub pull request should be labeled with the `Backport from WordPress Core` label.
202 -
203 -If you're unsure, you can always ask for help in the #core-editor channel in [WordPress Slack](https://make.wordpress.org/chat/).
134 +```php
135 +/**
136 + * Returns a navigation object for the given slug.
137 + *
138 + * Should live in `wp-includes/navigation.php` when merged to Core.
139 + *
140 + * @param string $slug
141 + *
142 + * @return WP_Navigation
143 + */
144 +function wp_get_navigation( $slug ) { ... }
145 +```