diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eec74dc..0279f10 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -176,7 +176,7 @@ jobs: uses: shivammathur/setup-php@e6f75134d35752277f093989e72e140eaa222f35 # pin@v2 with: coverage: none - tools: php-cs-fixer:3.8.0 + tools: php-cs-fixer:3.49.0 - name: Cache analysis data id: finishPrepare diff --git a/.gitignore b/.gitignore index aec3c3f..e73d216 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,14 @@ -# OS files +# os .DS_Store -# Vendor files +# vendor files /node_modules /vendor -# Cache and temporary files -/.cache -/.php-cs-fixer.cache -/.phpunit.result.cache +# cs fixer +.php-cs-fixer.cache + +# tests +.phpunit.cache /tests/coverage -/tests/*/tmp \ No newline at end of file +/tests/tmp diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index f7c903b..3957f88 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -8,13 +8,12 @@ $config = new PhpCsFixer\Config(); return $config ->setRules([ - '@PSR1' => true, - '@PSR2' => true, + '@PSR12' => true, 'align_multiline_comment' => ['comment_type' => 'phpdocs_like'], 'array_indentation' => true, 'array_syntax' => ['syntax' => 'short'], 'cast_spaces' => ['space' => 'none'], - 'class_keyword_remove' => false, + // 'class_keyword_remove' => true, // replaces static::class with 'static' (won't work) 'combine_consecutive_issets' => true, 'combine_consecutive_unsets' => true, 'combine_nested_dirname' => true, @@ -45,6 +44,7 @@ 'no_unused_imports' => true, 'no_useless_return' => true, 'ordered_imports' => ['sort_algorithm' => 'alpha'], + // 'phpdoc_add_missing_param_annotation' => ['only_untyped' => false], // adds params in the wrong order 'phpdoc_align' => ['align' => 'left'], 'phpdoc_indent' => true, 'phpdoc_scalar' => true, diff --git a/README.md b/README.md index e39b36e..7580bd0 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,7 @@ This should print the Kirby CLI version and a list of available commands ## Available core commands ``` +- kirby clean:content - kirby clear:cache - kirby clear:media - kirby clear:sessions @@ -279,7 +280,7 @@ return [ --- -© 2009-2022 Bastian Allgeier +© 2009 Bastian Allgeier [getkirby.com](https://getkirby.com) · [License agreement](./LICENSE.md) diff --git a/commands/clean/content.php b/commands/clean/content.php new file mode 100644 index 0000000..d470afb --- /dev/null +++ b/commands/clean/content.php @@ -0,0 +1,79 @@ +content($lang)->fields(); + + // unset all fields in the `$ignore` array + foreach ($ignore as $field) { + if (array_key_exists($field, $contentFields) === true) { + unset($contentFields[$field]); + } + } + + // get the keys + $contentFields = array_keys($contentFields); + + // get all field keys from blueprint + $blueprintFields = array_keys($item->blueprint()->fields()); + + // get all field keys that are in $contentFields but not in $blueprintFields + $fieldsToBeDeleted = array_diff($contentFields, $blueprintFields); + + // update page only if there are any fields to be deleted + if (count($fieldsToBeDeleted) > 0) { + + // flip keys and values and set new values to null + $data = array_map(fn ($value) => null, array_flip($fieldsToBeDeleted)); + + // try to update the page with the data + try { + $item->update($data, $lang); + } catch (Exception $e) { + throw $e->getMessage(); + } + } + } +} + +return [ + 'description' => 'Deletes all fields from page, file or user content files that are not defined in the blueprint, no matter if they contain content or not.', + 'command' => static function (CLI $cli): void { + + $cli->confirmToContinue('This will delete all fields from content files that are not defined in blueprints, no matter if they contain content or not. Are you sure?'); + + $kirby = $cli->kirby(); + + // Authenticate as almighty + $kirby->impersonate('kirby'); + + // Define your collection + $collection = $kirby->models(); + + // set the fields to be ignored + $ignore = ['uuid', 'title', 'slug', 'template', 'sort', 'focus']; + + // call the script for all languages if multilang + if ($kirby->multilang() === true) { + $languages = $kirby->languages(); + + foreach ($languages as $language) { + clean($collection, $ignore, $language->code()); + } + + } else { + clean($collection, $ignore); + } + + $cli->success('The content files have been cleaned'); + } +]; diff --git a/commands/download.php b/commands/download.php index b42b805..995f9cc 100755 --- a/commands/download.php +++ b/commands/download.php @@ -20,6 +20,7 @@ 'command' => static function (CLI $cli): void { $client = new Client(); $progress = $cli->progress()->total(100); + $file = $cli->arg('file'); try { $response = $client->get($cli->arg('url'), [ @@ -35,7 +36,7 @@ }, ]); - file_put_contents($cli->arg('file'), (string)$response->getBody()); + file_put_contents($file, (string)$response->getBody()); } catch (Throwable $e) { throw new Exception('The file could not be downloaded. (Status: ' . $e->getResponse()->getStatusCode() . ')'); } diff --git a/commands/unzip.php b/commands/unzip.php index 067272f..8b25d53 100755 --- a/commands/unzip.php +++ b/commands/unzip.php @@ -29,7 +29,7 @@ } // extract the zip file - exec('unzip ' . $file . ' -d ' . $to); + exec('unzip ' . escapeshellarg($file) . ' -d ' . escapeshellarg($to)); $to = realpath($to); @@ -40,7 +40,7 @@ throw new Exception('The archive directory could not be found'); } - exec('mv ' . $to . '/*/{.[!.],}* ' . $to . '/'); - exec('rm -rf ' . $archive); + exec('mv ' . escapeshellarg($to) . '/*/{.[!.],}* ' . escapeshellarg($to) . '/'); + exec('rm -rf ' . escapeshellarg($archive)); } ]; diff --git a/composer.json b/composer.json index a5627a8..c6a51c0 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,7 @@ "name": "getkirby/cli", "description": "Kirby command line interface", "license": "MIT", - "version": "1.2.0", + "version": "1.3.0", "keywords": [ "kirby", "cms", diff --git a/composer.lock b/composer.lock index a85e0d6..faffede 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "f843b10a4714c43702cdb0414727e0e9", + "content-hash": "919c6e5cb0284e3c87cf7cf7b6d96eb0", "packages": [ { "name": "guzzlehttp/guzzle", diff --git a/phpunit.xml.dist b/phpunit.xml.dist index a64a205..28dbd48 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,32 +1,41 @@ - - + - - - ./src - - - - ./src/Kql/Interceptors - - + + + ./src + + - - ./tests - - + + ./tests + + + + + + - - - + diff --git a/src/CLI/CLI.php b/src/CLI/CLI.php index 58614e1..58a2471 100644 --- a/src/CLI/CLI.php +++ b/src/CLI/CLI.php @@ -518,12 +518,11 @@ public function run(?string $name = null, ...$args): void ...$args ]; - $exception = null; - try { $this->climate->arguments->parse($argv); } catch (Throwable $e) { - $exception = $e; + $this->error($e->getMessage()); + exit; } // enable quiet mode @@ -537,10 +536,6 @@ public function run(?string $name = null, ...$args): void return; } - if ($exception !== null) { - throw $exception; - } - $command['command']($this); }