├── LICENSE ├── README.md ├── bin └── aplus ├── composer.json └── src ├── Commands ├── Index.php ├── NewApp.php ├── NewCommand.php └── NewOne.php ├── aplus.php └── preload.php /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Natan Felles 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Aplus Command Line Tool 2 | 3 | # Aplus Command Line Tool 4 | 5 | - [Home](https://aplus-framework.com/packages/aplus) 6 | - [User Guide](https://docs.aplus-framework.com/guides/aplus/index.html) 7 | 8 | [![tests](https://github.com/aplus-framework/aplus/actions/workflows/tests.yml/badge.svg)](https://github.com/aplus-framework/aplus/actions/workflows/tests.yml) 9 | [![coverage](https://coveralls.io/repos/github/aplus-framework/aplus/badge.svg?branch=master)](https://coveralls.io/github/aplus-framework/aplus?branch=master) 10 | [![packagist](https://img.shields.io/packagist/v/aplus/aplus)](https://packagist.org/packages/aplus/aplus) 11 | [![open-source](https://img.shields.io/badge/open--source-sponsor-magenta)](https://aplus-framework.com/sponsor) 12 | -------------------------------------------------------------------------------- /bin/aplus: -------------------------------------------------------------------------------- 1 | ../src/aplus.php -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "aplus/aplus", 3 | "description": "Aplus Command Line Tool", 4 | "license": "MIT", 5 | "type": "library", 6 | "keywords": [ 7 | "aplus", 8 | "cli", 9 | "framework", 10 | "installer", 11 | "preload", 12 | "tool" 13 | ], 14 | "authors": [ 15 | { 16 | "name": "Natan Felles", 17 | "email": "natanfelles@gmail.com", 18 | "homepage": "https://natanfelles.github.io" 19 | } 20 | ], 21 | "homepage": "https://aplus-framework.com/packages/aplus", 22 | "support": { 23 | "email": "support@aplus-framework.com", 24 | "issues": "https://github.com/aplus-framework/aplus/issues", 25 | "forum": "https://aplus-framework.com/forum", 26 | "source": "https://github.com/aplus-framework/aplus", 27 | "docs": "https://docs.aplus-framework.com/guides/aplus/" 28 | }, 29 | "funding": [ 30 | { 31 | "type": "Aplus Sponsor", 32 | "url": "https://aplus-framework.com/sponsor" 33 | } 34 | ], 35 | "require": { 36 | "php": ">=8.1", 37 | "ext-posix": "*", 38 | "aplus/app": "^23", 39 | "aplus/framework": "^23", 40 | "aplus/one": "^23" 41 | }, 42 | "require-dev": { 43 | "ext-xdebug": "*", 44 | "aplus/coding-standard": "^1.12", 45 | "ergebnis/composer-normalize": "^2.25", 46 | "phpmd/phpmd": "^2.12", 47 | "phpstan/phpstan": "^1.5", 48 | "phpunit/phpunit": "^9.5" 49 | }, 50 | "minimum-stability": "dev", 51 | "prefer-stable": true, 52 | "autoload": { 53 | "psr-4": { 54 | "Aplus\\": "src/" 55 | } 56 | }, 57 | "autoload-dev": { 58 | "psr-4": { 59 | "Tests\\": "tests/" 60 | } 61 | }, 62 | "bin": [ 63 | "bin/aplus" 64 | ], 65 | "config": { 66 | "allow-plugins": { 67 | "ergebnis/composer-normalize": true 68 | }, 69 | "optimize-autoloader": true, 70 | "preferred-install": "dist", 71 | "sort-packages": true 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/Commands/Index.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | namespace Aplus\Commands; 11 | 12 | use Aplus; 13 | use Framework\CLI\CLI; 14 | 15 | /** 16 | * Class Index. 17 | * 18 | * @package aplus 19 | */ 20 | class Index extends \Framework\CLI\Commands\Index 21 | { 22 | public function run() : void 23 | { 24 | $this->showHeader(); 25 | $this->showDate(); 26 | $this->showInfo(); 27 | if ($this->console->getOption('g')) { 28 | $this->greet(); 29 | } 30 | $this->listCommands(); 31 | } 32 | 33 | protected function showInfo() : void 34 | { 35 | $distro = \PHP_OS_FAMILY; 36 | if ($distro === 'Linux' && \is_file('/etc/lsb-release')) { 37 | $contents = \file_get_contents('/etc/lsb-release'); 38 | if ($contents) { 39 | $lsb = (array) \parse_ini_string($contents); 40 | if (isset($lsb['DISTRIB_ID'], $lsb['DISTRIB_RELEASE'])) { 41 | $distro = $lsb['DISTRIB_ID'] . ' ' . $lsb['DISTRIB_RELEASE']; 42 | } 43 | } 44 | } 45 | CLI::write( 46 | 'Running Aplus ' . Aplus::VERSION 47 | . ' on ' . $distro 48 | . ' with PHP ' . \PHP_VERSION 49 | ); 50 | CLI::newLine(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Commands/NewApp.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | namespace Aplus\Commands; 11 | 12 | /** 13 | * Class NewApp. 14 | * 15 | * @package aplus 16 | */ 17 | class NewApp extends NewCommand 18 | { 19 | protected string $name = 'new-app'; 20 | protected string $description = 'Creates a new App Project.'; 21 | protected string $usage = 'new-app [options] [directory]'; 22 | 23 | public function run() : void 24 | { 25 | $this->create('app', 'App Project'); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Commands/NewCommand.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | namespace Aplus\Commands; 11 | 12 | use Framework\CLI\CLI; 13 | use Framework\CLI\Command; 14 | use RecursiveDirectoryIterator; 15 | use RecursiveIteratorIterator; 16 | 17 | /** 18 | * Class NewCommand. 19 | * 20 | * @package aplus 21 | */ 22 | abstract class NewCommand extends Command 23 | { 24 | protected function create(string $package, string $name) : void 25 | { 26 | $directory = $this->getDirectory(); 27 | $source = $this->getComposerSource($package); 28 | if ( ! $source) { 29 | $source = $this->getComposerSource($package, true); 30 | if ( ! $source) { 31 | $source = $this->getDistroSource($package); 32 | } 33 | } 34 | if ( ! $source) { 35 | CLI::error('Package aplus/' . $package . ' not found'); 36 | return; 37 | } 38 | $this->copyDir($source, $directory); 39 | CLI::write( 40 | $name . ' structure created at "' . $directory . '"', 41 | CLI::FG_GREEN 42 | ); 43 | } 44 | 45 | protected function getComposerSource(string $package, bool $global = false) : false | string 46 | { 47 | $source = $global 48 | ? __DIR__ . '/../../../../../' 49 | : __DIR__ . '/../../'; 50 | $source .= 'vendor/aplus/' . $package; 51 | if (\is_dir($source)) { 52 | return \realpath($source); 53 | } 54 | return false; 55 | } 56 | 57 | protected function getDistroSource(string $package) : false | string 58 | { 59 | $source = __DIR__ . '/../../../../packages/' . $package; 60 | if (\is_dir($source)) { 61 | return \realpath($source); 62 | } 63 | return false; 64 | } 65 | 66 | protected function copyDir(string $source, string $directory) : void 67 | { 68 | $iterator = new RecursiveIteratorIterator( 69 | new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS), 70 | RecursiveIteratorIterator::SELF_FIRST 71 | ); 72 | foreach ($iterator as $item) { 73 | if ($item->isDir()) { 74 | $dir = $directory . \DIRECTORY_SEPARATOR . $iterator->getSubPathname(); 75 | if ( ! \mkdir($dir, 0755, true) && ! \is_dir($dir)) { 76 | CLI::error( 77 | \sprintf('Directory "%s" could not be created', $dir) 78 | ); 79 | } 80 | continue; 81 | } 82 | \copy((string) $item, $directory . \DIRECTORY_SEPARATOR . $iterator->getSubPathname()); 83 | } 84 | } 85 | 86 | protected function getDirectory() : string 87 | { 88 | $directory = $this->console->getArgument(0); 89 | if ($directory === null) { 90 | $directory = $this->promptDirectory(); 91 | } 92 | if ( ! \str_starts_with($directory, '/')) { 93 | $directory = \getcwd() . '/' . $directory; 94 | } 95 | if (\file_exists($directory)) { 96 | CLI::error( 97 | \sprintf('The path "%s" already exists', $directory) 98 | ); 99 | } 100 | if ( ! \mkdir($directory, 0755, true) && ! \is_dir($directory)) { 101 | CLI::error( 102 | \sprintf('Directory "%s" could not be created', $directory) 103 | ); 104 | } 105 | $realpath = \realpath($directory); 106 | if ($realpath === false) { 107 | CLI::error( 108 | \sprintf('Was not possible get the realpath of "%s"', $directory) 109 | ); 110 | } 111 | return $realpath; // @phpstan-ignore-line 112 | } 113 | 114 | protected function promptDirectory() : string 115 | { 116 | $directory = CLI::prompt('Directory'); 117 | $directory = \trim($directory); 118 | if ($directory === '') { 119 | CLI::error('Directory path cannot be empty. Try again.', null); 120 | return $this->promptDirectory(); 121 | } 122 | if ( ! \str_starts_with($directory, '/')) { 123 | $directory = \getcwd() . '/' . $directory; 124 | } 125 | if (\file_exists($directory)) { 126 | CLI::error('Directory already exists. Try Again.', null); 127 | return $this->promptDirectory(); 128 | } 129 | return $directory; 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/Commands/NewOne.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | namespace Aplus\Commands; 11 | 12 | /** 13 | * Class NewOne. 14 | * 15 | * @package aplus 16 | */ 17 | class NewOne extends NewCommand 18 | { 19 | protected string $name = 'new-one'; 20 | protected string $description = 'Creates a new One Project.'; 21 | protected string $usage = 'new-one [options] [directory]'; 22 | 23 | public function run() : void 24 | { 25 | $this->create('one', 'One Project'); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/aplus.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | if (is_file(__DIR__ . '/../../../autoload.php')) { 12 | require __DIR__ . '/../../../autoload.php'; 13 | } else { 14 | require __DIR__ . '/../vendor/autoload.php'; 15 | } 16 | 17 | use Aplus\Commands\Index; 18 | use Aplus\Commands\NewApp; 19 | use Aplus\Commands\NewOne; 20 | use Framework\CLI\Console; 21 | 22 | $console = new Console(); 23 | $console->addCommand(Index::class); 24 | $console->addCommand(NewApp::class); 25 | $console->addCommand(NewOne::class); 26 | $console->run(); 27 | -------------------------------------------------------------------------------- /src/preload.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | if (is_file(__DIR__ . '/../../autoload/src/Preloader.php')) { 11 | require __DIR__ . '/../../autoload/src/Preloader.php'; 12 | } else { 13 | require __DIR__ . '/../vendor/aplus/autoload/src/Preloader.php'; 14 | } 15 | 16 | use Framework\Autoload\Preloader; 17 | 18 | (new Preloader())->load(); 19 | --------------------------------------------------------------------------------