Complex classes like WPSC_Settings_Page 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 WPSC_Settings_Page, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 175 | final class WPSC_Settings_Page { |
||
| 176 | /** |
||
| 177 | * @staticvar object The active object instance |
||
| 178 | * @since 3.8.8 |
||
| 179 | * @access private |
||
| 180 | */ |
||
| 181 | private static $instance; |
||
| 182 | |||
| 183 | /** |
||
| 184 | * @staticvar array An array of default tabs containing pairs of id => title |
||
| 185 | * @since 3.8.8 |
||
| 186 | * @access private |
||
| 187 | */ |
||
| 188 | private static $default_tabs; |
||
| 189 | |||
| 190 | /** |
||
| 191 | * Initialize default tabs and add necessary action hooks. |
||
| 192 | * |
||
| 193 | * @since 3.8.8 |
||
| 194 | * |
||
| 195 | * @uses add_action() Attaches to wpsc_register_settings_tabs hook |
||
| 196 | * @uses add_action() Attaches to wpsc_load_settings_tab_class hook |
||
| 197 | * |
||
| 198 | * @see wpsc_load_settings_page() |
||
| 199 | * |
||
| 200 | * @access public |
||
| 201 | * @static |
||
| 202 | */ |
||
| 203 | public static function init() { |
||
| 204 | self::$default_tabs = array( |
||
| 205 | 'general' => _x( 'General' , 'General settings tab in Settings->Store page' , 'wp-e-commerce' ), |
||
| 206 | 'admin' => _x( 'Admin' , 'Admin settings tab in Settings->Store page' , 'wp-e-commerce' ), |
||
| 207 | 'taxes' => _x( 'Taxes' , 'Taxes settings tab in Settings->Store page' , 'wp-e-commerce' ), |
||
| 208 | 'shipping' => _x( 'Shipping' , 'Shipping settings tab in Settings->Store page' , 'wp-e-commerce' ), |
||
| 209 | 'gateway' => _x( 'Payments' , 'Payments settings tab in Settings->Store page' , 'wp-e-commerce' ), |
||
| 210 | 'checkout' => _x( 'Checkout' , 'Checkout settings tab in Settings->Store page' , 'wp-e-commerce' ), |
||
| 211 | 'marketing' => _x( 'Marketing' , 'Marketing settings tab in Settings->Store page' , 'wp-e-commerce' ), |
||
| 212 | 'import' => _x( 'Import' , 'Import settings tab in Settings->Store page' , 'wp-e-commerce' ) |
||
| 213 | ); |
||
| 214 | |||
| 215 | add_action( 'wpsc_register_settings_tabs' , array( 'WPSC_Settings_Page', 'register_default_tabs' ), 1 ); |
||
| 216 | add_action( 'wpsc_load_settings_tab_class', array( 'WPSC_Settings_Page', 'load_default_tab_class' ), 1 ); |
||
| 217 | } |
||
| 218 | |||
| 219 | /** |
||
| 220 | * Get active object instance |
||
| 221 | * |
||
| 222 | * @since 3.8.8 |
||
| 223 | * |
||
| 224 | * @access public |
||
| 225 | * @static |
||
| 226 | * @return object |
||
| 227 | */ |
||
| 228 | public static function get_instance() { |
||
| 229 | if ( ! self::$instance ) { |
||
| 230 | self::$instance = new WPSC_Settings_Page(); |
||
| 231 | } |
||
| 232 | |||
| 233 | return self::$instance; |
||
| 234 | } |
||
| 235 | |||
| 236 | /** |
||
| 237 | * Automatically load tab classes inside wpsc-admin/includes/settings-tabs. |
||
| 238 | * |
||
| 239 | * @since 3.8.8 |
||
| 240 | * |
||
| 241 | * @see WPSC_Settings_Page::init() |
||
| 242 | * |
||
| 243 | * @uses WPSC_Settings_Page::get_current_tab_id() Gets current tab ID |
||
| 244 | * |
||
| 245 | * @access public |
||
| 246 | * @param object $page_instance The WPSC_Settings_Page instance |
||
| 247 | * @static |
||
| 248 | */ |
||
| 249 | public static function load_default_tab_class( $page_instance ) { |
||
| 250 | $current_tab_id = $page_instance->get_current_tab_id(); |
||
| 251 | if ( array_key_exists( $current_tab_id, self::$default_tabs ) ) { |
||
| 252 | require_once( 'includes/settings-tabs/' . $current_tab_id . '.php' ); |
||
| 253 | } |
||
| 254 | } |
||
| 255 | |||
| 256 | /** |
||
| 257 | * Register the default tabs' ids and titles. |
||
| 258 | * |
||
| 259 | * @since 3.8.8 |
||
| 260 | * |
||
| 261 | * @see WPSC_Settings_Page::init() |
||
| 262 | * |
||
| 263 | * @uses WPSC_Settings_Page::register_tab() Registers default tabs' idds and titles. |
||
| 264 | * |
||
| 265 | * @access public |
||
| 266 | * @param object $page_instance The WPSC_Settings_Page instance |
||
| 267 | * @static |
||
| 268 | */ |
||
| 269 | public static function register_default_tabs( $page_instance ) { |
||
| 270 | foreach ( self::$default_tabs as $id => $title ) { |
||
| 271 | $page_instance->register_tab( $id, $title ); |
||
| 272 | } |
||
| 273 | } |
||
| 274 | |||
| 275 | /** |
||
| 276 | * Current tab ID |
||
| 277 | * @since 3.8.8 |
||
| 278 | * @access private |
||
| 279 | * @var string |
||
| 280 | */ |
||
| 281 | private $current_tab_id; |
||
| 282 | |||
| 283 | /** |
||
| 284 | * Current tab object |
||
| 285 | * @since 3.8.8 |
||
| 286 | * @access private |
||
| 287 | * @var object |
||
| 288 | */ |
||
| 289 | private $current_tab; |
||
| 290 | |||
| 291 | /** |
||
| 292 | * An array containing registered tabs |
||
| 293 | * @since 3.8.8 |
||
| 294 | * @access private |
||
| 295 | * @var array |
||
| 296 | */ |
||
| 297 | private $tabs; |
||
| 298 | |||
| 299 | /** |
||
| 300 | * Constructor |
||
| 301 | * |
||
| 302 | * @since 3.8.8 |
||
| 303 | * |
||
| 304 | * @uses do_action() Calls wpsc_register_settings_tabs hook. |
||
| 305 | * @uses apply_filters Calls wpsc_settings_tabs hook. |
||
| 306 | * @uses WPSC_Settings_Page::set_current_tab() Set current tab to the specified ID |
||
| 307 | * |
||
| 308 | * @access public |
||
| 309 | * @param string $tab_id Optional. If specified then the current tab will be set to this ID. |
||
| 310 | */ |
||
| 311 | public function __construct( $tab_id = null ) { |
||
| 312 | do_action( 'wpsc_register_settings_tabs', $this ); |
||
| 313 | $this->tabs = apply_filters( 'wpsc_settings_tabs', $this->tabs ); |
||
| 314 | $this->set_current_tab( $tab_id ); |
||
| 315 | } |
||
| 316 | |||
| 317 | /** |
||
| 318 | * Returns the current tab object |
||
| 319 | * |
||
| 320 | * @since 3.8.8 |
||
| 321 | * |
||
| 322 | * @uses do_action() Calls wpsc_load_settings_tab_class hook. |
||
| 323 | * @uses WPSC_Settings_Tab() constructing a new settings tab object |
||
| 324 | * |
||
| 325 | * @access public |
||
| 326 | * @return object WPSC_Settings_Tab object |
||
| 327 | */ |
||
| 328 | public function get_current_tab() { |
||
| 329 | if ( ! $this->current_tab ) { |
||
| 330 | do_action( 'wpsc_load_settings_tab_class', $this ); |
||
| 331 | $class_name = ucwords( str_replace( array( '-', '_' ), ' ', $this->current_tab_id ) ); |
||
| 332 | $class_name = str_replace( ' ', '_', $class_name ); |
||
| 333 | $class_name = 'WPSC_Settings_Tab_' . $class_name; |
||
| 334 | if ( class_exists( $class_name ) ) { |
||
| 335 | $reflection = new ReflectionClass( $class_name ); |
||
| 336 | $this->current_tab = $reflection->newInstance(); |
||
| 337 | } |
||
| 338 | } |
||
| 339 | |||
| 340 | return $this->current_tab; |
||
| 341 | } |
||
| 342 | |||
| 343 | /** |
||
| 344 | * Get current tab ID |
||
| 345 | * @since 3.8.8 |
||
| 346 | * @access public |
||
| 347 | * @return string |
||
| 348 | */ |
||
| 349 | public function get_current_tab_id() { |
||
| 352 | |||
| 353 | /** |
||
| 354 | * Set current tab to the specified tab ID. |
||
| 355 | * |
||
| 356 | * @since 3.8.8 |
||
| 357 | * |
||
| 358 | * @uses check_admin_referer() Prevent CSRF |
||
| 359 | * @uses WPSC_Settings_Page::get_current_tab() Initializes the current tab object. |
||
| 360 | * @uses WPSC_Settings_Page::save_options() Saves the submitted options to the database. |
||
| 361 | * @uses WPSC_Settings_Tab::callback_submit_options() If this method exists in the tab object, it will be called after WPSC_Settings_Page::save_options(). |
||
| 362 | * |
||
| 363 | * @access public |
||
| 364 | * @param string $tab_id Optional. The Tab ID. If this is not specified, the $_GET['tab'] variable will be used. If that variable also does not exists, the first tab will be used. |
||
| 365 | */ |
||
| 366 | public function set_current_tab( $tab_id = null ) { |
||
| 367 | if ( ! $tab_id ) { |
||
| 368 | $tabs = array_keys( $this->tabs ); |
||
| 369 | |||
| 370 | if ( isset( $_GET['tab'] ) && array_key_exists( $_GET['tab'], $this->tabs ) ) |
||
| 371 | $this->current_tab_id = $_GET['tab']; |
||
| 372 | else |
||
| 373 | $this->current_tab_id = array_shift( $tabs ); |
||
| 374 | |||
| 375 | } else { |
||
| 376 | $this->current_tab_id = $tab_id; |
||
| 377 | } |
||
| 378 | |||
| 379 | $this->current_tab = $this->get_current_tab(); |
||
| 380 | |||
| 381 | if ( isset( $_REQUEST['wpsc_admin_action'] ) && ( $_REQUEST['wpsc_admin_action'] == 'submit_options' ) ) { |
||
| 382 | check_admin_referer( 'update-options', 'wpsc-update-options' ); |
||
| 383 | |||
| 384 | $this->save_options(); |
||
| 385 | do_action( 'wpsc_save_' . $this->current_tab_id . '_settings', $this->current_tab ); |
||
| 386 | |||
| 387 | $query_args = array(); |
||
| 388 | if ( is_callable( array( $this->current_tab, 'callback_submit_options' ) ) ) { |
||
| 389 | $additional_query_args = $this->current_tab->callback_submit_options(); |
||
| 390 | if ( ! empty( $additional_query_args ) ) |
||
| 391 | $query_args += $additional_query_args; |
||
| 392 | } |
||
| 393 | if ( $this->current_tab->is_update_message_displayed() ) { |
||
| 394 | if ( ! count( get_settings_errors() ) ) |
||
| 395 | add_settings_error( 'wpsc-settings', 'settings_updated', __( 'Settings saved.', 'wp-e-commerce' ), 'updated' ); |
||
| 396 | set_transient( 'settings_errors', get_settings_errors(), 30 ); |
||
| 397 | $query_args['settings-updated'] = true; |
||
| 398 | } |
||
| 399 | wp_redirect( esc_url_raw( add_query_arg( $query_args ) ) ); |
||
| 400 | exit; |
||
| 401 | } |
||
| 402 | } |
||
| 403 | |||
| 404 | /** |
||
| 405 | * Register a tab's ID and title |
||
| 406 | * |
||
| 407 | * @since 3.8.8 |
||
| 408 | * |
||
| 409 | * @access public |
||
| 410 | * @param string $id Tab ID. |
||
| 411 | * @param string $title Tab title. |
||
| 412 | */ |
||
| 413 | public function register_tab( $id, $title ) { |
||
| 416 | |||
| 417 | /** |
||
| 418 | * Get an array containing tabs' IDs and titles |
||
| 419 | * |
||
| 420 | * @since 3.8.8 |
||
| 421 | * |
||
| 422 | * @access public |
||
| 423 | * @return array |
||
| 424 | */ |
||
| 425 | public function get_tabs() { |
||
| 428 | |||
| 429 | /** |
||
| 430 | * Get the HTML class of a tab. |
||
| 431 | * @since 3.8.8 |
||
| 432 | * @param string $id Tab ID |
||
| 433 | * @return string |
||
| 434 | */ |
||
| 435 | private function tab_class( $id ) { |
||
| 441 | |||
| 442 | /** |
||
| 443 | * Get the form's submit (action) url. |
||
| 444 | * @since 3.8.8 |
||
| 445 | * @access private |
||
| 446 | * @return string |
||
| 447 | */ |
||
| 448 | private function submit_url() { |
||
| 453 | |||
| 454 | /** |
||
| 455 | * Output HTML of tab navigation. |
||
| 456 | * @since 3.8.8 |
||
| 457 | * @access public |
||
| 458 | * @uses esc_html Prevents xss |
||
| 459 | */ |
||
| 460 | public function output_tabs() { |
||
| 469 | |||
| 470 | /** |
||
| 471 | * Display the current tab. |
||
| 472 | * @since 3.8.8 |
||
| 473 | * @uses do_action() Calls wpsc_{$current_tab_id}_settings_page hook. |
||
| 474 | * @uses WPSC_Settings_Tab::display() Displays the tab. |
||
| 475 | * @access public |
||
| 476 | */ |
||
| 477 | public function display_current_tab() { |
||
| 497 | |||
| 498 | /** |
||
| 499 | * Display the settings page. |
||
| 500 | * @since 3.8.8 |
||
| 501 | * @uses esc_html_e() Sanitize HTML |
||
| 502 | * @uses esc_attr() Sanitize HTML attributes |
||
| 503 | * @uses wp_nonce_field() Prevent CSRF |
||
| 504 | * @uses WPSC_Settings_Page::output_tabs() Display tab navigation. |
||
| 505 | * @uses WPSC_Settings_Page::display_current_tab() Display current tab. |
||
| 506 | * @access public |
||
| 507 | */ |
||
| 508 | public function display() { |
||
| 537 | |||
| 538 | /** |
||
| 539 | * Save submitted options to the database. |
||
| 540 | * @since 3.8.8 |
||
| 541 | * @uses check_admin_referer() Prevents CSRF. |
||
| 542 | * @uses update_option() Saves options to the database. |
||
| 543 | * @uses wpdb::query() Queries the database. |
||
| 544 | * @uses wpdb::get_col() Queries the database. |
||
| 545 | * @access public |
||
| 546 | */ |
||
| 547 | private function save_options( $selected = '' ) { |
||
| 730 | } |
||
| 731 | |||
| 742 |
For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a
@returndoc comment to communicate to implementors of these methods what they are expected to return.