diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..c9c1473
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,15 @@
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+insert_final_newline = true
+indent_style = space
+indent_size = 4
+trim_trailing_whitespace = true
+
+[*.md]
+trim_trailing_whitespace = false
+
+[*.{yml,yaml,json}]
+indent_size = 2
diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml
index 7e21426..ae11553 100644
--- a/.github/workflows/php.yml
+++ b/.github/workflows/php.yml
@@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: Validate composer.json and composer.lock
run: composer validate
@@ -20,8 +20,8 @@ jobs:
- name: Install dependencies
run: composer install --prefer-dist --no-progress
- - name: Run test suite
- run: composer test
+ - name: Check code style
+ run: composer test:lint
- - name: Run php-cs-fixer
- run: composer csfix .
+ - name: Run test suite
+ run: composer test:unit
diff --git a/Command/Create/CommandController.php b/Command/Create/CommandController.php
new file mode 100644
index 0000000..c857f1c
--- /dev/null
+++ b/Command/Create/CommandController.php
@@ -0,0 +1,81 @@
+info('Command: ');
+ $command = $input->read();
+
+ $this->createCommandFile($this->buildCommandPath($command), $command);
+ }
+
+ private function buildCommandPath(string $command): array
+ {
+ $commandsPath = realpath($this->config->app_path[0]);
+ $commandArray = explode(' ', $command);
+ $commandPartsCount = count($commandArray);
+ if ($commandPartsCount > 2) {
+ $this->error('Command name must be one or two words.');
+
+ return [];
+ }
+
+ $commandPath = [];
+
+ do {
+ $commandPart = array_shift($commandArray);
+ $commandPart = ucfirst(strtolower($commandPart));
+ $commandPath[] = $commandPart;
+
+ if (count($commandArray) === 0 && $commandPartsCount > 1) {
+ break;
+ }
+
+ $dir = "{$commandsPath}/" . implode('/', $commandPath);
+ if (! is_dir($dir)) {
+ mkdir($dir);
+ }
+ } while (count($commandArray) > 0);
+
+ return array_map(fn ($item) => ucfirst(strtolower($item)), $commandPath);
+ }
+
+ private function createCommandFile(array $commandPath, string $command): void
+ {
+ if ($commandPath === []) {
+ return;
+ }
+ $commandsPath = realpath($this->config->app_path[0]);
+ $commandName = count($commandPath) > 1 ? array_pop($commandPath) : 'Default';
+ $commandClass = "{$commandName}Controller";
+ $commandFilePath = realpath("{$commandsPath}/" . implode('/', $commandPath)) . "/{$commandClass}.php";
+
+ if (file_exists($commandFilePath)) {
+ $this->error("Command file already exists at {$commandFilePath}");
+
+ return;
+ }
+
+ $commandNamespace = 'namespace App\Command' . '\\' . implode('\\', $commandPath);
+ $commandFileContent = file_get_contents(__DIR__ . '/../../stubs/command.stub');
+ $commandFileContent = str_replace(
+ ['{{command_namespace}}', '{{command_class}}', '{{command_name}}'],
+ [$commandNamespace, $commandClass, $command],
+ $commandFileContent
+ );
+
+ file_put_contents($commandFilePath, $commandFileContent);
+
+ $this->success("{$command} command created!");
+ }
+}
diff --git a/Command/Create/ContentController.php b/Command/Create/ContentController.php
index 06263a3..b3a8d82 100644
--- a/Command/Create/ContentController.php
+++ b/Command/Create/ContentController.php
@@ -1,11 +1,13 @@
getApp()->config->has('stencil_dir')) {
- $this->error("You must define a stencil_dir config option.");
+ if (! $this->getApp()->config->has('stencil_dir')) {
+ $this->error('You must define a stencil_dir config option.');
+
return;
}
- if (!$this->getApp()->config->has('stencil_locations')) {
- $this->error("You must define a stencil_locations array config option.");
+ if (! $this->getApp()->config->has('stencil_locations')) {
+ $this->error('You must define a stencil_locations array config option.');
+
return;
}
$args = $this->getArgs();
$template_name = $args[3] ?? null;
- if (!$template_name) {
+ if (! $template_name) {
$template_name = 'post';
}
@@ -34,21 +38,22 @@ public function handle(): void
$input = new Input(' ');
- $this->info("Content Title: ");
+ $this->info('Content Title: ');
$title = $input->read();
- $this->info("Content Description: ");
+ $this->info('Content Description: ');
$description = $input->read();
$content = $stencil->applyTemplate($template_name, [
'title' => $title,
- 'description' => $description
+ 'description' => $description,
]);
$save_locations = $this->getApp()->config->stencil_locations;
- if (!array_key_exists($template_name, $save_locations)) {
- $this->error("Save location not found for template $template_name");
+ if (! array_key_exists($template_name, $save_locations)) {
+ $this->error("Save location not found for template {$template_name}");
+
return;
}
@@ -57,7 +62,7 @@ public function handle(): void
$file = fopen($path . '/' . $save_name, 'a+');
fwrite($file, $content);
- $this->info("Content generated at " . $path . '/' . $save_name);
+ $this->info('Content generated at ' . $path . '/' . $save_name);
}
public function slugify($title)
diff --git a/Command/Create/DefaultController.php b/Command/Create/DefaultController.php
index 904ee4b..985db88 100644
--- a/Command/Create/DefaultController.php
+++ b/Command/Create/DefaultController.php
@@ -1,15 +1,16 @@
info("./librarian create [subcommand]", true);
- $this->info("Run \"./librarian create content\" to create a content file based on a template.");
+ $this->info('./librarian create [subcommand]', true);
+ $this->info('Run "./librarian create content" to create a content file based on a template.');
}
}
diff --git a/README.md b/README.md
index 106537f..9768a42 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,18 @@
-# command-create
+
+
Command Create
+ Librarian's built-in create command.
+
-Librarian's built-in create command.
+## Commands Available
+
+### Create Content
```shell
./librarian create content [template]
```
+
+### Create Command
+
+```shell
+./librarian create command
+```
diff --git a/composer.json b/composer.json
index e93e1f6..39b2b8b 100644
--- a/composer.json
+++ b/composer.json
@@ -1,30 +1,41 @@
{
- "name": "librarianphp/command-create",
- "type": "library",
- "description": "Librarian's built-in command to create new content",
- "license": "MIT",
- "homepage": "https://github.com/librarianphp/command-demo",
- "keywords": ["cli","command-line", "markdown"],
- "autoload": {
- "psr-4": {
- "librarianphp\\": "Command/"
- }
- },
- "require": {
- "minicli/minicli": "^4.0",
- "minicli/stencil": "^0.1.1"
- },
- "require-dev": {
- "pestphp/pest": "^2.4",
- "friendsofphp/php-cs-fixer": "^3.16"
- },
- "scripts": {
- "test" : ["pest"],
- "csfix": ["php-cs-fixer fix"]
- },
- "config": {
- "allow-plugins": {
- "pestphp/pest-plugin": true
- }
+ "name": "librarianphp/command-create",
+ "type": "library",
+ "description": "Librarian's built-in command to create new content",
+ "license": "MIT",
+ "homepage": "https://github.com/librarianphp/command-demo",
+ "keywords": [
+ "cli",
+ "command-line",
+ "markdown"
+ ],
+ "autoload": {
+ "psr-4": {
+ "librarianphp\\": "Command/"
}
+ },
+ "require": {
+ "php": ">=8.1",
+ "minicli/minicli": "^4.0",
+ "minicli/stencil": "^0.1.1"
+ },
+ "require-dev": {
+ "pestphp/pest": "^2.6",
+ "friendsofphp/php-cs-fixer": "^3.17",
+ "laravel/pint": "^1.10"
+ },
+ "scripts": {
+ "lint": ["pint"],
+ "test:lint": ["pint --test"],
+ "test:unit": ["pest"],
+ "test": [
+ "@test:lint",
+ "@test:unit"
+ ]
+ },
+ "config": {
+ "allow-plugins": {
+ "pestphp/pest-plugin": true
+ }
+ }
}
diff --git a/composer.lock b/composer.lock
index d22a97f..4e88f17 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,20 +4,20 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "34d9c79907e425762d9dd7110e76bf13",
+ "content-hash": "96c508cb13bbadb79ad683bcecc4154b",
"packages": [
{
"name": "minicli/minicli",
- "version": "4.0.3",
+ "version": "4.0.5",
"source": {
"type": "git",
"url": "https://github.com/minicli/minicli.git",
- "reference": "7ccff45d4311e31a2fba896dfe70d4d2c6671aab"
+ "reference": "1f71a5d8ec76d5b07280816ffcc9b36499830f43"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/minicli/minicli/zipball/7ccff45d4311e31a2fba896dfe70d4d2c6671aab",
- "reference": "7ccff45d4311e31a2fba896dfe70d4d2c6671aab",
+ "url": "https://api.github.com/repos/minicli/minicli/zipball/1f71a5d8ec76d5b07280816ffcc9b36499830f43",
+ "reference": "1f71a5d8ec76d5b07280816ffcc9b36499830f43",
"shasum": ""
},
"require": {
@@ -32,6 +32,9 @@
},
"type": "library",
"autoload": {
+ "files": [
+ "src/helpers.php"
+ ],
"psr-4": {
"Minicli\\": "src/"
}
@@ -48,7 +51,7 @@
],
"support": {
"issues": "https://github.com/minicli/minicli/issues",
- "source": "https://github.com/minicli/minicli/tree/4.0.3"
+ "source": "https://github.com/minicli/minicli/tree/4.0.5"
},
"funding": [
{
@@ -56,7 +59,7 @@
"type": "github"
}
],
- "time": "2023-05-20T22:04:58+00:00"
+ "time": "2023-06-07T18:49:30+00:00"
},
{
"name": "minicli/stencil",
@@ -495,25 +498,29 @@
},
{
"name": "doctrine/deprecations",
- "version": "v1.1.0",
+ "version": "v1.1.1",
"source": {
"type": "git",
"url": "https://github.com/doctrine/deprecations.git",
- "reference": "8cffffb2218e01f3b370bf763e00e81697725259"
+ "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/deprecations/zipball/8cffffb2218e01f3b370bf763e00e81697725259",
- "reference": "8cffffb2218e01f3b370bf763e00e81697725259",
+ "url": "https://api.github.com/repos/doctrine/deprecations/zipball/612a3ee5ab0d5dd97b7cf3874a6efe24325efac3",
+ "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3",
"shasum": ""
},
"require": {
- "php": "^7.1|^8.0"
+ "php": "^7.1 || ^8.0"
},
"require-dev": {
"doctrine/coding-standard": "^9",
- "phpunit/phpunit": "^7.5|^8.5|^9.5",
- "psr/log": "^1|^2|^3"
+ "phpstan/phpstan": "1.4.10 || 1.10.15",
+ "phpstan/phpstan-phpunit": "^1.0",
+ "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
+ "psalm/plugin-phpunit": "0.18.4",
+ "psr/log": "^1 || ^2 || ^3",
+ "vimeo/psalm": "4.30.0 || 5.12.0"
},
"suggest": {
"psr/log": "Allows logging deprecations via PSR-3 logger implementation"
@@ -532,9 +539,9 @@
"homepage": "https://www.doctrine-project.org/",
"support": {
"issues": "https://github.com/doctrine/deprecations/issues",
- "source": "https://github.com/doctrine/deprecations/tree/v1.1.0"
+ "source": "https://github.com/doctrine/deprecations/tree/v1.1.1"
},
- "time": "2023-05-29T18:55:17+00:00"
+ "time": "2023-06-03T09:27:29+00:00"
},
{
"name": "doctrine/lexer",
@@ -900,6 +907,72 @@
},
"time": "2021-10-08T21:21:46+00:00"
},
+ {
+ "name": "laravel/pint",
+ "version": "v1.10.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/laravel/pint.git",
+ "reference": "d69f914aa347a448628b672ba90adf0b4ea0ce4a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/laravel/pint/zipball/d69f914aa347a448628b672ba90adf0b4ea0ce4a",
+ "reference": "d69f914aa347a448628b672ba90adf0b4ea0ce4a",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "ext-mbstring": "*",
+ "ext-tokenizer": "*",
+ "ext-xml": "*",
+ "php": "^8.1.0"
+ },
+ "require-dev": {
+ "friendsofphp/php-cs-fixer": "^3.17.0",
+ "illuminate/view": "^10.5.1",
+ "laravel-zero/framework": "^10.0.2",
+ "mockery/mockery": "^1.5.1",
+ "nunomaduro/larastan": "^2.5.1",
+ "nunomaduro/termwind": "^1.15.1",
+ "pestphp/pest": "^2.4.0"
+ },
+ "bin": [
+ "builds/pint"
+ ],
+ "type": "project",
+ "autoload": {
+ "psr-4": {
+ "App\\": "app/",
+ "Database\\Seeders\\": "database/seeders/",
+ "Database\\Factories\\": "database/factories/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nuno Maduro",
+ "email": "enunomaduro@gmail.com"
+ }
+ ],
+ "description": "An opinionated code formatter for PHP.",
+ "homepage": "https://laravel.com",
+ "keywords": [
+ "format",
+ "formatter",
+ "lint",
+ "linter",
+ "php"
+ ],
+ "support": {
+ "issues": "https://github.com/laravel/pint/issues",
+ "source": "https://github.com/laravel/pint"
+ },
+ "time": "2023-06-03T15:01:17+00:00"
+ },
{
"name": "myclabs/deep-copy",
"version": "1.11.1",
@@ -1199,16 +1272,16 @@
},
{
"name": "pestphp/pest",
- "version": "v2.6.1",
+ "version": "v2.6.3",
"source": {
"type": "git",
"url": "https://github.com/pestphp/pest.git",
- "reference": "faafedd55ca4479b0634f85cc1a68bf5af44764e"
+ "reference": "3c20e8114e5d2f5e39cf013f0f9b8ebc0ac1a6fa"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/pestphp/pest/zipball/faafedd55ca4479b0634f85cc1a68bf5af44764e",
- "reference": "faafedd55ca4479b0634f85cc1a68bf5af44764e",
+ "url": "https://api.github.com/repos/pestphp/pest/zipball/3c20e8114e5d2f5e39cf013f0f9b8ebc0ac1a6fa",
+ "reference": "3c20e8114e5d2f5e39cf013f0f9b8ebc0ac1a6fa",
"shasum": ""
},
"require": {
@@ -1216,17 +1289,17 @@
"nunomaduro/collision": "^7.5.2",
"nunomaduro/termwind": "^1.15.1",
"pestphp/pest-plugin": "^2.0.1",
- "pestphp/pest-plugin-arch": "^2.1.2",
+ "pestphp/pest-plugin-arch": "^2.2.0",
"php": "^8.1.0",
- "phpunit/phpunit": "^10.1.3"
+ "phpunit/phpunit": "^10.2.1"
},
"conflict": {
- "phpunit/phpunit": ">10.1.3",
+ "phpunit/phpunit": ">10.2.1",
"webmozart/assert": "<1.11.0"
},
"require-dev": {
- "pestphp/pest-dev-tools": "^2.9.0",
- "symfony/process": "^6.2.10"
+ "pestphp/pest-dev-tools": "^2.10.0",
+ "symfony/process": "^6.3.0"
},
"bin": [
"bin/pest"
@@ -1282,7 +1355,7 @@
],
"support": {
"issues": "https://github.com/pestphp/pest/issues",
- "source": "https://github.com/pestphp/pest/tree/v2.6.1"
+ "source": "https://github.com/pestphp/pest/tree/v2.6.3"
},
"funding": [
{
@@ -1294,7 +1367,7 @@
"type": "github"
}
],
- "time": "2023-05-12T08:22:02+00:00"
+ "time": "2023-06-07T19:19:04+00:00"
},
{
"name": "pestphp/pest-plugin",
@@ -1367,27 +1440,27 @@
},
{
"name": "pestphp/pest-plugin-arch",
- "version": "v2.1.2",
+ "version": "v2.2.0",
"source": {
"type": "git",
"url": "https://github.com/pestphp/pest-plugin-arch.git",
- "reference": "485cbfbe2e194e9cfd8284625bd8922c9d27ac6f"
+ "reference": "88725fd0d6ae4025df39c27bd91e98d14b8f1916"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/pestphp/pest-plugin-arch/zipball/485cbfbe2e194e9cfd8284625bd8922c9d27ac6f",
- "reference": "485cbfbe2e194e9cfd8284625bd8922c9d27ac6f",
+ "url": "https://api.github.com/repos/pestphp/pest-plugin-arch/zipball/88725fd0d6ae4025df39c27bd91e98d14b8f1916",
+ "reference": "88725fd0d6ae4025df39c27bd91e98d14b8f1916",
"shasum": ""
},
"require": {
- "nunomaduro/collision": "^7.5.0",
+ "nunomaduro/collision": "^7.5.2",
"pestphp/pest-plugin": "^2.0.1",
"php": "^8.1",
"ta-tikoma/phpunit-architecture-test": "^0.7.3"
},
"require-dev": {
- "pestphp/pest": "^2.5.1",
- "pestphp/pest-dev-tools": "^2.6.0"
+ "pestphp/pest": "dev-develop as 2.6.2",
+ "pestphp/pest-dev-tools": "^2.10.0"
},
"type": "library",
"autoload": {
@@ -1415,7 +1488,7 @@
"unit"
],
"support": {
- "source": "https://github.com/pestphp/pest-plugin-arch/tree/v2.1.2"
+ "source": "https://github.com/pestphp/pest-plugin-arch/tree/v2.2.0"
},
"funding": [
{
@@ -1427,7 +1500,7 @@
"type": "github"
}
],
- "time": "2023-04-19T08:48:22+00:00"
+ "time": "2023-06-02T23:15:55+00:00"
},
{
"name": "phar-io/manifest",
@@ -2077,16 +2150,16 @@
},
{
"name": "phpunit/phpunit",
- "version": "10.1.3",
+ "version": "10.2.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "2379ebafc1737e71cdc84f402acb6b7f04198b9d"
+ "reference": "599b33294350e8f51163119d5670512f98b0490d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2379ebafc1737e71cdc84f402acb6b7f04198b9d",
- "reference": "2379ebafc1737e71cdc84f402acb6b7f04198b9d",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/599b33294350e8f51163119d5670512f98b0490d",
+ "reference": "599b33294350e8f51163119d5670512f98b0490d",
"shasum": ""
},
"require": {
@@ -2126,7 +2199,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "10.1-dev"
+ "dev-main": "10.2-dev"
}
},
"autoload": {
@@ -2158,7 +2231,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
- "source": "https://github.com/sebastianbergmann/phpunit/tree/10.1.3"
+ "source": "https://github.com/sebastianbergmann/phpunit/tree/10.2.1"
},
"funding": [
{
@@ -2174,7 +2247,7 @@
"type": "tidelift"
}
],
- "time": "2023-05-11T05:16:22+00:00"
+ "time": "2023-06-05T05:15:51+00:00"
},
{
"name": "psr/cache",
@@ -4751,7 +4824,9 @@
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
- "platform": [],
+ "platform": {
+ "php": ">=8.1"
+ },
"platform-dev": [],
"plugin-api-version": "2.3.0"
}
diff --git a/pint.json b/pint.json
new file mode 100644
index 0000000..ba1ad05
--- /dev/null
+++ b/pint.json
@@ -0,0 +1,56 @@
+{
+ "preset": "laravel",
+ "rules": {
+ "array_push": true,
+ "assign_null_coalescing_to_coalesce_equal": true,
+ "combine_consecutive_issets": true,
+ "combine_consecutive_unsets": true,
+ "concat_space": {
+ "spacing": "one"
+ },
+ "declare_strict_types": true,
+ "explicit_indirect_variable": true,
+ "explicit_string_variable": true,
+ "global_namespace_import": true,
+ "method_argument_space": {
+ "on_multiline": "ensure_fully_multiline"
+ },
+ "modernize_strpos": true,
+ "modernize_types_casting": true,
+ "new_with_braces": true,
+ "no_superfluous_elseif": true,
+ "no_useless_else": true,
+ "nullable_type_declaration_for_default_null_value": true,
+ "ordered_imports": {
+ "sort_algorithm": "alpha"
+ },
+ "ordered_class_elements": {
+ "order": [
+ "use_trait",
+ "case",
+ "constant",
+ "constant_public",
+ "constant_protected",
+ "constant_private",
+ "property_public",
+ "property_protected",
+ "property_private",
+ "construct",
+ "destruct",
+ "magic",
+ "phpunit",
+ "method_abstract",
+ "method_public_static",
+ "method_public",
+ "method_protected_static",
+ "method_protected",
+ "method_private_static",
+ "method_private"
+ ],
+ "sort_algorithm": "none"
+ },
+ "strict_comparison": true,
+ "ternary_to_null_coalescing": true,
+ "use_arrow_functions": true
+ }
+}
diff --git a/stubs/command.stub b/stubs/command.stub
new file mode 100644
index 0000000..4b0d976
--- /dev/null
+++ b/stubs/command.stub
@@ -0,0 +1,15 @@
+display('Hello from {{command_name}}!');
+ }
+}
diff --git a/tests/Feature/CommandTest.php b/tests/Feature/CommandTest.php
index 03a05bf..2cb3ccd 100644
--- a/tests/Feature/CommandTest.php
+++ b/tests/Feature/CommandTest.php
@@ -1,11 +1,13 @@
runCommand(['minicli', 'create']);
-})->expectOutputRegex("/librarian create/");
+})->expectOutputRegex('/librarian create/');
test('command "create content" throws error if stencil_dir is not defined', function () {
$app = getMinicli();
$app->runCommand(['minicli', 'create', 'content']);
-})->expectOutputRegex("/You must define a stencil_dir config option/");
+})->expectOutputRegex('/You must define a stencil_dir config option/');
diff --git a/tests/Pest.php b/tests/Pest.php
index 8f64f63..926538d 100644
--- a/tests/Pest.php
+++ b/tests/Pest.php
@@ -1,5 +1,7 @@
extend('toBeOne', function () {
- return $this->toBe(1);
-});
+expect()->extend('toBeOne', fn () => $this->toBe(1));
/*
|--------------------------------------------------------------------------
@@ -45,8 +45,8 @@ function getMinicli()
{
return new App([
'app_path' => [
- __DIR__ . '/../Command'
+ __DIR__ . '/../Command',
],
- 'debug' => true
+ 'debug' => true,
]);
}
diff --git a/tests/TestCase.php b/tests/TestCase.php
index cfb05b6..d42f312 100644
--- a/tests/TestCase.php
+++ b/tests/TestCase.php
@@ -1,5 +1,7 @@