From b42daa31d836c3781bbbf46997c70551ba989988 Mon Sep 17 00:00:00 2001 From: Jonny Bull Date: Mon, 20 Sep 2021 10:28:52 +0100 Subject: [PATCH] WP CLI support --- flagpole.php | 10 ++ includes/class-cli.php | 300 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 310 insertions(+) create mode 100644 includes/class-cli.php diff --git a/flagpole.php b/flagpole.php index ad35169..0af786f 100755 --- a/flagpole.php +++ b/flagpole.php @@ -25,6 +25,7 @@ } use Flagpole\Flagpole; +use Flagpole\CLI; // Define plugin paths and url for global usage. define( 'FLAGPOLE_PLUGIN_PATH', plugin_dir_path( __FILE__ ) ); @@ -100,6 +101,10 @@ function flagpole_admin_imports( $hook ) { require plugin_dir_path( __FILE__ ) . 'includes/api/api.general.php'; require plugin_dir_path( __FILE__ ) . 'includes/api/api.shortcode.php'; +if ( defined( '\WP_CLI' ) && \WP_CLI ) { + require_once( plugin_dir_path( __FILE__ ) . 'includes/class-cli.php' ); +} + /** * AJAX Action toggling features from the WP admin area. */ @@ -338,3 +343,8 @@ function flagpole_operation_redirect( $error_code = false, $redirect = true ) { add_shortcode( 'debugFlagpole_flags', 'flagpole_shortcode_debug_flags' ); add_shortcode( 'debugFlagpole_groups', 'flagpole_shortcode_debug_groups' ); add_shortcode( 'debugFlagpole_db', 'flagpole_shortcode_debug_db' ); + +if ( defined( '\WP_CLI' ) && \WP_CLI ) { + $flagpole_cli = new CLI(); + $flagpole_cli->register(); +} diff --git a/includes/class-cli.php b/includes/class-cli.php new file mode 100644 index 0000000..417eb65 --- /dev/null +++ b/includes/class-cli.php @@ -0,0 +1,300 @@ + $flag_value ) { + $encoded_data[ $flag_value->get_key( false ) ] = [ + 'key' => $flag_value->get_key( false ), + 'name' => $flag_value->get_name( false ), + 'description' => $flag_value->get_description( false ), + 'label' => $flag_value->get_label( false ), + 'activated' => $flag_value->is_enabled() ? $true_val : $false_val, + 'stable' => $flag_value->is_stable( false ) ? $true_val : $false_val, + 'enforced' => $flag_value->get_enforced() ? $true_val : $false_val, + 'private' => $false_val + ]; + } + + return $encoded_data; + } + + /** + * Lists all registered flags. + * + * ## OPTIONS + * + * + * : The type of table to display. + * default: table + * options: + * - csv + * - json + * - table + * - yaml + * + * ## EXAMPLES + * + * wp flagpole list + * wp flagpole list csv + * + */ + public function flag_list( $args ) { + /** + * @todo switch to associated arguments only. + * @todo filter by group/label. + * @todo filter by on/off. + * @todo filter fields to return. + */ + + // We don't support the 'ids' or 'count' types, as there's no real benefit to them here. + $render_types = [ + 'table', + 'csv', + 'json', + 'yaml', + ]; + + $render_type = 'table'; + + if ( $args !== [] and in_array( $args[0], $render_types, true ) ) { + $render_type = $args[0]; + } + + $available_flags = Flagpole::init()->get_flags(); + + $fields_to_display = [ + 'key', + 'name', + 'description', + 'label', + 'stable', + 'activated', + 'enforced', + 'private', + ]; + + $bool_type = 'boolean'; + + if ( 'table' === $render_type ) { + $bool_type = 'string'; + } + + $available_flags = $this->flag_list_data_encode( $available_flags, $bool_type ); + + $enabled_flags = array_filter( $available_flags, [ $this, 'flag_filter_enabled' ] ); + + WP_CLI::line( 'Flags: ' . count( $available_flags ) . ' registered. ' . count( $enabled_flags ) . ' enabled.' ); + WP_CLI::line(); + + if ( count( $available_flags ) > 0 ) { + WP_CLI\Utils\format_items( $render_type, $available_flags, $fields_to_display ); + WP_CLI::line(); + } + } + + /** + * Activates any given flag or a comma separated list of flags. + * If any given flag is already active, its state is not changed. + * + * ## OPTIONS + * + * + * : The key of the flag to activate. This can be a comma separated list for multiple flags. + * + * ## EXAMPLES + * + * wp flagpole activate my-example-flag + * wp flagpole activate my-example-flag,my-other-example-flag + * wp flagpole on my-example-flag + * + * @alias on + */ + public function flag_on( $args ) { + if ( $args == [] ) { + WP_CLI::error( 'Flag not provided' ); + return; + } + + if ( $args[0] ) { + if ( strpos( $args[0], ',' ) > 0 ) { + $flags = explode( ',', $args[0] ); + } else { + $flags = [ $args[0] ]; + } + + foreach( $flags as $flag ) { + if ( true === $this->flag_exists_and_has_state( $flag, true ) ) { + Flagpole::init()->toggle_feature_publication( $flag ); + WP_CLI::success( $flag . ' activated.' ); + } + } + return; + } + } + + /** + * Deactivates any given flag or a comma separated list of flags. + * If any given flag is already deactivated, its state is not changed. + * + * ## OPTIONS + * + * + * : The key of the flag to activate. This can be a comma separated list for multiple flags. + * + * ## EXAMPLES + * + * wp flagpole deactivate my-example-flag + * wp flagpole deactivate my-example-flag,my-other-example-flag + * wp flagpole off my-example-flag + * + * @alias off + */ + public function flag_off( $args ) { + if ( $args == [] ) { + WP_CLI::error( 'Flag not provided' ); + return; + } + + if ( $args[0] ) { + if ( strpos( $args[0], ',' ) > 0 ) { + $flags = explode( ',', $args[0] ); + } else { + $flags = [ $args[0] ]; + } + + foreach( $flags as $flag ) { + if ( true === $this->flag_exists_and_has_state( $flag, false ) ) { + Flagpole::init()->toggle_feature_publication( $flag ); + WP_CLI::success( $flag . ' deactivated.' ); + } + } + } + } + + /** + * Toggles any given flag or a comma separated list of flags. + * + * ## OPTIONS + * + * + * : The key of the flag to toggle. This can be a comma separated list for multiple flags. + * + * ## EXAMPLES + * + * wp flagpole toggle my-example-flag + * wp flagpole toggle my-example-flag,my-other-example-flag + * + */ + public function flag_toggle( $args ) { + if ( $args == [] ) { + WP_CLI::error( 'Flag not provided' ); + return; + } + + if ( $args[0] ) { + if ( strpos( $args[0], ',' ) > 0 ) { + $flags = explode( ',', $args[0] ); + } else { + $flags = [ $args[0] ]; + } + + foreach( $flags as $flag ) { + $query_flag = Flagpole::init()->find_flag( $flag ); + $is_currently_enabled = $query_flag->is_enabled(); + + Flagpole::init()->toggle_feature_publication( $flag ); + if ( true === $is_currently_enabled ) { + WP_CLI::success( $flag . ' deactivated.' ); + } else { + WP_CLI::success( $flag . ' activated.' ); + } + } + } + } + + /** + * Helper functions. + */ + + /** + * Looks up a flag, checks if it exists and is of a given state. + * + * @param string $flag Name of the flag. + * @param boolean $activated Whether the flag is activated or deactivated. + * @return void + */ + function flag_exists_and_has_state ( $flag, $activated = true ) { + $query_flag = Flagpole::init()->find_flag( $flag ); + + if ( false === $query_flag ) { + WP_CLI::error( $flag . ' is not a registered flag' ); + return false; + } + + if ( true === $activated && true === $query_flag->is_enabled() ) { + WP_CLI::success( $flag . ' is already active.' ); + return false; + } + + if ( false === $activated && false === $query_flag->is_enabled() ) { + WP_CLI::success( $flag . ' is already deactive.' ); + return false; + } + + return true; + } +}