Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like Block_Container often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Block_Container, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
9 | class Block_Container extends Container { |
||
10 | /** |
||
11 | * {@inheritDoc} |
||
12 | */ |
||
13 | public $settings = array( |
||
14 | 'mode' => 'edit', |
||
15 | 'preview' => true, |
||
16 | 'parent' => null, |
||
17 | 'icon' => 'block-default', |
||
18 | 'inner_blocks' => array( |
||
19 | 'enabled' => false, |
||
20 | 'position' => 'above', |
||
21 | 'template' => null, |
||
22 | 'template_lock' => null, |
||
23 | 'allowed_blocks' => null, |
||
24 | ), |
||
25 | 'category' => array( |
||
26 | 'slug' => 'common', |
||
27 | ), |
||
28 | ); |
||
29 | |||
30 | /** |
||
31 | * Mode map for settings |
||
32 | * |
||
33 | * @see set_mode() |
||
34 | * @var array |
||
35 | */ |
||
36 | protected $mode_map = array( |
||
37 | 'both' => array( |
||
38 | 'mode' => 'edit', |
||
39 | 'preview' => true, |
||
40 | ), |
||
41 | 'edit' => array( |
||
42 | 'mode' => 'edit', |
||
43 | 'preview' => false, |
||
44 | ), |
||
45 | 'preview' => array( |
||
46 | 'mode' => 'preview', |
||
47 | 'preview' => false, |
||
48 | ), |
||
49 | ); |
||
50 | |||
51 | /*** |
||
52 | * Block type render callback. |
||
53 | * |
||
54 | * @var callable |
||
55 | */ |
||
56 | protected $render_callback; |
||
57 | |||
58 | /** |
||
59 | * {@inheritDoc} |
||
60 | */ |
||
61 | View Code Duplication | public function __construct( $id, $title, $type, $condition_collection, $condition_translator ) { |
|
68 | |||
69 | /** |
||
70 | * {@inheritDoc} |
||
71 | */ |
||
72 | public function init() { |
||
75 | |||
76 | /** |
||
77 | * {@inheritDoc} |
||
78 | */ |
||
79 | public function is_valid_save() { |
||
84 | |||
85 | /** |
||
86 | * {@inheritDoc} |
||
87 | */ |
||
88 | public function save( $data = null ) { |
||
92 | |||
93 | /** |
||
94 | * {@inheritDoc} |
||
95 | */ |
||
96 | protected function get_environment_for_request() { |
||
99 | |||
100 | /** |
||
101 | * {@inheritDoc} |
||
102 | */ |
||
103 | public function is_valid_attach_for_request() { |
||
106 | |||
107 | /** |
||
108 | * {@inheritDoc} |
||
109 | */ |
||
110 | protected function get_environment_for_object( $object_id ) { |
||
113 | |||
114 | /** |
||
115 | * {@inheritDoc} |
||
116 | */ |
||
117 | public function is_valid_attach_for_object( $object_id = null ) { |
||
120 | |||
121 | /** |
||
122 | * {@inheritDoc} |
||
123 | */ |
||
124 | public function attach() { |
||
129 | |||
130 | /** |
||
131 | * Attach the category of the block type. |
||
132 | * |
||
133 | * @param array $categories |
||
134 | * @return array |
||
135 | */ |
||
136 | public function attach_block_category( $categories ) { |
||
145 | |||
146 | /** |
||
147 | * Set the description of the block type. |
||
148 | * |
||
149 | * @see https://wordpress.org/gutenberg/handbook/designers-developers/developers/block-api/block-registration/#description-optional |
||
150 | * |
||
151 | * @param string $description |
||
152 | * @return Block_Container |
||
153 | */ |
||
154 | public function set_description( $description ) { |
||
159 | |||
160 | /** |
||
161 | * Set the category of the block type. |
||
162 | * |
||
163 | * @see https://wordpress.org/gutenberg/handbook/designers-developers/developers/block-api/block-registration/#category |
||
164 | * |
||
165 | * @param string $slug |
||
166 | * @param string $title |
||
167 | * @param string $icon |
||
168 | * @return Block_Container |
||
169 | */ |
||
170 | public function set_category( $slug, $title = null, $icon = null ) { |
||
177 | |||
178 | /** |
||
179 | * Set the icon of the block type. |
||
180 | * |
||
181 | * @see https://developer.wordpress.org/resource/dashicons |
||
182 | * @see https://wordpress.org/gutenberg/handbook/designers-developers/developers/block-api/block-registration/#icon-optional |
||
183 | * |
||
184 | * @param string $icon |
||
185 | * @return Block_Container |
||
186 | */ |
||
187 | public function set_icon( $icon ) { |
||
192 | |||
193 | /** |
||
194 | * Set the keywords of the block type. |
||
195 | * |
||
196 | * @see https://wordpress.org/gutenberg/handbook/designers-developers/developers/block-api/block-registration/#keywords-optional |
||
197 | * |
||
198 | * @param array $keywords |
||
199 | * @return Block_Container |
||
200 | */ |
||
201 | public function set_keywords( $keywords = array() ) { |
||
206 | |||
207 | /** |
||
208 | * Set a style handle. |
||
209 | * |
||
210 | * @param string $key |
||
211 | * @param string $handle |
||
212 | * @return Block_Container |
||
213 | */ |
||
214 | protected function set_style_handle( $key, $handle ) { |
||
223 | |||
224 | /** |
||
225 | * Set the style of the block type. |
||
226 | * |
||
227 | * @param string $handle |
||
228 | * @return Block_Container |
||
229 | */ |
||
230 | public function set_style( $handle ) { |
||
233 | |||
234 | /** |
||
235 | * Set the editor style of the block type. |
||
236 | * |
||
237 | * @param string $handle |
||
238 | * @return Block_Container |
||
239 | */ |
||
240 | public function set_editor_style( $handle ) { |
||
243 | |||
244 | /** |
||
245 | * Set whether the preview mode is available for the block type. |
||
246 | * |
||
247 | * @param boolean $preview |
||
248 | * @return Block_Container |
||
249 | */ |
||
250 | public function set_preview_mode( $preview = true ) { |
||
258 | |||
259 | /** |
||
260 | * Set the mode for the block type. |
||
261 | * |
||
262 | * @param string $mode |
||
263 | * @return Block_Container |
||
264 | */ |
||
265 | public function set_mode( $mode ) { |
||
276 | |||
277 | /** |
||
278 | * Set the parent block(s) in which the block type can be inserted. |
||
279 | * |
||
280 | * @see https://wordpress.org/gutenberg/handbook/designers-developers/developers/block-api/block-registration/#parent-optional |
||
281 | * |
||
282 | * @param string|string[]|null $parent |
||
283 | * @return Block_Container |
||
284 | */ |
||
285 | public function set_parent( $parent = null ) { |
||
294 | |||
295 | /** |
||
296 | * Set whether the inner blocks are available for the block type. |
||
297 | * |
||
298 | * @param boolean $inner_blocks |
||
299 | * @return Block_Container |
||
300 | */ |
||
301 | public function set_inner_blocks( $inner_blocks = true ) { |
||
306 | |||
307 | /** |
||
308 | * Set the position of the inner blocks to be rendered |
||
309 | * above or below the fields. |
||
310 | * |
||
311 | * @param string $position |
||
312 | * @return Block_Container |
||
313 | */ |
||
314 | View Code Duplication | public function set_inner_blocks_position( $position = 'above' ) { |
|
323 | |||
324 | /** |
||
325 | * Set the default template that should be rendered in inner blocks. |
||
326 | * |
||
327 | * @see https://github.com/WordPress/gutenberg/tree/master/packages/editor/src/components/inner-blocks#template |
||
328 | * |
||
329 | * @param array[]|null $template |
||
330 | * @return Block_Container |
||
331 | */ |
||
332 | public function set_inner_blocks_template( $template = null ) { |
||
341 | |||
342 | /** |
||
343 | * Set the lock mode used by template of inner blocks. |
||
344 | * |
||
345 | * @see https://github.com/WordPress/gutenberg/tree/master/packages/editor/src/components/inner-blocks#templatelock |
||
346 | * |
||
347 | * @param string|boolean|null $lock |
||
348 | * @return Block_Container |
||
349 | */ |
||
350 | View Code Duplication | public function set_inner_blocks_template_lock( $lock = null ) { |
|
359 | |||
360 | /** |
||
361 | * Set the list of allowed blocks that can be inserted. |
||
362 | * |
||
363 | * @see https://github.com/WordPress/gutenberg/tree/master/packages/editor/src/components/inner-blocks#allowedblocks |
||
364 | * |
||
365 | * @param string[]|null $blocks |
||
366 | * @return Block_Container |
||
367 | */ |
||
368 | public function set_allowed_inner_blocks( $blocks = null ) { |
||
387 | |||
388 | /** |
||
389 | * Set the render callback of the block type. |
||
390 | * |
||
391 | * @see https://wordpress.org/gutenberg/handbook/designers-developers/developers/tutorials/block-tutorial/creating-dynamic-blocks/ |
||
392 | * |
||
393 | * @param callable $render_callback |
||
394 | * @return Block_Container |
||
395 | */ |
||
396 | public function set_render_callback( $render_callback ) { |
||
401 | |||
402 | /** |
||
403 | * Render the block type. |
||
404 | * |
||
405 | * @param array $attributes |
||
406 | * @param string $content |
||
407 | * @return string |
||
408 | */ |
||
409 | public function render_block( $attributes, $content ) { |
||
422 | |||
423 | /** |
||
424 | * Returns the block type name, e.g. "carbon-fields/testimonial" |
||
425 | */ |
||
426 | private function get_block_type_name() { |
||
429 | |||
430 | /** |
||
431 | * Register the block type. |
||
432 | * |
||
433 | * @return void |
||
434 | */ |
||
435 | protected function register_block() { |
||
464 | } |
||
465 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.