新增:设备归属和解除归属原因

This commit is contained in:
celaraze 2023-09-18 10:04:56 +08:00
parent 3701c42cad
commit 405cd57d77
32 changed files with 262 additions and 224 deletions

View File

@ -22,7 +22,7 @@ class DeviceRecordCreateUpdateTrackAction extends RowAction
*
* @return Modal|string
*/
public function render()
public function render(): string|Modal
{
// 实例化表单类并传递自定义参数
$form = DeviceRecordCreateUpdateTrackForm::make()->payload([

View File

@ -2,16 +2,18 @@
namespace App\Admin\Actions\Show;
use App\Admin\Forms\DeviceRecordDeleteTrackForm;
use App\Models\DeviceTrack;
use Dcat\Admin\Actions\Response;
use Dcat\Admin\Show\AbstractTool;
use Dcat\Admin\Widgets\Modal;
class DeviceRecordDeleteTrackAction extends AbstractTool
{
public function __construct()
{
parent::__construct();
$this->title = '<i class="fa fa-fw feather icon-trash"></i> ' . admin_trans_label('Track Delete');
$this->title = '<a class="btn btn-sm btn-primary" style="color: white;"><i class="fa fa-fw feather icon-trash"></i> ' . admin_trans_label('Track Delete') . '</a>';
}
/**
@ -35,11 +37,23 @@ class DeviceRecordDeleteTrackAction extends AbstractTool
->refresh();
}
/**
* @return array
* 渲染模态框.
*
* @return Modal|string
*/
public function confirm(): array
public function render(): string|Modal
{
return [admin_trans_label('Track Delete Confirm')];
// 实例化表单类并传递自定义参数
$form = DeviceRecordDeleteTrackForm::make()->payload([
'id' => $this->getKey(),
]);
return Modal::make()
->lg()
->title(admin_trans_label('Track Delete'))
->body($form)
->button($this->title);
}
}

View File

@ -159,7 +159,7 @@ class DeviceRecordController extends AdminController
/**
* 自定义字段.
*/
ControllerHasCustomColumns::makeDetail((new DeviceRecord())->getTable(), $show, $sort_columns);
self::makeDetail((new DeviceRecord())->getTable(), $show, $sort_columns);
$show->field('created_at', '', $sort_columns);
$show->field('updated_at', '', $sort_columns);
@ -280,7 +280,7 @@ class DeviceRecordController extends AdminController
/**
* 自定义字段.
*/
ControllerHasCustomColumns::makeGrid((new DeviceRecord())->getTable(), $grid, $sort_columns);
self::makeGrid((new DeviceRecord())->getTable(), $grid, $sort_columns);
/**
* 批量操作.
@ -415,7 +415,7 @@ class DeviceRecordController extends AdminController
'expired',
'admin_user.name',
'admin_user.department.name',
], ControllerHasCustomColumns::makeQuickSearch((new DeviceRecord())->getTable()))
], self::makeQuickSearch((new DeviceRecord())->getTable()))
)
->placeholder(trans('main.quick_search'))
->auto(false);
@ -489,7 +489,7 @@ class DeviceRecordController extends AdminController
/**
* 自定义字段.
*/
ControllerHasCustomColumns::makeFilter((new DeviceRecord())->getTable(), $filter);
self::makeFilter((new DeviceRecord())->getTable(), $filter);
});
/**

View File

@ -87,6 +87,8 @@ class DeviceRecordCreateUpdateTrackForm extends Form implements LazyRenderable
return $this->response()
->error(trans('main.record_same'));
} else {
$device_track->setAttribute('deleted_description', '(自动生成)管理者重新分配使用者。');
$device_track->save();
$device_track->delete();
}
}
@ -95,6 +97,7 @@ class DeviceRecordCreateUpdateTrackForm extends Form implements LazyRenderable
$device_track = new DeviceTrack();
$device_track->device_id = $device_id;
$device_track->user_id = $user_id;
$device_track->setAttribute('description', $input['description']);
if ($type == 'lend') {
$device_track->user_id = $lend_user_id;
@ -131,6 +134,8 @@ class DeviceRecordCreateUpdateTrackForm extends Form implements LazyRenderable
$form->select('user_id', trans('main.new_user_id'))
->options($users)
->help(trans('main.user_id_help'));
$form->text('description', trans('main.device_track_description'))
->required();
})
->when('lend', function (Form $form) use ($users) {
$form->select('lend_user_id', trans('main.new_user_id'))

View File

@ -0,0 +1,71 @@
<?php
namespace App\Admin\Forms;
use App\Models\DeviceRecord;
use App\Models\DeviceTrack;
use Dcat\Admin\Contracts\LazyRenderable;
use Dcat\Admin\Http\JsonResponse;
use Dcat\Admin\Traits\LazyWidget;
use Dcat\Admin\Widgets\Form;
class DeviceRecordDeleteTrackForm extends Form implements LazyRenderable
{
use LazyWidget;
/**
* 处理表单提交逻辑.
*
* @param array $input
*
* @return JsonResponse
*/
public function handle(array $input): JsonResponse
{
// 获取设备id
$device_id = $this->payload['id'] ?? null;
// 获取设备解除归属原因,来自表单传参
$deleted_description = $input['deleted_description'] ?? null;
// 如果没有设备id或者解除归属原因则返回错误
if (!$device_id || !$deleted_description) {
return $this->response()
->error(trans('main.parameter_missing'));
}
// 设备记录
$device = DeviceRecord::where('id', $device_id)->first();
// 如果没有找到这个设备记录则返回错误
if (!$device) {
return $this->response()
->error(trans('main.record_none'));
}
// 设备追踪
$device_track = DeviceTrack::where('device_id', $device_id)->first();
// 如果没有设备追踪
if (empty($device_track)) {
return $this->response()
->error(trans('main.record_none'));
}
$device_track->setAttribute('deleted_description', $deleted_description);
$device_track->save();
$device_track->delete();
return $this->response()
->success(trans('main.success'))
->refresh();
}
/**
* 构造表单.
*/
public function form()
{
$this->text('deleted_description')
->required();
}
}

View File

@ -31,6 +31,7 @@ class DeviceService
'status' => '',
'style' => '',
'datetime' => '',
'description' => ''
];
// 处理设备使用者变动履历

View File

@ -61,14 +61,16 @@ class Support
*
* @return array
*/
public static function itemTrack($template, $item_track, $data = []): array
public static function itemTrack($template, $item_track, array $data = []): array
{
$template['status'] = '+';
$template['datetime'] = json_decode($item_track, true)['created_at'];
$template['description'] = json_decode($item_track, true)['description'];
$data[] = $template;
if (!empty($item_track->deleted_at)) {
$template['status'] = '-';
$template['datetime'] = json_decode($item_track, true)['deleted_at'];
$template['description'] = json_decode($item_track, true)['deleted_description'];
$data[] = $template;
}

View File

@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('device_tracks', function (Blueprint $table) {
$table->string('description')->nullable()->after('user_id')->comment('归属原因');
$table->string('deleted_description')->nullable()->after('description')->comment('解除归属原因');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('device_tracks', function (Blueprint $table) {
$table->dropColumn(['description', 'deleted_description']);
});
}
};

View File

@ -109,7 +109,8 @@ return [
'file' => '文件',
'depreciation_rule_id' => '折旧规则',
'device_status' => '设备状态',
'no_user' => '闲置'
'no_user' => '闲置',
'deleted_description' => '解除归属原因'
],
'options' => [
],

View File

@ -136,5 +136,6 @@ return [
'device_category' => '设备分类',
'part_category' => '配件分类',
'software_category' => '软件分类',
'consumable_category' => '耗材分类'
'consumable_category' => '耗材分类',
'device_track_description' => '归属原因',
];

View File

@ -12,7 +12,7 @@
关联了 {{$item['type']}}
</h3>
<div class="timeline-body">
{{$item['name']}}
{{$item['name']}}。原因:{{$item['description']}}
</div>
</div>
@else
@ -23,7 +23,7 @@
解除了 {{$item['type']}}
</h3>
<div class="timeline-body">
{{$item['name']}}
{{$item['name']}}。原因:{{$item['description']}}
</div>
</div>
@endif

10
vendor/bin/psysh vendored Normal file → Executable file
View File

@ -108,12 +108,10 @@ if (PHP_VERSION_ID < 80000) {
}
}
if (
(function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
|| (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
) {
return include("phpvfscomposer://" . __DIR__ . '/..'.'/psy/psysh/bin/psysh');
if (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper')) {
include("phpvfscomposer://" . __DIR__ . '/..'.'/psy/psysh/bin/psysh');
exit(0);
}
}
return include __DIR__ . '/..'.'/psy/psysh/bin/psysh';
include __DIR__ . '/..'.'/psy/psysh/bin/psysh';

View File

@ -1,5 +0,0 @@
@ECHO OFF
setlocal DISABLEDELAYEDEXPANSION
SET BIN_TARGET=%~dp0/psysh
SET COMPOSER_RUNTIME_BIN_DIR=%~dp0
php "%BIN_TARGET%" %*

View File

@ -295,6 +295,7 @@ return array(
'App\\Admin\\Forms\\DeviceRecordBatchCreateUpdateTrackForm' => $baseDir . '/app/Admin/Forms/DeviceRecordBatchCreateUpdateTrackForm.php',
'App\\Admin\\Forms\\DeviceRecordCreateUpdateTrackForm' => $baseDir . '/app/Admin/Forms/DeviceRecordCreateUpdateTrackForm.php',
'App\\Admin\\Forms\\DeviceRecordDeleteForm' => $baseDir . '/app/Admin/Forms/DeviceRecordDeleteForm.php',
'App\\Admin\\Forms\\DeviceRecordDeleteTrackForm' => $baseDir . '/app/Admin/Forms/DeviceRecordDeleteTrackForm.php',
'App\\Admin\\Forms\\DeviceRecordImportForm' => $baseDir . '/app/Admin/Forms/DeviceRecordImportForm.php',
'App\\Admin\\Forms\\DeviceRecordTagPrintForm' => $baseDir . '/app/Admin/Forms/DeviceRecordTagPrintForm.php',
'App\\Admin\\Forms\\DeviceTrackUpdateDeleteForm' => $baseDir . '/app/Admin/Forms/DeviceTrackUpdateDeleteForm.php',
@ -6131,6 +6132,7 @@ return array(
'Psy\\CodeCleaner\\ValidFunctionNamePass' => $vendorDir . '/psy/psysh/src/CodeCleaner/ValidFunctionNamePass.php',
'Psy\\Command\\BufferCommand' => $vendorDir . '/psy/psysh/src/Command/BufferCommand.php',
'Psy\\Command\\ClearCommand' => $vendorDir . '/psy/psysh/src/Command/ClearCommand.php',
'Psy\\Command\\CodeArgumentParser' => $vendorDir . '/psy/psysh/src/Command/CodeArgumentParser.php',
'Psy\\Command\\Command' => $vendorDir . '/psy/psysh/src/Command/Command.php',
'Psy\\Command\\DocCommand' => $vendorDir . '/psy/psysh/src/Command/DocCommand.php',
'Psy\\Command\\DumpCommand' => $vendorDir . '/psy/psysh/src/Command/DumpCommand.php',

View File

@ -32,10 +32,10 @@ return array(
'c7a3c339e7e14b60e06a2d7fcce9476b' => $vendorDir . '/laravel/framework/src/Illuminate/Events/functions.php',
'f0906e6318348a765ffb6eb24e0d0938' => $vendorDir . '/laravel/framework/src/Illuminate/Foundation/helpers.php',
'58571171fd5812e6e447dce228f52f4d' => $vendorDir . '/laravel/framework/src/Illuminate/Support/helpers.php',
'801c31d8ed748cfa537fa45402288c95' => $vendorDir . '/psy/psysh/src/functions.php',
'8825ede83f2f289127722d4e842cf7e8' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php',
'fe62ba7e10580d903cc46d808b5961a4' => $vendorDir . '/tightenco/collect/src/Collect/Support/helpers.php',
'caf31cc6ec7cf2241cb6f12c226c3846' => $vendorDir . '/tightenco/collect/src/Collect/Support/alias.php',
'801c31d8ed748cfa537fa45402288c95' => $vendorDir . '/psy/psysh/src/functions.php',
'dc1275c308c5b416beb314b6317daca2' => $vendorDir . '/overtrue/pinyin/src/const.php',
'320163ac6b93aebe3dc25b60a0533d56' => $vendorDir . '/spatie/laravel-ignition/src/helpers.php',
'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php',

View File

@ -33,10 +33,10 @@ class ComposerStaticInitab540f0684551bbb4b79f360b913ca88
'c7a3c339e7e14b60e06a2d7fcce9476b' => __DIR__ . '/..' . '/laravel/framework/src/Illuminate/Events/functions.php',
'f0906e6318348a765ffb6eb24e0d0938' => __DIR__ . '/..' . '/laravel/framework/src/Illuminate/Foundation/helpers.php',
'58571171fd5812e6e447dce228f52f4d' => __DIR__ . '/..' . '/laravel/framework/src/Illuminate/Support/helpers.php',
'801c31d8ed748cfa537fa45402288c95' => __DIR__ . '/..' . '/psy/psysh/src/functions.php',
'8825ede83f2f289127722d4e842cf7e8' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/bootstrap.php',
'fe62ba7e10580d903cc46d808b5961a4' => __DIR__ . '/..' . '/tightenco/collect/src/Collect/Support/helpers.php',
'caf31cc6ec7cf2241cb6f12c226c3846' => __DIR__ . '/..' . '/tightenco/collect/src/Collect/Support/alias.php',
'801c31d8ed748cfa537fa45402288c95' => __DIR__ . '/..' . '/psy/psysh/src/functions.php',
'dc1275c308c5b416beb314b6317daca2' => __DIR__ . '/..' . '/overtrue/pinyin/src/const.php',
'320163ac6b93aebe3dc25b60a0533d56' => __DIR__ . '/..' . '/spatie/laravel-ignition/src/helpers.php',
'b6b991a57620e2fb6b2f66f03fe9ddc2' => __DIR__ . '/..' . '/symfony/string/Resources/functions.php',
@ -954,6 +954,7 @@ class ComposerStaticInitab540f0684551bbb4b79f360b913ca88
'App\\Admin\\Forms\\DeviceRecordBatchCreateUpdateTrackForm' => __DIR__ . '/../..' . '/app/Admin/Forms/DeviceRecordBatchCreateUpdateTrackForm.php',
'App\\Admin\\Forms\\DeviceRecordCreateUpdateTrackForm' => __DIR__ . '/../..' . '/app/Admin/Forms/DeviceRecordCreateUpdateTrackForm.php',
'App\\Admin\\Forms\\DeviceRecordDeleteForm' => __DIR__ . '/../..' . '/app/Admin/Forms/DeviceRecordDeleteForm.php',
'App\\Admin\\Forms\\DeviceRecordDeleteTrackForm' => __DIR__ . '/../..' . '/app/Admin/Forms/DeviceRecordDeleteTrackForm.php',
'App\\Admin\\Forms\\DeviceRecordImportForm' => __DIR__ . '/../..' . '/app/Admin/Forms/DeviceRecordImportForm.php',
'App\\Admin\\Forms\\DeviceRecordTagPrintForm' => __DIR__ . '/../..' . '/app/Admin/Forms/DeviceRecordTagPrintForm.php',
'App\\Admin\\Forms\\DeviceTrackUpdateDeleteForm' => __DIR__ . '/../..' . '/app/Admin/Forms/DeviceTrackUpdateDeleteForm.php',
@ -6790,6 +6791,7 @@ class ComposerStaticInitab540f0684551bbb4b79f360b913ca88
'Psy\\CodeCleaner\\ValidFunctionNamePass' => __DIR__ . '/..' . '/psy/psysh/src/CodeCleaner/ValidFunctionNamePass.php',
'Psy\\Command\\BufferCommand' => __DIR__ . '/..' . '/psy/psysh/src/Command/BufferCommand.php',
'Psy\\Command\\ClearCommand' => __DIR__ . '/..' . '/psy/psysh/src/Command/ClearCommand.php',
'Psy\\Command\\CodeArgumentParser' => __DIR__ . '/..' . '/psy/psysh/src/Command/CodeArgumentParser.php',
'Psy\\Command\\Command' => __DIR__ . '/..' . '/psy/psysh/src/Command/Command.php',
'Psy\\Command\\DocCommand' => __DIR__ . '/..' . '/psy/psysh/src/Command/DocCommand.php',
'Psy\\Command\\DumpCommand' => __DIR__ . '/..' . '/psy/psysh/src/Command/DumpCommand.php',

View File

@ -5571,17 +5571,17 @@
},
{
"name": "psy/psysh",
"version": "v0.11.20",
"version_normalized": "0.11.20.0",
"version": "v0.11.21",
"version_normalized": "0.11.21.0",
"source": {
"type": "git",
"url": "https://github.com/bobthecow/psysh.git",
"reference": "0fa27040553d1d280a67a4393194df5228afea5b"
"reference": "bcb22101107f3bf770523b65630c9d547f60c540"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/bobthecow/psysh/zipball/0fa27040553d1d280a67a4393194df5228afea5b",
"reference": "0fa27040553d1d280a67a4393194df5228afea5b",
"url": "https://api.github.com/repos/bobthecow/psysh/zipball/bcb22101107f3bf770523b65630c9d547f60c540",
"reference": "bcb22101107f3bf770523b65630c9d547f60c540",
"shasum": ""
},
"require": {
@ -5604,7 +5604,7 @@
"ext-posix": "If you have PCNTL, you'll want the POSIX extension as well.",
"ext-readline": "Enables support for arrow-key history navigation, and showing and manipulating command history."
},
"time": "2023-07-31T14:32:22+00:00",
"time": "2023-09-17T21:15:54+00:00",
"bin": [
"bin/psysh"
],
@ -5612,6 +5612,10 @@
"extra": {
"branch-alias": {
"dev-main": "0.11.x-dev"
},
"bamarni-bin": {
"bin-links": false,
"forward-command": false
}
},
"installation-source": "dist",
@ -5644,7 +5648,7 @@
],
"support": {
"issues": "https://github.com/bobthecow/psysh/issues",
"source": "https://github.com/bobthecow/psysh/tree/v0.11.20"
"source": "https://github.com/bobthecow/psysh/tree/v0.11.21"
},
"install-path": "../psy/psysh"
},

View File

@ -5,7 +5,7 @@
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'reference' => 'f7569774a761f4d250164880c59437e98c4300e8',
'reference' => '3701c42cad005a8d3fe609c0ffe578b69019c675',
'name' => 'celaraze/chemex',
'dev' => true,
),
@ -52,7 +52,7 @@
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'reference' => 'f7569774a761f4d250164880c59437e98c4300e8',
'reference' => '3701c42cad005a8d3fe609c0ffe578b69019c675',
'dev_requirement' => false,
),
'celaraze/laravel-ace' => array(
@ -959,12 +959,12 @@
),
),
'psy/psysh' => array(
'pretty_version' => 'v0.11.20',
'version' => '0.11.20.0',
'pretty_version' => 'v0.11.21',
'version' => '0.11.21.0',
'type' => 'library',
'install_path' => __DIR__ . '/../psy/psysh',
'aliases' => array(),
'reference' => '0fa27040553d1d280a67a4393194df5228afea5b',
'reference' => 'bcb22101107f3bf770523b65630c9d547f60c540',
'dev_requirement' => false,
),
'ralouphie/getallheaders' => array(

0
vendor/psy/psysh/bin/psysh vendored Normal file → Executable file
View File

View File

@ -49,6 +49,10 @@
"extra": {
"branch-alias": {
"dev-main": "0.11.x-dev"
},
"bamarni-bin": {
"bin-links": false,
"forward-command": false
}
},
"conflict": {

View File

@ -0,0 +1,59 @@
<?php
/*
* This file is part of Psy Shell.
*
* (c) 2012-2023 Justin Hileman
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Psy\Command;
use PhpParser\Parser;
use Psy\Exception\ParseErrorException;
use Psy\ParserFactory;
/**
* Class CodeArgumentParser.
*/
class CodeArgumentParser
{
private $parser;
public function __construct(Parser $parser = null)
{
$this->parser = $parser ?? (new ParserFactory())->createParser();
}
/**
* Lex and parse a string of code into statements.
*
* This is intended for code arguments, so the code string *should not* start with <?php
*
* @throws ParseErrorException
*
* @return array Statements
*/
public function parse(string $code): array
{
$code = '<?php '.$code;
try {
return $this->parser->parse($code);
} catch (\PhpParser\Error $e) {
if (\strpos($e->getMessage(), 'unexpected EOF') === false) {
throw ParseErrorException::fromParseError($e);
}
// If we got an unexpected EOF, let's try it again with a semicolon.
try {
return $this->parser->parse($code.';');
} catch (\PhpParser\Error $_e) {
// Throw the original error, not the semicolon one.
throw ParseErrorException::fromParseError($e);
}
}
}
}

View File

@ -15,7 +15,6 @@ use Psy\Shell;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command as BaseCommand;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Helper\TableHelper;
use Symfony\Component\Console\Helper\TableStyle;
use Symfony\Component\Console\Output\OutputInterface;
@ -231,16 +230,10 @@ abstract class Command extends BaseCommand
/**
* Get a Table instance.
*
* Falls back to legacy TableHelper.
*
* @return Table|TableHelper
* @return Table
*/
protected function getTable(OutputInterface $output)
{
if (!\class_exists(Table::class)) {
return $this->getTableHelper();
}
$style = new TableStyle();
// Symfony 4.1 deprecated single-argument style setters.
@ -260,18 +253,4 @@ abstract class Command extends BaseCommand
->setRows([])
->setStyle($style);
}
/**
* Legacy fallback for getTable.
*/
protected function getTableHelper(): TableHelper
{
$table = $this->getApplication()->getHelperSet()->get('table');
return $table
->setRows([])
->setLayout(TableHelper::LAYOUT_BORDERLESS)
->setHorizontalBorderChar('')
->setCrossingChar('');
}
}

View File

@ -12,7 +12,6 @@
namespace Psy\Command;
use Psy\Output\ShellOutput;
use Symfony\Component\Console\Helper\TableHelper;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
@ -93,11 +92,7 @@ class HelpCommand extends Command
$output->startPaging();
}
if ($table instanceof TableHelper) {
$table->render($output);
} else {
$table->render();
}
$table->render();
if ($output instanceof ShellOutput) {
$output->stopPaging();

View File

@ -26,7 +26,6 @@ use Psy\Output\ShellOutput;
use Psy\VarDumper\Presenter;
use Psy\VarDumper\PresenterAware;
use Symfony\Component\Console\Formatter\OutputFormatter;
use Symfony\Component\Console\Helper\TableHelper;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
@ -213,11 +212,7 @@ HELP
$table->addRow([$this->formatItemName($item), $item['value']]);
}
if ($table instanceof TableHelper) {
$table->render($output);
} else {
$table->render();
}
$table->render();
}
}

View File

@ -122,13 +122,10 @@ HELP
protected function execute(InputInterface $input, OutputInterface $output)
{
$code = $input->getArgument('code');
if (\strpos($code, '<?') === false) {
$code = '<?php '.$code;
}
$parserKind = $input->getOption('kind');
$depth = $input->getOption('depth');
$nodes = $this->parse($this->getParser($parserKind), $code);
$nodes = $this->getParser($parserKind)->parse($code);
$output->page($this->presenter->present($nodes, $depth));
$this->context->setReturnValue($nodes);
@ -136,37 +133,15 @@ HELP
return 0;
}
/**
* Lex and parse a string of code into statements.
*
* @param Parser $parser
* @param string $code
*
* @return array Statements
*/
private function parse(Parser $parser, string $code): array
{
try {
return $parser->parse($code);
} catch (\PhpParser\Error $e) {
if (\strpos($e->getMessage(), 'unexpected EOF') === false) {
throw $e;
}
// If we got an unexpected EOF, let's try it again with a semicolon.
return $parser->parse($code.';');
}
}
/**
* Get (or create) the Parser instance.
*
* @param string|null $kind One of Psy\ParserFactory constants (only for PHP parser 2.0 and above)
*/
private function getParser(string $kind = null): Parser
private function getParser(string $kind = null): CodeArgumentParser
{
if (!\array_key_exists($kind, $this->parsers)) {
$this->parsers[$kind] = $this->parserFactory->createParser($kind);
$this->parsers[$kind] = new CodeArgumentParser($this->parserFactory->createParser($kind));
}
return $this->parsers[$kind];

View File

@ -19,7 +19,6 @@ use Psy\ContextAware;
use Psy\Exception\ErrorException;
use Psy\Exception\RuntimeException;
use Psy\Exception\UnexpectedTargetException;
use Psy\ParserFactory;
use Psy\Reflection\ReflectionClassConstant;
use Psy\Reflection\ReflectionConstant_;
use Psy\Sudo\SudoVisitor;
@ -51,8 +50,7 @@ abstract class ReflectingCommand extends Command implements ContextAware
*/
public function __construct($name = null)
{
$parserFactory = new ParserFactory();
$this->parser = $parserFactory->createParser();
$this->parser = new CodeArgumentParser();
$this->traverser = new NodeTraverser();
$this->traverser->addVisitor(new SudoVisitor());
@ -195,7 +193,7 @@ abstract class ReflectingCommand extends Command implements ContextAware
{
try {
// Add an implicit `sudo` to target resolution.
$nodes = $this->traverser->traverse($this->parse($code));
$nodes = $this->traverser->traverse($this->parser->parse($code));
$sudoCode = $this->printer->prettyPrint($nodes);
$value = $this->getApplication()->execute($sudoCode, true);
} catch (\Throwable $e) {
@ -209,29 +207,6 @@ abstract class ReflectingCommand extends Command implements ContextAware
return $value;
}
/**
* Lex and parse a string of code into statements.
*
* @param string $code
*
* @return array Statements
*/
private function parse($code)
{
$code = '<?php '.$code;
try {
return $this->parser->parse($code);
} catch (\PhpParser\Error $e) {
if (\strpos($e->getMessage(), 'unexpected EOF') === false) {
throw $e;
}
// If we got an unexpected EOF, let's try it again with a semicolon.
return $this->parser->parse($code.';');
}
}
/**
* Resolve code to an object in the current scope.
*

View File

@ -14,7 +14,6 @@ namespace Psy\Command;
use PhpParser\NodeTraverser;
use PhpParser\PrettyPrinter\Standard as Printer;
use Psy\Input\CodeArgument;
use Psy\ParserFactory;
use Psy\Readline\Readline;
use Psy\Sudo\SudoVisitor;
use Symfony\Component\Console\Input\InputInterface;
@ -35,8 +34,7 @@ class SudoCommand extends Command
*/
public function __construct($name = null)
{
$parserFactory = new ParserFactory();
$this->parser = $parserFactory->createParser();
$this->parser = new CodeArgumentParser();
$this->traverser = new NodeTraverser();
$this->traverser->addVisitor(new SudoVisitor());
@ -111,11 +109,7 @@ HELP
$code = $history[\count($history) - 2];
}
if (\strpos($code, '<?') === false) {
$code = '<?php '.$code;
}
$nodes = $this->traverser->traverse($this->parse($code));
$nodes = $this->traverser->traverse($this->parser->parse($code));
$sudoCode = $this->printer->prettyPrint($nodes);
$shell = $this->getApplication();
@ -123,25 +117,4 @@ HELP
return 0;
}
/**
* Lex and parse a string of code into statements.
*
* @param string $code
*
* @return array Statements
*/
private function parse(string $code): array
{
try {
return $this->parser->parse($code);
} catch (\PhpParser\Error $e) {
if (\strpos($e->getMessage(), 'unexpected EOF') === false) {
throw $e;
}
// If we got an unexpected EOF, let's try it again with a semicolon.
return $this->parser->parse($code.';');
}
}
}

View File

@ -22,7 +22,6 @@ use Psy\Context;
use Psy\ContextAware;
use Psy\Exception\ThrowUpException;
use Psy\Input\CodeArgument;
use Psy\ParserFactory;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
@ -39,9 +38,7 @@ class ThrowUpCommand extends Command implements ContextAware
*/
public function __construct($name = null)
{
$parserFactory = new ParserFactory();
$this->parser = $parserFactory->createParser();
$this->parser = new CodeArgumentParser();
$this->printer = new Printer();
parent::__construct($name);
@ -120,11 +117,7 @@ HELP
return [new Arg(new Variable('_e'))];
}
if (\strpos($code, '<?') === false) {
$code = '<?php '.$code;
}
$nodes = $this->parse($code);
$nodes = $this->parser->parse($code);
if (\count($nodes) !== 1) {
throw new \InvalidArgumentException('No idea how to throw this');
}
@ -143,25 +136,4 @@ HELP
return $args;
}
/**
* Lex and parse a string of code into statements.
*
* @param string $code
*
* @return array Statements
*/
private function parse(string $code): array
{
try {
return $this->parser->parse($code);
} catch (\PhpParser\Error $e) {
if (\strpos($e->getMessage(), 'unexpected EOF') === false) {
throw $e;
}
// If we got an unexpected EOF, let's try it again with a semicolon.
return $this->parser->parse($code.';');
}
}
}

View File

@ -15,7 +15,6 @@ use PhpParser\NodeTraverser;
use PhpParser\PrettyPrinter\Standard as Printer;
use Psy\Command\TimeitCommand\TimeitVisitor;
use Psy\Input\CodeArgument;
use Psy\ParserFactory;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
@ -45,8 +44,7 @@ class TimeitCommand extends Command
// @todo Remove microtime use after we drop support for PHP < 7.3
self::$useHrtime = \function_exists('hrtime');
$parserFactory = new ParserFactory();
$this->parser = $parserFactory->createParser();
$this->parser = new CodeArgumentParser();
$this->traverser = new NodeTraverser();
$this->traverser->addVisitor(new TimeitVisitor());
@ -87,17 +85,17 @@ HELP
protected function execute(InputInterface $input, OutputInterface $output)
{
$code = $input->getArgument('code');
$num = $input->getOption('num') ?: 1;
$num = (int) ($input->getOption('num') ?: 1);
$shell = $this->getApplication();
$instrumentedCode = $this->instrumentCode($code);
self::$times = [];
for ($i = 0; $i < $num; $i++) {
do {
$_ = $shell->execute($instrumentedCode);
$this->ensureEndMarked();
}
} while (\count(self::$times) < $num);
$shell->writeReturnValue($_);
@ -169,34 +167,9 @@ HELP
*
* This inserts `markStart` and `markEnd` calls to ensure that (reasonably)
* accurate times are recorded for just the code being executed.
*
* @param string $code
*/
private function instrumentCode(string $code): string
{
return $this->printer->prettyPrint($this->traverser->traverse($this->parse($code)));
}
/**
* Lex and parse a string of code into statements.
*
* @param string $code
*
* @return array Statements
*/
private function parse(string $code): array
{
$code = '<?php '.$code;
try {
return $this->parser->parse($code);
} catch (\PhpParser\Error $e) {
if (\strpos($e->getMessage(), 'unexpected EOF') === false) {
throw $e;
}
// If we got an unexpected EOF, let's try it again with a semicolon.
return $this->parser->parse($code.';');
}
return $this->printer->prettyPrint($this->traverser->traverse($this->parser->parse($code)));
}
}

View File

@ -17,6 +17,8 @@ use Psy\Shell;
/**
* A runkit-based code reloader, which is pretty much magic.
*
* @todo Remove RunkitReloader once we drop support for PHP 7.x :(
*/
class RunkitReloader extends AbstractListener
{

View File

@ -27,6 +27,7 @@ use Psy\TabCompletion\Matcher;
use Psy\VarDumper\PresenterAware;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command as BaseCommand;
use Symfony\Component\Console\Exception\ExceptionInterface as SymfonyConsoleException;
use Symfony\Component\Console\Formatter\OutputFormatter;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputArgument;
@ -49,7 +50,7 @@ use Symfony\Component\Console\Output\OutputInterface;
*/
class Shell extends Application
{
const VERSION = 'v0.11.20';
const VERSION = 'v0.11.21';
/** @deprecated */
const PROMPT = '>>> ';
@ -1319,10 +1320,21 @@ class Shell extends Application
}
}
if ($e instanceof PsyException) {
if ($e instanceof PsyException || $e instanceof SymfonyConsoleException) {
$exceptionShortName = (new \ReflectionClass($e))->getShortName();
$typeParts = \preg_split('/(?=[A-Z])/', $exceptionShortName);
\array_pop($typeParts); // Removes "Exception"
switch ($exceptionShortName) {
case 'RuntimeException':
case 'LogicException':
// These ones look weird without 'Exception'
break;
default:
if (\end($typeParts) === 'Exception') {
\array_pop($typeParts);
}
break;
}
return \trim(\strtoupper(\implode(' ', $typeParts)));
}

View File

@ -395,7 +395,7 @@ if (!\function_exists('Psy\\bin')) {
}
// Handle --help
if ($usageException !== null || $input->getOption('help')) {
if (!isset($config) || $usageException !== null || $input->getOption('help')) {
if ($usageException !== null) {
echo $usageException->getMessage().\PHP_EOL.\PHP_EOL;
}