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:
1 | <?php |
||
11 | class Settings extends MetaBox |
||
12 | { |
||
13 | /** |
||
14 | * @var string |
||
15 | */ |
||
16 | const ID = 'settings'; |
||
17 | |||
18 | /** |
||
19 | * @var array |
||
20 | */ |
||
21 | public static $conditions = [ |
||
22 | 'class_exists', 'defined', 'function_exists', 'hook', 'is_plugin_active', |
||
23 | 'is_plugin_inactive', |
||
24 | ]; |
||
25 | |||
26 | /** |
||
27 | * @var string |
||
28 | */ |
||
29 | public $hook; |
||
30 | |||
31 | /** |
||
32 | * @return string |
||
33 | */ |
||
34 | public static function id() |
||
35 | { |
||
36 | return apply_filters( sprintf( 'pollux/%s/id', static::ID ), Application::prefix() . static::ID ); |
||
37 | } |
||
38 | |||
39 | /** |
||
40 | * {@inheritdoc} |
||
41 | */ |
||
42 | public function init() |
||
43 | { |
||
44 | // if( empty( $this->app->config->{static::ID} ))return; |
||
|
|||
45 | // if( is_bool( $this->app->config->{static::ID} )) { |
||
46 | // $this->app->config->{static::ID} = []; |
||
47 | // } |
||
48 | |||
49 | // @todo: run GateKeeper to check dependencies and capability (make sure it it run on the correct hook!) |
||
50 | // if( !is_plugin_active( 'meta-box/meta-box.php' ))return; |
||
51 | |||
52 | $this->normalize( $this->app->config->{static::ID} ); |
||
53 | |||
54 | add_action( 'pollux/'.static::ID.'/init', [$this, 'addSubmitMetaBox'] ); |
||
55 | add_action( 'current_screen', [$this, 'register'] ); |
||
56 | add_action( 'admin_menu', [$this, 'registerPage'] ); |
||
57 | add_action( 'admin_menu', [$this, 'registerSetting'] ); |
||
58 | add_action( 'pollux/'.static::ID.'/init', [$this, 'resetPage'] ); |
||
59 | add_action( 'admin_print_footer_scripts', [$this, 'renderFooterScript'] ); |
||
60 | add_filter( 'pollux/'.static::ID.'/instruction', [$this, 'filterInstruction'], 10, 3 ); |
||
61 | add_filter( 'pollux/'.static::ID.'/before/instructions', [$this, 'filterBeforeInstructions'] ); |
||
62 | } |
||
63 | |||
64 | /** |
||
65 | * @return void |
||
66 | * @action pollux/{static::ID}/init |
||
67 | */ |
||
68 | public function addSubmitMetaBox() |
||
69 | { |
||
70 | call_user_func_array( 'add_meta_box', $this->filter( 'metabox/submit', [ |
||
71 | 'submitdiv', |
||
72 | __( 'Save Settings', 'pollux' ), |
||
73 | [$this, 'renderSubmitMetaBox'], |
||
74 | $this->hook, |
||
75 | 'side', |
||
76 | 'high', |
||
77 | ])); |
||
78 | } |
||
79 | |||
80 | /** |
||
81 | * @return string |
||
82 | * @filter pollux/{static::ID}/before/instructions |
||
83 | */ |
||
84 | public function filterBeforeInstructions() |
||
85 | { |
||
86 | return '<pre class="my-sites nav-tab-active misc-pub-section">SiteMeta::all();</pre>'; |
||
87 | } |
||
88 | |||
89 | /** |
||
90 | * @param string $instruction |
||
91 | * @return string |
||
92 | * @action pollux/{static::ID}/instruction |
||
93 | */ |
||
94 | public function filterInstruction( $instruction, array $field, array $metabox ) |
||
95 | { |
||
96 | return sprintf( "SiteMeta::%s('%s');", $metabox['slug'], $field['slug'] ); |
||
97 | } |
||
98 | |||
99 | /** |
||
100 | * @param null|array $settings |
||
101 | * @return array |
||
102 | * @callback register_setting |
||
103 | */ |
||
104 | public function filterSavedSettings( $settings ) |
||
105 | { |
||
106 | if( is_null( $settings )) { |
||
107 | $settings = []; |
||
108 | } |
||
109 | return $this->filter( 'save', array_merge( $this->getSettings(), $settings )); |
||
110 | } |
||
111 | |||
112 | /** |
||
113 | * @param string $key |
||
114 | * @param mixed $fallback |
||
115 | * @param string $group |
||
116 | * @return string|array |
||
117 | */ |
||
118 | public function getMetaValue( $key, $fallback = '', $group = '' ) |
||
119 | { |
||
120 | return SiteMeta::get( $group, $key, $fallback ); |
||
121 | } |
||
122 | |||
123 | /** |
||
124 | * @return void |
||
125 | * @action current_screen |
||
126 | */ |
||
127 | public function register() |
||
128 | { |
||
129 | if(( new Helper )->getCurrentScreen()->id != $this->hook )return; |
||
130 | foreach( parent::register() as $metabox ) { |
||
131 | new RWMetaBox( $metabox, static::ID, $this ); |
||
132 | } |
||
133 | add_screen_option( 'layout_columns', [ |
||
134 | 'max' => 2, |
||
135 | 'default' => 2, |
||
136 | ]); |
||
137 | $this->action( 'init' ); |
||
138 | } |
||
139 | |||
140 | /** |
||
141 | * @return void |
||
142 | * @action admin_menu |
||
143 | */ |
||
144 | public function registerPage() |
||
145 | { |
||
146 | $this->hook = call_user_func_array( 'add_menu_page', $this->filter( 'page', [ |
||
147 | __( 'Site Settings', 'pollux' ), |
||
148 | __( 'Site Settings', 'pollux' ), |
||
149 | 'edit_theme_options', |
||
150 | static::id(), |
||
151 | [$this, 'renderPage'], |
||
152 | 'dashicons-screenoptions', |
||
153 | 1313 |
||
154 | ])); |
||
155 | } |
||
156 | |||
157 | /** |
||
158 | * @return void |
||
159 | * @action admin_menu |
||
160 | */ |
||
161 | public function registerSetting() |
||
162 | { |
||
163 | register_setting( static::id(), static::id(), [$this, 'filterSavedSettings'] ); |
||
164 | } |
||
165 | |||
166 | /** |
||
167 | * @return void |
||
168 | * @action admin_print_footer_scripts |
||
169 | */ |
||
170 | public function renderFooterScript() |
||
171 | { |
||
172 | if(( new Helper )->getCurrentScreen()->id != $this->hook )return; |
||
173 | $this->app->render( 'settings/script', [ |
||
174 | 'confirm' => __( 'Are you sure want to do this?', 'pollux' ), |
||
175 | 'hook' => $this->hook, |
||
176 | 'id' => static::id(), |
||
177 | ]); |
||
178 | } |
||
179 | |||
180 | /** |
||
181 | * @return void |
||
182 | * @callback add_menu_page |
||
183 | */ |
||
184 | public function renderPage() |
||
185 | { |
||
186 | $this->app->render( 'settings/index', [ |
||
187 | 'columns' => get_current_screen()->get_columns(), |
||
188 | 'heading' => __( 'Site Settings', 'pollux' ), |
||
189 | 'id' => static::id(), |
||
190 | ]); |
||
191 | } |
||
192 | |||
193 | /** |
||
194 | * @return void |
||
195 | * @callback add_meta_box |
||
196 | */ |
||
197 | public function renderSubmitMetaBox() |
||
198 | { |
||
199 | global $pagenow; |
||
200 | $query = [ |
||
201 | '_wpnonce' => wp_create_nonce( $this->hook ), |
||
202 | 'action' => 'reset', |
||
203 | 'page' => static::id(), |
||
204 | ]; |
||
205 | $this->app->render( 'settings/submit', [ |
||
206 | 'reset' => __( 'Reset all', 'pollux' ), |
||
207 | 'reset_url' => esc_url( add_query_arg( $query, admin_url( $pagenow ))), |
||
208 | 'submit' => get_submit_button( __( 'Save', 'pollux' ), 'primary', 'submit', false ), |
||
209 | ]); |
||
210 | } |
||
211 | |||
212 | /** |
||
213 | * @return void |
||
214 | * @action pollux/{static::ID}/init |
||
215 | */ |
||
216 | View Code Duplication | public function resetPage() |
|
217 | { |
||
218 | if( filter_input( INPUT_GET, 'page' ) !== static::id() |
||
219 | || filter_input( INPUT_GET, 'action' ) !== 'reset' |
||
220 | )return; |
||
221 | if( wp_verify_nonce( filter_input( INPUT_GET, '_wpnonce' ), $this->hook )) { |
||
222 | update_option( static::id(), $this->getDefaults() ); |
||
223 | add_settings_error( static::id(), 'reset', __( 'Reset successful.', 'pollux' ), 'updated' ); |
||
224 | } |
||
225 | else { |
||
226 | add_settings_error( static::id(), 'failed', __( 'Failed to reset. Please try again.', 'pollux' )); |
||
227 | } |
||
228 | set_transient( 'settings_errors', get_settings_errors(), 30 ); |
||
229 | wp_safe_redirect( add_query_arg( 'settings-updated', 'true', wp_get_referer() )); |
||
230 | exit; |
||
231 | } |
||
232 | |||
233 | /** |
||
234 | * @param string $key |
||
235 | * @return array |
||
236 | */ |
||
237 | protected function filterArrayByKey( array $array, $key ) |
||
238 | { |
||
239 | return array_filter( $array, function( $value ) use( $key ) { |
||
240 | return !empty( $value[$key] ); |
||
241 | }); |
||
242 | } |
||
243 | |||
244 | /** |
||
245 | * @return array |
||
246 | */ |
||
247 | protected function getDefaults() |
||
248 | { |
||
249 | $metaboxes = $this->filterArrayByKey( $this->metaboxes, 'slug' ); |
||
250 | |||
251 | array_walk( $metaboxes, function( &$metabox ) { |
||
252 | $fields = array_map( function( $field ) { |
||
253 | $field = wp_parse_args( $field, ['std' => ''] ); |
||
254 | return [$field['slug'] => $field['std']]; |
||
255 | }, $this->filterArrayByKey( $metabox['fields'], 'slug' )); |
||
256 | $metabox = [ |
||
257 | $metabox['slug'] => call_user_func_array( 'array_merge', $fields ), |
||
258 | ]; |
||
259 | }); |
||
260 | return call_user_func_array( 'array_merge', $metaboxes ); |
||
261 | } |
||
262 | |||
263 | protected function getSettings() |
||
264 | { |
||
265 | return (array) SiteMeta::all(); |
||
266 | } |
||
267 | |||
268 | /** |
||
269 | * @param string $name |
||
270 | * @param string $parentId |
||
271 | * @return string |
||
272 | */ |
||
273 | protected function normalizeFieldName( $name, array $data, $parentId ) |
||
274 | { |
||
275 | return sprintf( '%s[%s][%s]', static::id(), $parentId, $data['slug'] ); |
||
276 | } |
||
277 | |||
278 | /** |
||
279 | * @param string $id |
||
280 | * @param string $parentId |
||
281 | * @return string |
||
282 | */ |
||
283 | protected function normalizeId( $id, array $data, $parentId ) |
||
289 | } |
||
290 |
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.