Importer
This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
<?php
|
||||
|
||||
namespace App\Command;
|
||||
|
||||
use App\Command\Pf2eSchemaGenerator\Schema;
|
||||
use App\Command\Pf2eSchemaGenerator\SchemaItem;
|
||||
use App\Service\AonprdConnectionService;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
#[AsCommand(
|
||||
name: 'pf2e:generate',
|
||||
description: 'Add a short description for your command',
|
||||
)]
|
||||
class Pf2eGenerateCommand extends Command
|
||||
{
|
||||
public function __construct(private AonprdConnectionService $connectionService)
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
$this
|
||||
->addOption("revision", null, InputOption::VALUE_REQUIRED, "Load index of specific revision. Default value - latest revision.")
|
||||
->addOption('type', null, InputOption::VALUE_REQUIRED, 'Specify types to import schema')
|
||||
->addOption('all', null, InputOption::VALUE_NONE, 'Generate schema for all types')
|
||||
;
|
||||
}
|
||||
|
||||
private int $revision;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private array $types;
|
||||
|
||||
/**
|
||||
* @var array<string, Schema>
|
||||
*/
|
||||
private array $schemas = [];
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
|
||||
$this->revision = $input->getOption('revision') ?? $this->connectionService->getRevision();
|
||||
|
||||
if ($input->getOption('all')) {
|
||||
$this->types = [];
|
||||
}
|
||||
else if (is_null($input->getOption('type'))) {
|
||||
// $io->error("You must specify --type=[TYPE] or --all");
|
||||
// return Command::INVALID;
|
||||
$this->types = ["class"];
|
||||
}
|
||||
else {
|
||||
$this->types = explode(",", $input->getOption('type'));
|
||||
}
|
||||
|
||||
$typePages = $this->loadTypePages();
|
||||
|
||||
if ($input->getOption('all')) {
|
||||
$this->types = array_keys($typePages);
|
||||
}
|
||||
|
||||
$pages = [];
|
||||
|
||||
foreach ($this->types as $type) {
|
||||
$pages = [...$pages, ...$typePages[$type]];
|
||||
$this->schemas[$type] = new Schema();
|
||||
}
|
||||
|
||||
$pages = array_unique($pages);
|
||||
|
||||
foreach ($pages as $page) {
|
||||
$this->loadPage($page);
|
||||
}
|
||||
|
||||
foreach ($this->schemas as $type => $schema) {
|
||||
$io->write("<options=bold,underscore>{$type}</>");
|
||||
$io->writeln(str_replace(PHP_EOL, PHP_EOL.str_repeat(" ", 4), PHP_EOL.$schema));
|
||||
$io->writeln("");
|
||||
}
|
||||
|
||||
$io->success('You have a new command! Now make it your own! Pass --help to see your options.');
|
||||
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
|
||||
protected function loadTypePages(): array
|
||||
{
|
||||
$typePages = [];
|
||||
|
||||
$index = $this->connectionService->loadCurrentIndex($this->revision);
|
||||
|
||||
foreach ($index as $page => $elements) {
|
||||
foreach ($elements as $element) {
|
||||
preg_match("#^([a-z\\-]+?)-(\\d.*)$#", $element, $matches);
|
||||
$type = $matches[1];
|
||||
|
||||
if (!empty($targetType) && !in_array($type, $this->types)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($typePages[$type])) {
|
||||
$typePages[$type] = [];
|
||||
}
|
||||
|
||||
if (!in_array($page, $typePages[$type])) {
|
||||
$typePages[$type][] = $page;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $typePages;
|
||||
}
|
||||
|
||||
protected function loadPage(string $page): void {
|
||||
$data = $this->connectionService->load("/json-data/{$page}.json");
|
||||
|
||||
foreach ($data as $element) {
|
||||
$type = $element["category"];
|
||||
|
||||
if (!in_array($type, $this->types)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->schemas[$type]->process($element);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace App\Command;
|
||||
|
||||
use App\Service\AonprdConnectionService;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
#[AsCommand(
|
||||
name: "pf2e:revision",
|
||||
description: "Get current revision number of Archives of Nethys",
|
||||
)]
|
||||
class Pf2eIndexCommand extends Command
|
||||
{
|
||||
public function __construct(private AonprdConnectionService $connectionService)
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
|
||||
$revision = $this->connectionService->getRevision();
|
||||
$io->success("Current Archives of Nethys' revision number is {$revision}");
|
||||
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
namespace App\Command\Pf2eSchemaGenerator;
|
||||
|
||||
class Schema
|
||||
{
|
||||
/**
|
||||
* @var SchemaItem[]
|
||||
*/
|
||||
private array $items = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function process(mixed $element): void
|
||||
{
|
||||
$keys = array_keys($element);
|
||||
|
||||
foreach ($this->items as $key => $item) {
|
||||
if (!in_array($key, $keys)) {
|
||||
$item->disableRequired();
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($keys as $key) {
|
||||
if (!array_key_exists($key, $this->items)) {
|
||||
$this->items[$key] = new SchemaItem($key);
|
||||
}
|
||||
|
||||
$this->items[$key]->adapt($element[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static function resolveType(mixed $value): string
|
||||
{
|
||||
$type = gettype($value);
|
||||
|
||||
if ($type === "array") {
|
||||
if (empty($value)) {
|
||||
return "empty[]";
|
||||
}
|
||||
|
||||
if (array_is_list($value)) {
|
||||
$elementType = "";
|
||||
foreach ($value as $element) {
|
||||
$elementType = self::mergeTypes($elementType, self::resolveType($element));
|
||||
}
|
||||
|
||||
if (str_contains("|", $elementType)) {
|
||||
return "mixed[]";
|
||||
}
|
||||
|
||||
return $elementType . "[]";
|
||||
}
|
||||
|
||||
return "object";
|
||||
}
|
||||
|
||||
return $type;
|
||||
}
|
||||
|
||||
public static function mergeTypes(string $typeList, string $newType): string {
|
||||
if (empty($typeList)) {
|
||||
return $newType;
|
||||
}
|
||||
|
||||
else if (str_contains("|", $typeList)) {
|
||||
$types = explode("|", $typeList);
|
||||
|
||||
if (!in_array($newType, $types, true)) {
|
||||
$types[] = $newType;
|
||||
}
|
||||
|
||||
return implode("|", $types);
|
||||
}
|
||||
else if ($newType !== $typeList) {
|
||||
return $typeList . "|" . $newType;
|
||||
}
|
||||
|
||||
return $typeList;
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
$rows = [];
|
||||
|
||||
foreach ($this->items as $item) {
|
||||
$rows = [...$rows, ...$item->strings()];
|
||||
}
|
||||
|
||||
return implode(PHP_EOL, $rows);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace App\Command\Pf2eSchemaGenerator;
|
||||
|
||||
class SchemaItem
|
||||
{
|
||||
public string $name;
|
||||
|
||||
public string $type = "";
|
||||
|
||||
public bool $required = true;
|
||||
|
||||
public ?array $elements = [];
|
||||
|
||||
public function __construct($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public function disableRequired(): void
|
||||
{
|
||||
$this->required = false;
|
||||
}
|
||||
|
||||
public function adapt(mixed $value): void
|
||||
{
|
||||
$type = Schema::resolveType($value);
|
||||
|
||||
$this->type = Schema::mergeTypes($this->type, $type);
|
||||
|
||||
if (str_contains($this->type, "[]") && !is_null($this->elements)) {
|
||||
foreach ($value as $element) {
|
||||
if (!in_array($element, $this->elements)) {
|
||||
$this->elements[] = $element;
|
||||
}
|
||||
}
|
||||
|
||||
if (count($this->elements) > 20) {
|
||||
$this->elements = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function strings(): array {
|
||||
$name = $this->name;
|
||||
|
||||
if (!$this->required) {
|
||||
$name = "[{$name}]";
|
||||
}
|
||||
|
||||
$rows = [
|
||||
sprintf("%s: %s", $name, $this->type),
|
||||
];
|
||||
|
||||
if (!empty($this->elements)) {
|
||||
sort($this->elements);
|
||||
$elements = [];
|
||||
foreach ($this->elements as $element) {
|
||||
$elements[] = is_string($element) ? "\"{$element}\"" : strval($element);
|
||||
}
|
||||
$rows[] = " Elements: [ " . implode(", ", $elements) . " ]";
|
||||
}
|
||||
|
||||
return $rows;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
namespace App\Command;
|
||||
|
||||
use App\Service\AonprdConnectionService;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Helper\Table;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
#[AsCommand(
|
||||
name: 'pf2e:types',
|
||||
description: 'Load types from Archives of Nethys',
|
||||
)]
|
||||
class Pf2eTypesCommand extends Command
|
||||
{
|
||||
public function __construct(private AonprdConnectionService $connectionService)
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
$this
|
||||
->addOption("revision", null, InputOption::VALUE_REQUIRED, "Load index of specific revision. Default value - latest revision.")
|
||||
->addOption("full", null, InputOption::VALUE_NONE, "Display all columns")
|
||||
;
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
|
||||
$revision = $input->getOption("revision");
|
||||
$full = $input->getOption("full") ?? false;
|
||||
|
||||
$index = $this->connectionService->loadCurrentIndex($revision);
|
||||
|
||||
$types = [];
|
||||
|
||||
foreach ($index as $page) {
|
||||
foreach ($page as $element) {
|
||||
preg_match("#^([a-z\\-]+?)-(\\d.*)$#", $element, $matches);
|
||||
$type = $matches[1];
|
||||
$id = $matches[2];
|
||||
|
||||
if (!isset($types[$type])) {
|
||||
$types[$type] = [
|
||||
"name" => $type,
|
||||
"first_id" => $element,
|
||||
"count" => 0,
|
||||
"templates" => []
|
||||
];
|
||||
}
|
||||
|
||||
$template = preg_replace("#\\d+#", "%d", $id);
|
||||
|
||||
if (!in_array($template, $types[$type]['templates'])) {
|
||||
$types[$type]['templates'][] = $template;
|
||||
}
|
||||
|
||||
$types[$type]['count']++;
|
||||
}
|
||||
}
|
||||
|
||||
if ($full) {
|
||||
$table = [];
|
||||
|
||||
foreach ($types as $key => $type) {
|
||||
$table[] = [
|
||||
$key,
|
||||
sprintf("<href=https://elasticsearch.aonprd.com/aon/_doc/%s>%s</>",
|
||||
$type["first_id"],
|
||||
$type["first_id"]
|
||||
),
|
||||
$type['count'],
|
||||
implode(", ", $type['templates']),
|
||||
];
|
||||
}
|
||||
|
||||
$io->table(["Type name", "First Id", "Amount", "ID templates"], $table);
|
||||
}
|
||||
else {
|
||||
foreach ($types as $type) {
|
||||
$io->writeln($type['name']);
|
||||
}
|
||||
}
|
||||
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user