From 22312600fc56b686ccf933fe29ae972590b3e5a3 Mon Sep 17 00:00:00 2001 From: Kelly Dwan Date: Mon, 27 Jun 2022 16:02:27 -0400 Subject: [PATCH] Add create script --- bin/create | 116 +++++++++++++++++ composer.json | 6 +- composer.lock | 123 ++++++++++++++++++ .../child-theme/create-project.config.php | 44 +++++++ 4 files changed, 288 insertions(+), 1 deletion(-) create mode 100755 bin/create create mode 100644 composer.lock create mode 100644 templates/child-theme/create-project.config.php diff --git a/bin/create b/bin/create new file mode 100755 index 0000000..8771ad2 --- /dev/null +++ b/bin/create @@ -0,0 +1,116 @@ +#!/usr/bin/env php +setSignature( './bin/create child-theme' ); + +/** + * Run the prompts from the project's configuration. + * + * @param array $prompts A set of properties used to request user input. + * @param array $params The parameters provided to the script on the command line. + * @return array The merged list of values - from user input, command line, or defaults. + */ +function run_prompts( $prompts, $params ) { + $settings = array_fill_keys( array_keys( $prompts ), '' ); + + foreach ( $prompts as $key => $prompt ) { + $validation = $prompt['validate'] ?: function( $value ) { return $value; }; + + // If the value was provided in CLI args, skip the prompt. + if ( isset( $params[ '--' . $key ] ) ) { + $settings[ $key ] = call_user_func( $validation, $params[ '--' . $key ] ); + } else { + if ( $prompt['default'] ) { + $request = new Input( sprintf( '%1$s [default: %2$s]: ', $prompt['message'], $prompt['default'] ) ); + } else { + $request = new Input( sprintf( '%s: ', $prompt['message'] ) ); + } + + $response = $request->read(); + $settings[ $key ] = call_user_func( $validation, $response ); + } + + // If we still have no value, inherit the default. + if ( empty( $settings[ $key ] ) ) { + $settings[ $key ] = $prompt['default']; + } + } + + return $settings; +} + +$app->registerCommand( + 'child-theme', + function( CommandCall $input ) use ( $app ) { + $app->getPrinter()->display( "Let's create a child theme project!" ); + $app->getPrinter()->out( 'Hit enter to accept the default values.', 'info' ); + $app->getPrinter()->newline(); + $app->getPrinter()->newline(); + + $template_path = dirname( __DIR__ ) . '/templates/child-theme'; + $raw_files = scandir( $template_path ); + $files = array_filter( + $raw_files, + function( $file ) { + return preg_match( '/\.mustache$/', $file ); + } + ); + + if ( empty( $files ) ) { + $app->getPrinter()->error( "Can't find any project templates in $template_path" ); + return; + } + + $prompts = require_once( $template_path . '/create-project.config.php' ); + if ( empty( $prompts['slug'] ) || empty( $prompts['slug']['default'] ) ) { + $app->getPrinter()->error( 'Project is not configured correctly. Slug is a required prompt, and must have a default.' ); + return; + } + + $settings = run_prompts( $prompts, $input->params ); + + // Generate any built values (like slugSnakeCase). + $settings['slugSnakeCase'] = str_replace( ' ', '', ucwords( str_replace( '-', ' ', $settings['slug'] ) ) ); + + $app->getPrinter()->display( 'Generating themeā€¦' ); + $m = new \Mustache_Engine; + + $project_path = getcwd() . '/' . $settings['slug']; + $result = mkdir( $project_path ); + if ( ! $result ) { + $app->getPrinter()->error( "Couldn't create directory $project_path" ); + return; + } + + foreach ( $files as $file ) { + $file_content = file_get_contents( $template_path . '/' . $file ); + $new_content = $m->render( $file_content, $settings ); + $new_file = preg_replace( '/\.mustache$/', '', $file ); + $result = file_put_contents( $project_path . '/' . $new_file, $new_content ); + + // This is an error whether this is false or "zero bytes". + if ( ! $result ) { + $app->getPrinter()->error( "Nothing written to $project_path/$new_file" ); + return; + } + } + + $app->getPrinter()->success( "Tada! Theme created in $project_path" ); + } +); + +$app->runCommand( $argv ); diff --git a/composer.json b/composer.json index 530d25f..3787b3a 100644 --- a/composer.json +++ b/composer.json @@ -8,5 +8,9 @@ }, "bin": [ "bin/update-configs" - ] + ], + "require": { + "minicli/minicli": "^2.2", + "mustache/mustache": "^2.14" + } } diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..40dbceb --- /dev/null +++ b/composer.lock @@ -0,0 +1,123 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "298e74f41bd5a5da7dd3b19a249f6b95", + "packages": [ + { + "name": "minicli/minicli", + "version": "2.2.2", + "source": { + "type": "git", + "url": "https://github.com/minicli/minicli.git", + "reference": "7a136614949b47d716769a037a1107e414bc4f38" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/minicli/minicli/zipball/7a136614949b47d716769a037a1107e414bc4f38", + "reference": "7a136614949b47d716769a037a1107e414bc4f38", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.16", + "pestphp/pest": "^1.0", + "phpunit/phpunit": "^9.0" + }, + "suggest": { + "ext-readline": "For obtaining user input" + }, + "type": "library", + "autoload": { + "psr-4": { + "Assets\\": "tests/Assets", + "Minicli\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Experimental micro CLI framework for PHP", + "homepage": "https://github.com/minicli/minicli", + "keywords": [ + "cli", + "command-line" + ], + "support": { + "issues": "https://github.com/minicli/minicli/issues", + "source": "https://github.com/minicli/minicli/tree/2.2.2" + }, + "funding": [ + { + "url": "https://github.com/erikaheidi", + "type": "github" + } + ], + "time": "2021-10-30T07:30:03+00:00" + }, + { + "name": "mustache/mustache", + "version": "v2.14.1", + "source": { + "type": "git", + "url": "https://github.com/bobthecow/mustache.php.git", + "reference": "579ffa5c96e1d292c060b3dd62811ff01ad8c24e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/bobthecow/mustache.php/zipball/579ffa5c96e1d292c060b3dd62811ff01ad8c24e", + "reference": "579ffa5c96e1d292c060b3dd62811ff01ad8c24e", + "shasum": "" + }, + "require": { + "php": ">=5.2.4" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "~1.11", + "phpunit/phpunit": "~3.7|~4.0|~5.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "Mustache": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Justin Hileman", + "email": "justin@justinhileman.info", + "homepage": "http://justinhileman.com" + } + ], + "description": "A Mustache implementation in PHP.", + "homepage": "https://github.com/bobthecow/mustache.php", + "keywords": [ + "mustache", + "templating" + ], + "support": { + "issues": "https://github.com/bobthecow/mustache.php/issues", + "source": "https://github.com/bobthecow/mustache.php/tree/v2.14.1" + }, + "time": "2022-01-21T06:08:36+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [], + "plugin-api-version": "2.3.0" +} diff --git a/templates/child-theme/create-project.config.php b/templates/child-theme/create-project.config.php new file mode 100644 index 0000000..81a3366 --- /dev/null +++ b/templates/child-theme/create-project.config.php @@ -0,0 +1,44 @@ + array( + 'message' => 'The display title for the theme', + 'default' => 'Child Theme', + 'validate' => false, + ), + 'slug' => array( + 'message' => 'The theme slug used for identification (also the output folder name)', + 'default' => 'wporg-child-theme', + 'validate' => __NAMESPACE__ . '\sanitize_slug', + ), + 'description' => array( + 'message' => 'The short description for the theme', + 'default' => '', + 'validate' => false, + ), + 'textdomain' => array( + 'message' => 'The textdomain used for this theme', + 'default' => 'wporg', + 'validate' => __NAMESPACE__ . '\sanitize_slug', + ), +);