Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Settings UI #66

Merged
merged 13 commits into from
Apr 7, 2023
Merged
8 changes: 7 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,18 @@
},
"require-dev": {
"phpunit/phpunit": "~7.5.0",
"10up/phpcs-composer": "dev-master"
"10up/phpcs-composer": "dev-master",
"yoast/phpunit-polyfills": "^1.0"
},
"scripts": {
"lint": "phpcs .",
"lint-fix": "phpcbf .",
"test": "phpunit",
"setup-local-tests": "bash bin/install-wp-tests.sh convert_to_blocks_test root password mysql trunk"
},
"config": {
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
}
}
}
65 changes: 63 additions & 2 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions config.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
convert_to_blocks_define( 'CONVERT_TO_BLOCKS_VERSION', $plugin_version );
convert_to_blocks_define( 'CONVERT_TO_BLOCKS_DIR', plugin_dir_path( __FILE__ ) );
convert_to_blocks_define( 'CONVERT_TO_BLOCKS_URL', plugin_dir_url( __FILE__ ) );
convert_to_blocks_define( 'CONVERT_TO_BLOCKS_SLUG', 'convert-to-blocks' );

/* Labels */

Expand Down
1 change: 1 addition & 0 deletions includes/ConvertToBlocks/Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ public function init() {
$this->register_objects(
[
new RESTSupport(),
new Settings(),
]
);
}
Expand Down
261 changes: 261 additions & 0 deletions includes/ConvertToBlocks/Settings.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
<?php
/**
* Settings UI
*
* @package convert-to-blocks
*/

namespace ConvertToBlocks;

/**
* UI for configuring plugin settings.
*/
class Settings {

/**
* User permissions to manage settings.
*
* @var string
*/
private $capability = 'manage_options';

/**
* Settings page slug.
*
* @var string
*/
private $settings_page = 'settings-page';

/**
* Settings section name.
*
* @var string
*/
private $settings_section = 'settings-section';

/**
* Settings group name.
*
* @var string
*/
private $settings_group = 'settings';

/**
* Post types.
*
* @var array
*/
private $post_types = [];

/**
* Register hooks with WordPress
*/
public function register() {
// Configure variables and get post types.
$this->init();

add_action( 'admin_menu', [ $this, 'add_menu' ] );
add_action( 'admin_init', [ $this, 'register_section' ], 10 );
add_action( 'admin_init', [ $this, 'register_fields' ], 20 );

add_filter( 'post_type_supports_convert_to_blocks', [ $this, 'supported_post_types' ], PHP_INT_MAX, 2 );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using PHP_INT_MAX makes it very hard for plugins and/or themes to use this filter. I think even using the default priority is enough.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dinhtungdu I totally agree. I was myself having second thoughts about this. I'll correct this.

}

/**
* Only registers on admin context.
*/
public function can_register() {
return is_admin();
}

/**
* Configures variables and fetches post types.
*
* @return void
*/
public function init() {
// Configure variables.
$this->settings_page = sprintf( '%s-%s', CONVERT_TO_BLOCKS_SLUG, $this->settings_page );
$this->settings_section = sprintf( '%s-%s', CONVERT_TO_BLOCKS_SLUG, $this->settings_section );
$this->settings_group = sprintf( '%s_%s', CONVERT_TO_BLOCKS_SLUG, $this->settings_group );

// Get post types.
$this->post_types = $this->get_post_types();
}

/**
* Retrieves all public post types.
*
* @return array
*/
public function get_post_types() {
$post_types = get_post_types(
[ 'public' => true ]
);

if ( ! empty( $post_types['attachment'] ) ) {
unset( $post_types['attachment'] );
}

return $post_types;
}

/**
* Adds a submenu item for the `Settings` menu.
*
* @return void
*/
public function add_menu() {
add_options_page(
esc_html__( 'Convert to Blocks', 'convert-to-blocks' ),
esc_html__( 'Convert to Blocks', 'convert-to-blocks' ),
$this->capability,
CONVERT_TO_BLOCKS_SLUG,
[ $this, 'settings_page' ]
);
}

/**
* Registers the settings page.
*
* @return void
*/
public function settings_page() {
?>
<div class="wrap">
<h1>
<?php esc_html_e( 'Convert to Blocks', 'convert-to-blocks' ); ?>
</h1>
<hr>

<p>
<?php esc_html_e( 'Configure plugin by selecting the supported post types.', 'convert-to-blocks' ); ?>
</p>

<form method="post" action="options.php">
<?php
settings_fields( $this->settings_group );
do_settings_sections( CONVERT_TO_BLOCKS_SLUG );
submit_button();
?>
</form>
</div>
<?php
}

/**
* Registers section for the settings page.
*
* @return void
*/
public function register_section() {
add_settings_section(
$this->settings_section,
false,
false,
CONVERT_TO_BLOCKS_SLUG
);
}

/**
* Registers setting fields.
*
* @return void
*/
public function register_fields() {
// Supported post types.
add_settings_field(
sprintf( '%s_post_types', CONVERT_TO_BLOCKS_SLUG ),
esc_html__( 'Supported Post Types', 'convert-to-blocks' ),
[ $this, 'field_post_types' ],
CONVERT_TO_BLOCKS_SLUG,
$this->settings_section,
[
'label_for' => sprintf( '%s_post_types', CONVERT_TO_BLOCKS_SLUG ),
]
);

register_setting(
$this->settings_group,
sprintf( '%s_post_types', CONVERT_TO_BLOCKS_SLUG ),
[
'sanitize_callback' => [ $this, 'sanitize_post_types' ],
]
);
}

/**
* Renders the `post_types` field.
*
* @return void
*/
public function field_post_types() {
$post_types = get_option( sprintf( '%s_post_types', CONVERT_TO_BLOCKS_SLUG ), [] );
$output_html = '';

foreach ( $this->post_types as $post_type ) {
$output_html .= sprintf(
'<label for="%1$s"><input name="%2$s[]" type="checkbox" %3$s id="%1$s" value="%4$s"> %5$s</label> <br>',
sprintf( '%s_post_types_%s', esc_attr( CONVERT_TO_BLOCKS_SLUG ), esc_attr( $post_type ) ),
sprintf( '%s_post_types', esc_attr( CONVERT_TO_BLOCKS_SLUG ) ),
checked( in_array( $post_type, $post_types, true ), 1, false ),
esc_attr( $post_type ),
esc_attr( ucfirst( $post_type ) )
);
}
?>
<fieldset>
<?php echo $output_html; // phpcs:ignore ?>
</fieldset>
<?php
}

/**
* Sanitizes post_types values.
*
* @param array $input Array containing checked values.
*
* @return array Sanitized array.
*/
public function sanitize_post_types( $input ) {
if ( ! is_array( $input ) ) {
return [];
}

return array_map( 'sanitize_text_field', $input );
}

/**
* Adds support for supported post types to the plugin.
*
* @param bool $supports Whether the post_type is supported or not.
* @param string $post_type Post type to be be checked.
*
* @return bool
*/
public function supported_post_types( $supports, $post_type ) {
$supported_post_types = get_option( sprintf( '%s_post_types', CONVERT_TO_BLOCKS_SLUG ) );

// If the settings option does not exist in DB.
if ( false === $supported_post_types ) {
return $supports;
}

// If no post_type is selected.
if ( empty( $supported_post_types ) ) {
return false;
}

// Check if post_type is selected by the user.
if ( in_array( $post_type, $supported_post_types, true ) ) {
return true;
}

/**
* This also overrides default post_types since we have the option to de-select the
* default ones via the settings panel.
*/
return false;
}

}