Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions src/app-store/src/Command/AbstractCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);
/**
* This file is part of MineAdmin.
*
* @link https://www.mineadmin.com
* @document https://doc.mineadmin.com
* @contact root@imoi.cn
* @license https://github.com/mineadmin/MineAdmin/blob/master/LICENSE
*/

namespace Xmo\AppStore\Command;

use Hyperf\Command\Command;

abstract class AbstractCommand extends Command
{
public function __construct(string $name = null)
{
parent::__construct('mine-extension:' . $this->commandName());
}

abstract public function __invoke();

abstract public function commandName(): string;
}
149 changes: 149 additions & 0 deletions src/app-store/src/Command/CreateCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
<?php

declare(strict_types=1);
/**
* This file is part of MineAdmin.
*
* @link https://www.mineadmin.com
* @document https://doc.mineadmin.com
* @contact root@imoi.cn
* @license https://github.com/mineadmin/MineAdmin/blob/master/LICENSE
*/

namespace Xmo\AppStore\Command;

use Hyperf\Command\Annotation\Command;
use Mine\Helper\Str;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Xmo\AppStore\Enums\PluginTypeEnum;
use Xmo\AppStore\Plugin;
use Xmo\AppStore\Utils\FileSystemUtils;

#[Command]
class CreateCommand extends AbstractCommand
{
protected string $description = 'Creating Plug-ins';

public function __invoke()
{
$path = $this->input->getArgument('path');
$name = $this->input->getOption('name');
$type = $this->input->getOption('type') ?? 'mix';
$type = PluginTypeEnum::fromValue($type);
if ($type === null) {
$this->output->error('Plugin type is empty');
return;
}
if (! FileSystemUtils::checkDirectory($name)) {
$this->output->error(sprintf('The given directory name %s is not a valid directory', $path));
}
$pluginPath = Plugin::PLUGIN_PATH . '/' . $path;
if (file_exists($pluginPath)) {
$this->output->error(sprintf('Plugin directory %s already exists', $path));
return;
}
if (! mkdir($pluginPath, 0755, true) && ! is_dir($pluginPath)) {
throw new \RuntimeException(sprintf('Directory "%s" was not created', $pluginPath));
}

$this->createMineJson($pluginPath, $name, $type);
}

#[\Override]
public function commandName(): string
{
return 'create';
}

public function createMineJson(string $path, string $name, PluginTypeEnum $pluginType): void
{
$output = new \stdClass();
$output->name = $name;
$output->description = $this->input->getOption('description') ?: 'This is a sample plugin';
$author = $this->input->getOption('author') ?: 'demo';
$output->author = [
[
'name' => $author,
],
];
if ($pluginType === PluginTypeEnum::Backend || $pluginType === PluginTypeEnum::Mix) {
$namespace = 'Mine\\' . Str::snake($author) . '\\Example';

$this->createInstallScript($namespace, $path);
$this->createUninstallScript($namespace, $path);
$this->createConfigProvider($namespace, $path);
$output->composer = [
'require' => [],
'psr-4' => [
$namespace . '\\' => 'src',
],
'installScript' => $namespace . '\\InstallScript',
'uninstallScript' => $namespace . '\\UninstallScript',
'config' => $namespace . '\\ConfigProvider',
];
}

if ($pluginType === PluginTypeEnum::Mix || $pluginType === PluginTypeEnum::Frond) {
$output->package = [
'dependencies' => [
],
];
}

$output = json_encode($output, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE, 512);
file_put_contents($path . '/mine.json', $output);
$this->output->success(sprintf('%s 创建成功', $path . '/mine.json'));
}

public function createConfigProvider(string $namespace, string $path): void
{
$installScript = $this->buildStub('ConfigProvider', compact('namespace'));
$installScriptPath = $path . '/src/ConfigProvider.php';
file_put_contents($installScriptPath, $installScript);
$this->output->success(sprintf('%s Created Successfully', $installScriptPath));
}

public function createInstallScript(string $namespace, string $path): void
{
$installScript = $this->buildStub('InstallScript', compact('namespace'));
$installScriptPath = $path . '/src/InstallScript.php';
file_put_contents($installScriptPath, $installScript);
$this->output->success(sprintf('%s Created Successfully', $installScriptPath));
}

public function createUninstallScript(string $namespace, string $path): void
{
$installScript = $this->buildStub('UninstallScript', compact('namespace'));
$installScriptPath = $path . '/src/UninstallScript.php';
file_put_contents($installScriptPath, $installScript);
$this->output->success(sprintf('%s Created Successfully', $installScriptPath));
}

public function buildStub(string $stub, array $replace): string
{
$stubPath = $this->getStubDirectory() . '/' . $stub . '.stub';
if (! file_exists($stubPath)) {
throw new \RuntimeException(sprintf('File %s does not exist', $stubPath));
}
$stubBody = file_get_contents($stubPath);
foreach ($replace as $key => $value) {
$stubBody = str_replace('%' . $key . '%', $value, $stubBody);
}
return $stubBody;
}

public function getStubDirectory(): string
{
return realpath(__DIR__) . '/Stub';
}

protected function configure()
{
$this->addArgument('path', InputArgument::REQUIRED, 'Plugin Path');
$this->addOption('name', 'n', InputOption::VALUE_REQUIRED, 'Plug-in Name');
$this->addOption('type', 't', InputOption::VALUE_OPTIONAL, 'Plugin type, default mix optional mix,frond,backend');
$this->addOption('description', 'desc', InputOption::VALUE_OPTIONAL, 'Plug-in Introduction');
$this->addOption('author', 'desc', InputOption::VALUE_OPTIONAL, 'Plugin Author Information');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
use Xmo\AppStore\Service\AppStoreService;

#[Command]
class ExtensionDownloadCommand extends Base
class DownloadCommand extends Base
{
protected ?string $name = 'mine-extension:download';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
use Symfony\Component\Console\Input\InputOption;

#[Command]
class ExtensionInitialCommand extends Base
class InitialCommand extends Base
{
protected ?string $name = 'mine-extension:initial';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
use Xmo\AppStore\Service\PluginService;

#[Command]
class ExtensionInstallCommand extends Base
class InstallCommand extends Base
{
protected ?string $name = 'mine-extension:install';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
use Xmo\AppStore\Service\AppStoreService;

#[Command]
class ExtensionListCommand extends Base
class ListCommand extends Base
{
protected ?string $name = 'mine-extension:list';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
use Xmo\AppStore\Plugin;

#[Command]
class ExtensionLocalListCommand extends Base
class LocalListCommand extends Base
{
protected ?string $name = 'mine-extension:local-list';

Expand Down
20 changes: 20 additions & 0 deletions src/app-store/src/Command/Stub/ConfigProvider.stub
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php
namespace %namespace%;

class ConfigProvider
{
public function __invoke()
{
// Initial configuration
return [
// 合并到 config/autoload/annotations.php 文件
'annotations' => [
'scan' => [
'paths' => [
__DIR__,
],
],
],
];
}
}
11 changes: 11 additions & 0 deletions src/app-store/src/Command/Stub/InstallScript.stub
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace %namespace%;

class InstallScript {

public function __invoke(){
echo "Execute the command when installing the plug-in";
}

}
11 changes: 11 additions & 0 deletions src/app-store/src/Command/Stub/UninstallScript.stub
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace %namespace%;

class InstallScript {

public function __invoke(){
echo "Commands to be executed when uninstalling the plug-in";
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
use Xmo\AppStore\Service\PluginService;

#[Command]
class ExtensionUninstallCommand extends Base
class UninstallCommand extends Base
{
protected ?string $name = 'mine-extension:uninstall';

Expand Down
44 changes: 44 additions & 0 deletions src/app-store/src/Enums/PluginTypeEnum.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

declare(strict_types=1);
/**
* This file is part of MineAdmin.
*
* @link https://www.mineadmin.com
* @document https://doc.mineadmin.com
* @contact root@imoi.cn
* @license https://github.com/mineadmin/MineAdmin/blob/master/LICENSE
*/

namespace Xmo\AppStore\Enums;

/**
* Plug-in Type.
*/
enum PluginTypeEnum: string
{
/**
* Mix and match, front and back end source code included.
*/
case Mix = 'mix';

/**
* 只包含前端源码
*/
case Frond = 'frond';

/**
* Includes only the back-end source code.
*/
case Backend = 'backend';

public static function fromValue(string $value): ?self
{
return match (strtolower($value)) {
'mix' => self::Mix,
'frond' => self::Frond,
'backend' => self::Backend,
default => null
};
}
}
8 changes: 8 additions & 0 deletions src/app-store/src/Utils/FileSystemUtils.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,12 @@ public static function recovery(string $relationFilePath, string $dist): void
FileSystem::copy($backFile, $targetFile);
}
}

/**
* Checks if the given name is a valid directory path.
*/
public static function checkDirectory(string $name): bool
{
return (bool) preg_match('/^\/(?:[^\/\0]+\/)*[^\/\0]+$/', $name);
}
}