!C99Shell v. 2.5 [PHP 8 Update] [24.05.2025]!

Software: Apache. PHP/8.3.27 

uname -a: Linux pdx1-shared-a4-04 6.6.104-grsec-jammy+ #3 SMP Tue Sep 16 00:28:11 UTC 2025 x86_64 

uid=6659440(dh_z2jmpm) gid=2086089(pg10499364) groups=2086089(pg10499364)  

Safe-mode: OFF (not secure)

/usr/local/wp/vendor/wp-cli/scaffold-command/src/   drwxr-xr-x
Free 719.92 GB of 879.6 GB (81.85%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Self remove    Logout    


Viewing file:     Scaffold_Command.php (37.43 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php

use WP_CLI\Utils;
use WP_CLI\Inflector;

/**
 * Generates code for post types, taxonomies, plugins, child themes, etc.
 *
 * ## EXAMPLES
 *
 *     # Generate a new plugin with unit tests.
 *     $ wp scaffold plugin sample-plugin
 *     Success: Created plugin files.
 *     Success: Created test files.
 *
 *     # Generate theme based on _s.
 *     $ wp scaffold _s sample-theme --theme_name="Sample Theme" --author="John Doe"
 *     Success: Created theme 'Sample Theme'.
 *
 *     # Generate code for post type registration in given theme.
 *     $ wp scaffold post-type movie --label=Movie --theme=simple-life
 *     Success: Created '/var/www/example.com/public_html/wp-content/themes/simple-life/post-types/movie.php'.
 *
 * @package wp-cli
 */
class Scaffold_Command extends WP_CLI_Command {

    /**
     * Generates PHP code for registering a custom post type.
     *
     * ## OPTIONS
     *
     * <slug>
     * : The internal name of the post type.
     *
     * [--label=<label>]
     * : The text used to translate the update messages.
     *
     * [--textdomain=<textdomain>]
     * : The textdomain to use for the labels.
     *
     * [--dashicon=<dashicon>]
     * : The dashicon to use in the menu.
     *
     * [--theme]
     * : Create a file in the active theme directory, instead of sending to
     * STDOUT. Specify a theme with `--theme=<theme>` to have the file placed in that theme.
     *
     * [--plugin=<plugin>]
     * : Create a file in the given plugin's directory, instead of sending to STDOUT.
     *
     * [--raw]
     * : Just generate the `register_post_type()` call and nothing else.
     *
     * [--force]
     * : Overwrite files that already exist.
     *
     * ## EXAMPLES
     *
     *     # Generate a 'movie' post type for the 'simple-life' theme
     *     $ wp scaffold post-type movie --label=Movie --theme=simple-life
     *     Success: Created '/var/www/example.com/public_html/wp-content/themes/simple-life/post-types/movie.php'.
     *
     * @subcommand post-type
     *
     * @alias      cpt
     */
    public function post_type( $args, $assoc_args ) {

        if ( strlen( $args[0] ) > 20 ) {
            WP_CLI::error( 'Post type slugs cannot exceed 20 characters in length.' );
        }

        $defaults = [
            'textdomain' => '',
            'dashicon'   => 'admin-post',
        ];

        $templates = [
            'post_type.mustache',
            'post_type_extended.mustache',
        ];

        $this->scaffold( $args[0], $assoc_args, $defaults, '/post-types/', $templates );
    }

    /**
     * Generates PHP code for registering a custom taxonomy.
     *
     * ## OPTIONS
     *
     * <slug>
     * : The internal name of the taxonomy.
     *
     * [--post_types=<post-types>]
     * : Post types to register for use with the taxonomy.
     *
     * [--label=<label>]
     * : The text used to translate the update messages.
     *
     * [--textdomain=<textdomain>]
     * : The textdomain to use for the labels.
     *
     * [--theme]
     * : Create a file in the active theme directory, instead of sending to
     * STDOUT. Specify a theme with `--theme=<theme>` to have the file placed in that theme.
     *
     * [--plugin=<plugin>]
     * : Create a file in the given plugin's directory, instead of sending to STDOUT.
     *
     * [--raw]
     * : Just generate the `register_taxonomy()` call and nothing else.
     *
     * [--force]
     * : Overwrite files that already exist.
     *
     * ## EXAMPLES
     *
     *     # Generate PHP code for registering a custom taxonomy and save in a file
     *     $ wp scaffold taxonomy venue --post_types=event,presentation > taxonomy.php
     *
     * @subcommand taxonomy
     *
     * @alias      tax
     */
    public function taxonomy( $args, $assoc_args ) {
        $defaults = [
            'textdomain' => '',
            'post_types' => "'post'",
        ];

        if ( isset( $assoc_args['post_types'] ) ) {
            $assoc_args['post_types'] = $this->quote_comma_list_elements( $assoc_args['post_types'] );
        }

        $templates = [
            'taxonomy.mustache',
            'taxonomy_extended.mustache',
        ];

        $this->scaffold( $args[0], $assoc_args, $defaults, '/taxonomies/', $templates );
    }

    private function scaffold( $slug, $assoc_args, $defaults, $subdir, $templates ) {
        $wp_filesystem = $this->init_wp_filesystem();

        $control_defaults = [
            'label'  => preg_replace( '/_|-/', ' ', strtolower( $slug ) ),
            'theme'  => false,
            'plugin' => false,
            'raw'    => false,
        ];
        $control_args     = $this->extract_args( $assoc_args, $control_defaults );

        $vars = $this->extract_args( $assoc_args, $defaults );

        $dashicon = $this->extract_dashicon( $assoc_args );
        if ( $dashicon ) {
            $vars['dashicon'] = $dashicon;
        }

        $vars['slug'] = $slug;

        $vars['textdomain'] = $this->get_textdomain( $vars['textdomain'], $control_args );

        $vars['label'] = $control_args['label'];

        $vars['label_ucfirst']        = ucfirst( $vars['label'] );
        $vars['label_plural']         = $this->pluralize( $vars['label'] );
        $vars['label_plural_ucfirst'] = ucfirst( $vars['label_plural'] );

        $machine_name        = $this->generate_machine_name( $slug );
        $machine_name_plural = $this->pluralize( $slug );

        list( $raw_template, $extended_template ) = $templates;

        $raw_output = self::mustache_render( $raw_template, $vars );

        if ( ! $control_args['raw'] ) {
            $vars['machine_name'] = $machine_name;
            $vars['output']       = rtrim( $raw_output );

            $target_slug = '';

            if ( false !== $control_args['theme'] ) {
                $target_slug = $control_args['theme'];
            } elseif ( false !== $control_args['plugin'] ) {
                $target_slug = $control_args['plugin'];
            }

            $target_name = ( $target_slug ) ? $this->generate_machine_name( $target_slug ) : '';

            if ( empty( $target_name ) ) {
                $target_name = $machine_name;
            }

            $vars['prefix'] = $target_name;

            $final_output = self::mustache_render( $extended_template, $vars );
        } else {
            $final_output = $raw_output;
        }

        $path = $this->get_output_path( $control_args, $subdir );
        if ( is_string( $path ) && ! empty( $path ) ) {
            $filename = "{$path}{$slug}.php";

            $force           = Utils\get_flag_value( $assoc_args, 'force' );
            $files_written   = $this->create_files( [ $filename => $final_output ], $force );
            $skip_message    = "Skipped creating '{$filename}'.";
            $success_message = "Created '{$filename}'.";
            $this->log_whether_files_written( $files_written, $skip_message, $success_message );

        } else {
            // STDOUT
            echo $final_output;
        }
    }

    /**
     * Generates PHP, JS and CSS code for registering a Gutenberg block for a plugin or theme.
     *
     * **Warning: `wp scaffold block` is deprecated.**
     *
     * The official script to generate a block is the [@wordpress/create-block](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-create-block/) package.
     *
     * See the [Create a Block tutorial](https://developer.wordpress.org/block-editor/getting-started/tutorial/) for a complete walk-through.
     *
     * ## OPTIONS
     *
     * <slug>
     * : The internal name of the block.
     *
     * [--title=<title>]
     * : The display title for your block.
     *
     * [--dashicon=<dashicon>]
     * : The dashicon to make it easier to identify your block.
     *
     * [--category=<category>]
     * : The category name to help users browse and discover your block.
     * ---
     * default: widgets
     * options:
     *   - common
     *   - embed
     *   - formatting
     *   - layout
     *   - widgets
     * ---
     *
     * [--theme]
     * : Create files in the active theme directory. Specify a theme with `--theme=<theme>` to have the file placed in that theme.
     *
     * [--plugin=<plugin>]
     * : Create files in the given plugin's directory.
     *
     * [--force]
     * : Overwrite files that already exist.
     *
     * @subcommand block
     */
    public function block( $args, $assoc_args ) {

        $slug = $args[0];
        if ( ! preg_match( '/^[a-z][a-z0-9\-]*$/', $slug ) ) {
            WP_CLI::error( 'Invalid block slug specified. Block slugs can contain only lowercase alphanumeric characters or dashes, and start with a letter.' );
        }

        $defaults = [
            'title'    => str_replace( '-', ' ', $slug ),
            'category' => 'widgets',
        ];
        $data     = $this->extract_args( $assoc_args, $defaults );

        $data['slug']             = $slug;
        $data['title_ucfirst']    = ucfirst( $data['title'] );
        $data['title_ucfirst_js'] = esc_js( $data['title_ucfirst'] );

        $dashicon = $this->extract_dashicon( $assoc_args );
        if ( $dashicon ) {
            $data['dashicon'] = $dashicon;
        }

        $control_defaults = [
            'force'  => false,
            'plugin' => false,
            'theme'  => false,
        ];
        $control_args     = $this->extract_args( $assoc_args, $control_defaults );

        if ( isset( $control_args['plugin'] ) ) {
            if ( ! preg_match( '/^[A-Za-z0-9\-]*$/', $control_args['plugin'] ) ) {
                WP_CLI::error( 'Invalid plugin name specified. The block editor can only register blocks for plugins that have nothing but lowercase alphanumeric characters or dashes in their slug.' );
            }
        }

        $data['namespace']    = $control_args['plugin'] ? $control_args['plugin'] : $this->get_theme_name( $control_args['theme'] );
        $data['machine_name'] = $this->generate_machine_name( $slug );
        $data['plugin']       = $control_args['plugin'] ? true : false;
        $data['theme']        = ! $data['plugin'];

        $block_dir = $this->get_output_path( $control_args, '/blocks' );
        if ( ! $block_dir ) {
            WP_CLI::error( 'No plugin or theme selected.' );
        }

        $files_to_create = [
            "{$block_dir}/{$slug}.php"        => self::mustache_render( 'block-php.mustache', $data ),
            "{$block_dir}/{$slug}/index.js"   => self::mustache_render( 'block-index-js.mustache', $data ),
            "{$block_dir}/{$slug}/editor.css" => self::mustache_render( 'block-editor-css.mustache', $data ),
            "{$block_dir}/{$slug}/style.css"  => self::mustache_render( 'block-style-css.mustache', $data ),
        ];
        $files_written   = $this->create_files( $files_to_create, $control_args['force'] );
        $skip_message    = 'All block files were skipped.';
        $success_message = "Created block '{$data['title_ucfirst']}'.";
        $this->log_whether_files_written( $files_written, $skip_message, $success_message );
    }

    /**
     * Generates starter code for a theme based on _s.
     *
     * See the [Underscores website](https://underscores.me/) for more details.
     *
     * ## OPTIONS
     *
     * <slug>
     * : The slug for the new theme, used for prefixing functions.
     *
     * [--activate]
     * : Activate the newly downloaded theme.
     *
     * [--enable-network]
     * : Enable the newly downloaded theme for the entire network.
     *
     * [--theme_name=<title>]
     * : What to put in the 'Theme Name:' header in 'style.css'.
     *
     * [--author=<full-name>]
     * : What to put in the 'Author:' header in 'style.css'.
     *
     * [--author_uri=<uri>]
     * : What to put in the 'Author URI:' header in 'style.css'.
     *
     * [--sassify]
     * : Include stylesheets as SASS.
     *
     * [--woocommerce]
     * : Include WooCommerce boilerplate files.
     *
     * [--force]
     * : Overwrite files that already exist.
     *
     * ## EXAMPLES
     *
     *     # Generate a theme with name "Sample Theme" and author "John Doe"
     *     $ wp scaffold _s sample-theme --theme_name="Sample Theme" --author="John Doe"
     *     Success: Created theme 'Sample Theme'.
     *
     * @alias _s
     */
    public function underscores( $args, $assoc_args ) {

        $theme_slug = $args[0];
        $theme_path = WP_CONTENT_DIR . '/themes';
        $url        = 'https://underscores.me';
        $timeout    = 30;

        if ( ! preg_match( '/^[a-z_]\w+$/i', str_replace( '-', '_', $theme_slug ) ) ) {
            WP_CLI::error( 'Invalid theme slug specified. Theme slugs can only contain letters, numbers, underscores and hyphens, and can only start with a letter or underscore.' );
        }

        $defaults = [
            'theme_name' => ucfirst( $theme_slug ),
            'author'     => 'Me',
            'author_uri' => '',
        ];
        $data     = wp_parse_args( $assoc_args, $defaults );

        $_s_theme_path = "$theme_path/$data[theme_name]";

        $error_msg = $this->check_target_directory( 'theme', $_s_theme_path );
        if ( ! empty( $error_msg ) ) {
            WP_CLI::error( "Invalid theme slug specified. {$error_msg}" );
        }

        $force             = Utils\get_flag_value( $assoc_args, 'force' );
        $should_write_file = $this->prompt_if_files_will_be_overwritten( $_s_theme_path, $force );
        if ( ! $should_write_file ) {
            WP_CLI::log( 'No files created' );
            die;
        }

        $theme_description = "Custom theme: {$data['theme_name']}, developed by {$data['author']}";

        $body                                  = [];
        $body['underscoresme_name']            = $data['theme_name'];
        $body['underscoresme_slug']            = $theme_slug;
        $body['underscoresme_author']          = $data['author'];
        $body['underscoresme_author_uri']      = $data['author_uri'];
        $body['underscoresme_description']     = $theme_description;
        $body['underscoresme_generate_submit'] = 'Generate';
        $body['underscoresme_generate']        = '1';
        if ( Utils\get_flag_value( $assoc_args, 'sassify' ) ) {
            $body['underscoresme_sass'] = 1;
        }

        if ( Utils\get_flag_value( $assoc_args, 'woocommerce' ) ) {
            $body['underscoresme_woocommerce'] = 1;
        }

        $tmpfname  = wp_tempnam( $url );
        $post_args = [
            'timeout'  => $timeout,
            'body'     => $body,
            'stream'   => true,
            'filename' => $tmpfname,
        ];

        $response = wp_remote_post( $url, $post_args );

        if ( is_wp_error( $response ) ) {
            WP_CLI::error( $response );
        }

        $response_code = wp_remote_retrieve_response_code( $response );
        if ( 200 !== (int) $response_code ) {
            WP_CLI::error( "Couldn't create theme (received {$response_code} response)." );
        }

        $this->maybe_create_themes_dir();

        $this->init_wp_filesystem();

        $unzip_result = unzip_file( $tmpfname, $theme_path );
        unlink( $tmpfname );

        if ( true === $unzip_result ) {
            $files_to_create = [
                "{$theme_path}/{$theme_slug}/.editorconfig" => file_get_contents( self::get_template_path( '.editorconfig' ) ),
            ];
            $this->create_files( $files_to_create, false );
            WP_CLI::success( "Created theme '{$data['theme_name']}'." );
        } else {
            WP_CLI::error( "Could not decompress your theme files ('{$tmpfname}') at '{$theme_path}': {$unzip_result->get_error_message()}" );
        }

        if ( Utils\get_flag_value( $assoc_args, 'activate' ) ) {
            WP_CLI::run_command( [ 'theme', 'activate', $theme_slug ] );
        } elseif ( Utils\get_flag_value( $assoc_args, 'enable-network' ) ) {
            WP_CLI::run_command( [ 'theme', 'enable', $theme_slug ], [ 'network' => true ] );
        }
    }

    /**
     * Generates child theme based on an existing theme.
     *
     * Creates a child theme folder with `functions.php` and `style.css` files.
     *
     * ## OPTIONS
     *
     * <slug>
     * : The slug for the new child theme.
     *
     * --parent_theme=<slug>
     * : What to put in the 'Template:' header in 'style.css'.
     *
     * [--theme_name=<title>]
     * : What to put in the 'Theme Name:' header in 'style.css'.
     *
     * [--author=<full-name>]
     * : What to put in the 'Author:' header in 'style.css'.
     *
     * [--author_uri=<uri>]
     * : What to put in the 'Author URI:' header in 'style.css'.
     *
     * [--theme_uri=<uri>]
     * : What to put in the 'Theme URI:' header in 'style.css'.
     *
     * [--activate]
     * : Activate the newly created child theme.
     *
     * [--enable-network]
     * : Enable the newly created child theme for the entire network.
     *
     * [--force]
     * : Overwrite files that already exist.
     *
     * ## EXAMPLES
     *
     *     # Generate a 'sample-theme' child theme based on TwentySixteen
     *     $ wp scaffold child-theme sample-theme --parent_theme=twentysixteen
     *     Success: Created '/var/www/example.com/public_html/wp-content/themes/sample-theme'.
     *
     * @subcommand child-theme
     */
    public function child_theme( $args, $assoc_args ) {
        $theme_slug = $args[0];

        if ( in_array( $theme_slug, [ '.', '..' ], true ) ) {
            WP_CLI::error( "Invalid theme slug specified. The slug cannot be '.' or '..'." );
        }

        $defaults = [
            'theme_name' => ucfirst( $theme_slug ),
            'author'     => 'Me',
            'author_uri' => '',
            'theme_uri'  => '',
        ];

        $data                = wp_parse_args( $assoc_args, $defaults );
        $data['slug']        = $theme_slug;
        $data['prefix_safe'] = str_replace( [ ' ', '-' ], '_', $theme_slug );
        $data['description'] = ucfirst( $data['parent_theme'] ) . ' child theme.';

        $theme_dir = WP_CONTENT_DIR . "/themes/{$theme_slug}";

        $error_msg = $this->check_target_directory( 'theme', $theme_dir );
        if ( ! empty( $error_msg ) ) {
            WP_CLI::error( "Invalid theme slug specified. {$error_msg}" );
        }

        $theme_style_path     = "{$theme_dir}/style.css";
        $theme_functions_path = "{$theme_dir}/functions.php";

        $this->maybe_create_themes_dir();

        $files_to_create = [
            $theme_style_path            => self::mustache_render( 'child_theme.mustache', $data ),
            $theme_functions_path        => self::mustache_render( 'child_theme_functions.mustache', $data ),
            "{$theme_dir}/.editorconfig" => file_get_contents( self::get_template_path( '.editorconfig' ) ),
        ];
        $force           = Utils\get_flag_value( $assoc_args, 'force' );
        $files_written   = $this->create_files( $files_to_create, $force );
        $skip_message    = 'All theme files were skipped.';
        $success_message = "Created '{$theme_dir}'.";
        $this->log_whether_files_written( $files_written, $skip_message, $success_message );

        if ( Utils\get_flag_value( $assoc_args, 'activate' ) ) {
            WP_CLI::run_command( [ 'theme', 'activate', $theme_slug ] );
        } elseif ( Utils\get_flag_value( $assoc_args, 'enable-network' ) ) {
            WP_CLI::run_command( [ 'theme', 'enable', $theme_slug ], [ 'network' => true ] );
        }
    }

    private function get_output_path( $assoc_args, $subdir ) {
        if ( $assoc_args['theme'] ) {
            $theme = $assoc_args['theme'];
            if ( is_string( $theme ) ) {
                $path = get_theme_root( $theme ) . "/{$theme}";
            } else {
                $path = get_stylesheet_directory();
            }
            if ( ! is_dir( $path ) ) {
                WP_CLI::error( "Can't find '{$theme}' theme." );
            }
        } elseif ( $assoc_args['plugin'] ) {
            $plugin = $assoc_args['plugin'];
            $path   = WP_PLUGIN_DIR . "/{$plugin}";
            if ( ! is_dir( $path ) ) {
                WP_CLI::error( "Can't find '{$plugin}' plugin." );
            }
        } else {
            return false;
        }

        $path .= $subdir;

        return $path;
    }

    /**
     * Generates starter code for a plugin.
     *
     * The following files are always generated:
     *
     * * `plugin-slug.php` is the main PHP plugin file.
     * * `readme.txt` is the readme file for the plugin.
     * * `package.json` needed by NPM holds various metadata relevant to the project. Packages: `grunt`, `grunt-wp-i18n` and `grunt-wp-readme-to-markdown`. Scripts: `start`, `readme`, `i18n`.
     * * `Gruntfile.js` is the JS file containing Grunt tasks. Tasks: `i18n` containing `addtextdomain` and `makepot`, `readme` containing `wp_readme_to_markdown`.
     * * `.editorconfig` is the configuration file for Editor.
     * * `.gitignore` tells which files (or patterns) git should ignore.
     * * `.distignore` tells which files and folders should be ignored in distribution.
     *
     * The following files are also included unless the `--skip-tests` is used:
     *
     * * `phpunit.xml.dist` is the configuration file for PHPUnit.
     * * `.circleci/config.yml` is the configuration file for CircleCI. Use `--ci=<provider>` to select a different service.
     * * `bin/install-wp-tests.sh` configures the WordPress test suite and a test database.
     * * `tests/bootstrap.php` is the file that makes the current plugin active when running the test suite.
     * * `tests/test-sample.php` is a sample file containing test cases.
     * * `.phpcs.xml.dist` is a collection of PHP_CodeSniffer rules.
     *
     * ## OPTIONS
     *
     * <slug>
     * : The internal name of the plugin.
     *
     * [--dir=<dirname>]
     * : Put the new plugin in some arbitrary directory path. Plugin directory will be path plus supplied slug.
     *
     * [--plugin_name=<title>]
     * : What to put in the 'Plugin Name:' header.
     *
     * [--plugin_description=<description>]
     * : What to put in the 'Description:' header.
     *
     * [--plugin_author=<author>]
     * : What to put in the 'Author:' header.
     *
     * [--plugin_author_uri=<url>]
     * : What to put in the 'Author URI:' header.
     *
     * [--plugin_uri=<url>]
     * : What to put in the 'Plugin URI:' header.
     *
     * [--skip-tests]
     * : Don't generate files for unit testing.
     *
     * [--ci=<provider>]
     * : Choose a configuration file for a continuous integration provider.
     * ---
     * default: circle
     * options:
     *   - circle
     *   - gitlab
     *   - bitbucket
     *   - github
     * ---
     *
     * [--activate]
     * : Activate the newly generated plugin.
     *
     * [--activate-network]
     * : Network activate the newly generated plugin.
     *
     * [--force]
     * : Overwrite files that already exist.
     *
     * ## EXAMPLES
     *
     *     $ wp scaffold plugin sample-plugin
     *     Success: Created plugin files.
     *     Success: Created test files.
     */
    public function plugin( $args, $assoc_args ) {
        $plugin_slug    = $args[0];
        $plugin_name    = ucwords( str_replace( '-', ' ', $plugin_slug ) );
        $plugin_package = str_replace( ' ', '_', $plugin_name );

        if ( in_array( $plugin_slug, [ '.', '..' ], true ) ) {
            WP_CLI::error( "Invalid plugin slug specified. The slug cannot be '.' or '..'." );
        }

        $defaults = [
            'plugin_slug'         => $plugin_slug,
            'plugin_name'         => $plugin_name,
            'plugin_package'      => $plugin_package,
            'plugin_description'  => 'PLUGIN DESCRIPTION HERE',
            'plugin_author'       => 'YOUR NAME HERE',
            'plugin_author_uri'   => 'YOUR SITE HERE',
            'plugin_uri'          => 'PLUGIN SITE HERE',
            'plugin_tested_up_to' => get_bloginfo( 'version' ),
        ];
        $data     = wp_parse_args( $assoc_args, $defaults );

        $data['textdomain'] = $plugin_slug;

        if ( ! empty( $assoc_args['dir'] ) ) {
            if ( ! is_dir( $assoc_args['dir'] ) ) {
                WP_CLI::error( "Cannot create plugin in directory that doesn't exist." );
            }
            $plugin_dir = "{$assoc_args['dir']}/{$plugin_slug}";
        } else {
            $plugin_dir = WP_PLUGIN_DIR . "/{$plugin_slug}";
            $this->maybe_create_plugins_dir();

            $error_msg = $this->check_target_directory( 'plugin', $plugin_dir );
            if ( ! empty( $error_msg ) ) {
                WP_CLI::error( "Invalid plugin slug specified. {$error_msg}" );
            }
        }

        $plugin_path        = "{$plugin_dir}/{$plugin_slug}.php";
        $plugin_readme_path = "{$plugin_dir}/readme.txt";

        $files_to_create = [
            $plugin_path                  => self::mustache_render( 'plugin.mustache', $data ),
            $plugin_readme_path           => self::mustache_render( 'plugin-readme.mustache', $data ),
            "{$plugin_dir}/composer.json" => self::mustache_render( 'plugin-composer.mustache', $data ),
            "{$plugin_dir}/.gitignore"    => self::mustache_render( 'plugin-gitignore.mustache', $data ),
            "{$plugin_dir}/.distignore"   => self::mustache_render( 'plugin-distignore.mustache', $data ),
            "{$plugin_dir}/.editorconfig" => file_get_contents( self::get_template_path( '.editorconfig' ) ),
        ];
        $force           = Utils\get_flag_value( $assoc_args, 'force' );
        $files_written   = $this->create_files( $files_to_create, $force );

        $skip_message    = 'All plugin files were skipped.';
        $success_message = 'Created plugin files.';
        $this->log_whether_files_written( $files_written, $skip_message, $success_message );

        if ( ! Utils\get_flag_value( $assoc_args, 'skip-tests' ) ) {
            $command_args = [
                'dir'   => $plugin_dir,
                'ci'    => empty( $assoc_args['ci'] ) ? '' : $assoc_args['ci'],
                'force' => $force,
            ];
            WP_CLI::run_command( [ 'scaffold', 'plugin-tests', $plugin_slug ], $command_args );
        }

        if ( Utils\get_flag_value( $assoc_args, 'activate' ) ) {
            WP_CLI::run_command( [ 'plugin', 'activate', $plugin_slug ] );
        } elseif ( Utils\get_flag_value( $assoc_args, 'activate-network' ) ) {
            WP_CLI::run_command( [ 'plugin', 'activate', $plugin_slug ], [ 'network' => true ] );
        }
    }

    /**
     * Generates files needed for running PHPUnit tests in a plugin.
     *
     * The following files are generated by default:
     *
     * * `phpunit.xml.dist` is the configuration file for PHPUnit.
     * * `.circleci/config.yml` is the configuration file for CircleCI. Use `--ci=<provider>` to select a different service.
     * * `bin/install-wp-tests.sh` configures the WordPress test suite and a test database.
     * * `tests/bootstrap.php` is the file that makes the current plugin active when running the test suite.
     * * `tests/test-sample.php` is a sample file containing the actual tests.
     * * `.phpcs.xml.dist` is a collection of PHP_CodeSniffer rules.
     *
     * Learn more from the [plugin unit tests documentation](https://make.wordpress.org/cli/handbook/misc/plugin-unit-tests/).
     *
     * ## ENVIRONMENT
     *
     * The `tests/bootstrap.php` file looks for the WP_TESTS_DIR environment
     * variable.
     *
     * ## OPTIONS
     *
     * [<plugin>]
     * : The name of the plugin to generate test files for.
     *
     * [--dir=<dirname>]
     * : Generate test files for a non-standard plugin path. If no plugin slug is specified, the directory name is used.
     *
     * [--ci=<provider>]
     * : Choose a configuration file for a continuous integration provider.
     * ---
     * default: circle
     * options:
     *   - circle
     *   - gitlab
     *   - bitbucket
     *   - github
     * ---
     *
     * [--force]
     * : Overwrite files that already exist.
     *
     * ## EXAMPLES
     *
     *     # Generate unit test files for plugin 'sample-plugin'.
     *     $ wp scaffold plugin-tests sample-plugin
     *     Success: Created test files.
     *
     * @subcommand plugin-tests
     */
    public function plugin_tests( $args, $assoc_args ) {
        $this->scaffold_plugin_theme_tests( $args, $assoc_args, 'plugin' );
    }

    /**
     * Generates files needed for running PHPUnit tests in a theme.
     *
     * The following files are generated by default:
     *
     * * `phpunit.xml.dist` is the configuration file for PHPUnit.
     * * `.circleci/config.yml` is the configuration file for CircleCI. Use `--ci=<provider>` to select a different service.
     * * `bin/install-wp-tests.sh` configures the WordPress test suite and a test database.
     * * `tests/bootstrap.php` is the file that makes the current theme active when running the test suite.
     * * `tests/test-sample.php` is a sample file containing the actual tests.
     * * `.phpcs.xml.dist` is a collection of PHP_CodeSniffer rules.
     *
     * Learn more from the [plugin unit tests documentation](https://make.wordpress.org/cli/handbook/misc/plugin-unit-tests/).
     *
     * ## ENVIRONMENT
     *
     * The `tests/bootstrap.php` file looks for the WP_TESTS_DIR environment
     * variable.
     *
     * ## OPTIONS
     *
     * [<theme>]
     * : The name of the theme to generate test files for.
     *
     * [--dir=<dirname>]
     * : Generate test files for a non-standard theme path. If no theme slug is specified, the directory name is used.
     *
     * [--ci=<provider>]
     * : Choose a configuration file for a continuous integration provider.
     * ---
     * default: circle
     * options:
     *   - circle
     *   - gitlab
     *   - bitbucket
     *   - github
     * ---
     *
     * [--force]
     * : Overwrite files that already exist.
     *
     * ## EXAMPLES
     *
     *     # Generate unit test files for theme 'twentysixteenchild'.
     *     $ wp scaffold theme-tests twentysixteenchild
     *     Success: Created test files.
     *
     * @subcommand theme-tests
     */
    public function theme_tests( $args, $assoc_args ) {
        $this->scaffold_plugin_theme_tests( $args, $assoc_args, 'theme' );
    }

    private function scaffold_plugin_theme_tests( $args, $assoc_args, $type ) {
        $wp_filesystem = $this->init_wp_filesystem();

        if ( ! empty( $args[0] ) ) {
            $slug = $args[0];
            if ( in_array( $slug, [ '.', '..' ], true ) ) {
                WP_CLI::error( "Invalid {$type} slug specified. The slug cannot be '.' or '..'." );
            }
            if ( 'theme' === $type ) {
                $theme = wp_get_theme( $slug );
                if ( $theme->exists() ) {
                    $target_dir = $theme->get_stylesheet_directory();
                } else {
                    WP_CLI::error( "Invalid {$type} slug specified. The theme '{$slug}' does not exist." );
                }
            } else {
                $target_dir = WP_PLUGIN_DIR . "/{$slug}";
            }
            if ( empty( $assoc_args['dir'] ) && ! is_dir( $target_dir ) ) {
                WP_CLI::error( "Invalid {$type} slug specified. No such target directory '{$target_dir}'." );
            }

            $error_msg = $this->check_target_directory( $type, $target_dir );
            if ( ! empty( $error_msg ) ) {
                WP_CLI::error( "Invalid {$type} slug specified. {$error_msg}" );
            }
        }

        if ( ! empty( $assoc_args['dir'] ) ) {
            $target_dir = $assoc_args['dir'];
            if ( ! is_dir( $target_dir ) ) {
                WP_CLI::error( "Invalid {$type} directory specified. No such directory '{$target_dir}'." );
            }
            if ( empty( $slug ) ) {
                $slug = Utils\basename( $target_dir );
            }
        }

        if ( empty( $slug ) || empty( $target_dir ) ) {
            WP_CLI::error( "Invalid {$type} specified." );
        }

        $name    = ucwords( str_replace( '-', ' ', $slug ) );
        $package = str_replace( ' ', '_', $name );

        $tests_dir = "{$target_dir}/tests";
        $bin_dir   = "{$target_dir}/bin";

        $wp_filesystem->mkdir( $tests_dir );
        $wp_filesystem->mkdir( $bin_dir );

        $wp_versions_to_test = [];
        // Parse plugin readme.txt
        if ( file_exists( "{$target_dir}/readme.txt" ) ) {
            $readme_content = (string) file_get_contents( "{$target_dir}/readme.txt" );

            preg_match( '/Requires at least\:(.*)\n/m', $readme_content, $matches );
            if ( isset( $matches[1] ) && $matches[1] ) {
                $wp_versions_to_test[] = trim( $matches[1] );
            }
        }
        $wp_versions_to_test[] = 'latest';
        $wp_versions_to_test[] = 'trunk';

        $main_file = "{$slug}.php";

        if ( 'plugin' === $type ) {
            if ( ! function_exists( 'get_plugins' ) ) {
                require_once ABSPATH . 'wp-admin/includes/plugin.php';
            }

            $all_plugins = get_plugins();

            if ( ! empty( $all_plugins ) ) {
                $filtered = array_filter(
                    array_keys( $all_plugins ),
                    static function ( $item ) use ( $slug ) {
                        return ( false !== strpos( $item, "{$slug}/" ) );
                    }
                );

                if ( ! empty( $filtered ) ) {
                    $main_file = basename( reset( $filtered ) );
                }
            }
        }

        $template_data = [
            "{$type}_slug"      => $slug,
            "{$type}_package"   => $package,
            "{$type}_main_file" => $main_file,
        ];

        $force           = Utils\get_flag_value( $assoc_args, 'force' );
        $files_to_create = [
            "{$tests_dir}/bootstrap.php"   => self::mustache_render( "{$type}-bootstrap.mustache", $template_data ),
            "{$tests_dir}/test-sample.php" => self::mustache_render( "{$type}-test-sample.mustache", $template_data ),
        ];
        if ( 'circle' === $assoc_args['ci'] ) {
            $files_to_create[ "{$target_dir}/.circleci/config.yml" ] = self::mustache_render( 'plugin-circle.mustache', compact( 'wp_versions_to_test' ) );
        } elseif ( 'gitlab' === $assoc_args['ci'] ) {
            $files_to_create[ "{$target_dir}/.gitlab-ci.yml" ] = self::mustache_render( 'plugin-gitlab.mustache' );
        } elseif ( 'bitbucket' === $assoc_args['ci'] ) {
            $files_to_create[ "{$target_dir}/bitbucket-pipelines.yml" ] = self::mustache_render( 'plugin-bitbucket.mustache' );
        } elseif ( 'github' === $assoc_args['ci'] ) {
            $files_to_create[ "{$target_dir}/.github/workflows/testing.yml" ] = self::mustache_render( 'plugin-github.mustache' );
        }

        $files_written = $this->create_files( $files_to_create, $force );

        $to_copy = [
            'install-wp-tests.sh' => $bin_dir,
            'phpunit.xml.dist'    => $target_dir,
            '.phpcs.xml.dist'     => $target_dir,
        ];

        foreach ( $to_copy as $file => $dir ) {
            $file_name         = "{$dir}/{$file}";
            $force             = Utils\get_flag_value( $assoc_args, 'force' );
            $should_write_file = $this->prompt_if_files_will_be_overwritten( $file_name, $force );
            if ( ! $should_write_file ) {
                continue;
            }
            $files_written[] = $file_name;

            $wp_filesystem->copy( self::get_template_path( $file ), $file_name, true );
            if ( 'install-wp-tests.sh' === $file ) {
                if ( ! $wp_filesystem->chmod( "{$dir}/{$file}", 0755 ) ) {
                    WP_CLI::warning( "Couldn't mark 'install-wp-tests.sh' as executable." );
                }
            }
        }

        $skip_message    = 'All test files were skipped.';
        $success_message = 'Created test files.';
        $this->log_whether_files_written( $files_written, $skip_message, $success_message );
    }

    /**
     * Checks that the `$target_dir` is a child directory of the WP themes or plugins directory, depending on `$type`.
     *
     * @param string $type       "theme" or "plugin"
     * @param string $target_dir The theme/plugin directory to check.
     *
     * @return null|string Returns null on success, error message on error.
     */
    private function check_target_directory( $type, $target_dir ) {
        $parent_dir = dirname( self::canonicalize_path( str_replace( '\\', '/', $target_dir ) ) );

        if ( 'theme' === $type && str_replace( '\\', '/', WP_CONTENT_DIR . '/themes' ) !== $parent_dir ) {
            return sprintf( 'The target directory \'%1$s\' is not in \'%2$s\'.', $target_dir, WP_CONTENT_DIR . '/themes' );
        }

        if ( 'plugin' === $type && str_replace( '\\', '/', WP_PLUGIN_DIR ) !== $parent_dir ) {
            return sprintf( 'The target directory \'%1$s\' is not in \'%2$s\'.', $target_dir, WP_PLUGIN_DIR );
        }

        // Success.
        return null;
    }

    protected function create_files( $files_and_contents, $force ) {
        $wp_filesystem = $this->init_wp_filesystem();
        $wrote_files   = [];

        foreach ( $files_and_contents as $filename => $contents ) {
            $should_write_file = $this->prompt_if_files_will_be_overwritten( $filename, $force );
            if ( ! $should_write_file ) {
                continue;
            }

            $wp_filesystem->mkdir( dirname( $filename ) );

            // Create multi-level folders.
            if ( false === $wp_filesystem->exists( dirname( $filename ) ) ) {
                $wp_filesystem->mkdir( dirname( dirname( $filename ) ) );
                $wp_filesystem->mkdir( dirname( $filename ) );
            }

            if ( ! $wp_filesystem->put_contents( $filename, $contents ) ) {
                WP_CLI::error( "Error creating file: {$filename}" );
            } elseif ( $should_write_file ) {
                $wrote_files[] = $filename;
            }
        }
        return $wrote_files;
    }

    protected function prompt_if_files_will_be_overwritten( $filename, $force ) {
        $should_write_file = true;
        if ( ! file_exists( $filename ) ) {
            return true;
        }

        WP_CLI::warning( 'File already exists.' );
        WP_CLI::log( $filename );
        if ( ! $force ) {
            do {
                $answer      = cli\prompt(
                    'Skip this file, or replace it with scaffolding?',
                    $default = false,
                    $marker  = '[s/r]: '
                );
            } while ( ! in_array( $answer, [ 's', 'r' ], true ) );
            $should_write_file = 'r' === $answer;
        }

        $outcome = $should_write_file ? 'Replacing' : 'Skipping';
        WP_CLI::log( $outcome . PHP_EOL );

        return $should_write_file;
    }

    protected function log_whether_files_written( $files_written, $skip_message, $success_message ) {
        if ( empty( $files_written ) ) {
            WP_CLI::log( $skip_message );
        } else {
            WP_CLI::success( $success_message );
        }
    }

    /**
     * Extracts dashicon name when provided or return null otherwise.
     *
     * @param array{dashicon?: string} $assoc_args
     * @return string|null
     */
    private function extract_dashicon( $assoc_args ) {
        $dashicon = Utils\get_flag_value( $assoc_args, 'dashicon' );
        if ( ! $dashicon ) {
            return null;
        }
        return preg_replace( '/dashicon(-|s-)/', '', $dashicon );
    }

    /**
     * If you're writing your files to your theme directory your textdomain also needs to be the same as your theme.
     * Same goes for when plugin is being used.
     */
    private function get_textdomain( $textdomain, $args ) {
        if ( strlen( $textdomain ) ) {
            return $textdomain;
        }

        if ( $args['theme'] ) {
            return $this->get_theme_name( $args['theme'] );
        }

        if ( $args['plugin'] && true !== $args['plugin'] ) {
            return $args['plugin'];
        }

        return 'YOUR-TEXTDOMAIN';
    }

    /**
     * Generates the machine name for function declarations.
     *
     * @param string $slug Slug name to convert.
     * @return string
     */
    private function generate_machine_name( $slug ) {
        return str_replace( '-', '_', $slug );
    }

    /**
     * Pluralizes a noun.
     *
     * @see    Inflector::pluralize()
     * @param  string $word Word to be pluralized.
     * @return string
     */
    private function pluralize( $word ) {
        return Inflector::pluralize( $word );
    }

    protected function extract_args( $assoc_args, $defaults ) {
        $out = [];

        foreach ( $defaults as $key => $value ) {
            $out[ $key ] = Utils\get_flag_value( $assoc_args, $key, $value );
        }

        return $out;
    }

    protected function quote_comma_list_elements( $comma_list ) {
        return "'" . implode( "', '", explode( ',', $comma_list ) ) . "'";
    }

    /**
     * Creates the themes directory if it doesn't already exist.
     */
    protected function maybe_create_themes_dir() {

        $themes_dir = WP_CONTENT_DIR . '/themes';
        if ( ! is_dir( $themes_dir ) ) {
            wp_mkdir_p( $themes_dir );
        }
    }

    /**
     * Creates the plugins directory if it doesn't already exist.
     */
    protected function maybe_create_plugins_dir() {

        if ( ! is_dir( WP_PLUGIN_DIR ) ) {
            wp_mkdir_p( WP_PLUGIN_DIR );
        }
    }

    /**
     * Initializes WP_Filesystem.
     */
    protected function init_wp_filesystem() {
        global $wp_filesystem;
        WP_Filesystem();

        return $wp_filesystem;
    }

    /**
     * Localizes the template path.
     */
    private static function mustache_render( $template, $data = [] ) {
        return Utils\mustache_render( dirname( __DIR__ ) . "/templates/{$template}", $data );
    }

    /**
     * Gets the template path based on installation type.
     */
    private static function get_template_path( $template ) {
        $command_root  = Utils\phar_safe_path( dirname( __DIR__ ) );
        $template_path = "{$command_root}/templates/{$template}";

        if ( ! file_exists( $template_path ) ) {
            WP_CLI::error( "Couldn't find {$template}" );
        }

        return $template_path;
    }

    /*
     * Returns the canonicalized path, with dot and double dot segments resolved.
     *
     * Copied from Symfony\Component\DomCrawler\AbstractUriElement::canonicalizePath().
     * Implements RFC 3986, section 5.2.4.
     *
     * @param string $path The path to make canonical.
     *
     * @return string The canonicalized path.
     */
    private static function canonicalize_path( $path ) {
        if ( '' === $path || '/' === $path ) {
            return $path;
        }

        if ( '.' === substr( $path, -1 ) ) {
            $path .= '/';
        }

        $output = [];

        foreach ( explode( '/', $path ) as $segment ) {
            if ( '..' === $segment ) {
                array_pop( $output );
            } elseif ( '.' !== $segment ) {
                $output[] = $segment;
            }
        }

        return implode( '/', $output );
    }

    /**
     * Gets an active theme's name when true provided or the same name otherwise.
     *
     * @param string|bool $theme Theme name or true.
     * @return string
     */
    private function get_theme_name( $theme ) {
        if ( true === $theme ) {
            $theme = wp_get_theme()->template;
        }
        return strtolower( $theme );
    }
}

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ Read-Only ]

:: Make Dir ::
 
[ Read-Only ]
:: Make File ::
 
[ Read-Only ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 2.5 [PHP 8 Update] [24.05.2025] | Generation time: 0.0124 ]--