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
18 changes: 14 additions & 4 deletions poc/spiral-emit/Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,28 @@ dotenv: [

tasks:
c:
desc: docker compose и аргументы. Рабочий пример [task c -- up -d]. -- обязательно.
desc: docker compose and args. Example [task c -- up -d]. -- mandatory.
cmd: docker compose {{.CLI_ARGS}}

bash:
desc: Войти в терминал app.
desc: Application terminal
interactive: true
cmd: task c -- run --rm -it php bash

up:
desc: Поднять окружение.
desc: Up application
cmd: task c -- up -d --build

down:
desc: Остановить окружение.
desc: Down application
cmd: task c -- down --remove-orphans

emit:
desc: emit instruction
cmds:
- task c -- exec roadrunner php app.php op:i:e | jq

emit-validate:
desc: emit instruction and validate
cmds:
- task emit | tee /dev/stderr | check-jsonschema --schemafile https://thumbrise.github.io/op/reference/instruction.v1.json -
24 changes: 24 additions & 0 deletions poc/spiral-emit/app/src/Endpoint/Web/HomeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@
use Exception;
use Spiral\Prototype\Traits\PrototypeTrait;
use Spiral\Router\Annotation\Route;
use Thumbrise\OP\Universal\Schema\Attributes\OPComment;
use Thumbrise\OP\Universal\Schema\Attributes\OPError;
use Thumbrise\OP\Universal\Schema\Attributes\OPID;
use Thumbrise\OP\Universal\Schema\Attributes\OPTrait;
use Thumbrise\OP\Universal\Schema\Term;
use Thumbrise\OP\Universal\Vendors\Http\Path;
use Thumbrise\OP\Universal\Vendors\Http\Status;
use Thumbrise\OP\Universal\Vendors\Http\Verb;

/**
* Simple home page controller. It renders home page template and also provides
Expand All @@ -21,6 +29,11 @@ final class HomeController
*/
use PrototypeTrait;

/**
* Render home page html from docblock.
*/
#[OPID(value: 'HomeRenderHTML')]
#[OPComment(value: 'Render home page html from attribute. Has priority under docblock')]
#[Route(route: '/', name: 'index')]
public function index(): string
{
Expand All @@ -30,6 +43,17 @@ public function index(): string
/**
* Example of exception page.
*/
#[OPID(value: 'HomeException')]
#[OPComment(value: 'Throws Exception')]
#[OPError([
new Term('TestException', 'This is a test exception.', trait: [
new Status('500'),
]),
])]
#[OPTrait([
new Path('/exception'),
new Verb('GET'),
])]
#[Route(route: '/exception', name: 'exception')]
public function exception(): never
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

namespace App\Endpoint\Web\Request;

use Spiral\Filter\Filterable;
use Spiral\Filters\Model\FilterInterface;

final class BreedListRequest implements Filterable
final class BreedListRequest implements FilterInterface
Comment thread
thumbrise marked this conversation as resolved.
{
public ?string $size = null;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

namespace App\Endpoint\Web\Request;

use Spiral\Filter\Filterable;
use Spiral\Filters\Model\FilterInterface;

final class BuyDogRequest implements Filterable
final class BuyDogRequest implements FilterInterface
{
public string $breed;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

namespace App\Endpoint\Web\Request;

use Spiral\Filter\Filterable;
use Spiral\Filters\Model\FilterInterface;

final class DogShowRequest implements Filterable
final class DogShowRequest implements FilterInterface
{
public string $breed;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

namespace App\Endpoint\Web\Request;

use Spiral\Filter\Filterable;
use Spiral\Filters\Model\FilterInterface;

final class OrderCancelRequest implements Filterable
final class OrderCancelRequest implements FilterInterface
{
public string $id;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

namespace App\Endpoint\Web\Request;

use Spiral\Filter\Filterable;
use Spiral\Filters\Model\FilterInterface;

final class OrderListRequest implements Filterable
final class OrderListRequest implements FilterInterface
{
public ?string $status = null;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

namespace App\Endpoint\Web\Request;

use Spiral\Filter\Filterable;
use Spiral\Filters\Model\FilterInterface;

final class OrderShowRequest implements Filterable
final class OrderShowRequest implements FilterInterface
{
public string $id;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

namespace App\Modules\OPSpiral\Endpoints\Console;

use App\Modules\OPSpiral\Infrastructure\InstructionEmitter;
use Spiral\Console\Attribute\AsCommand;
use Spiral\Console\Command;

#[AsCommand(name: 'op:instruction:emit', description: 'Emit OP instruction')]
final class OPInstructionEmitCommand extends Command
{
public function __invoke(InstructionEmitter $emitter): int
{
$this->info(json_encode($emitter->emit(), JSON_THROW_ON_ERROR));

return self::SUCCESS;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace App\Modules\OPSpiral\Endpoints\Web;

use App\Modules\OPSpiral\Infrastructure\InstructionEmitter;
use Psr\Http\Message\ResponseInterface;
use Spiral\Http\ResponseWrapper;
use Spiral\Router\Annotation\Route;

class OPInstructionEmitRoute
{
#[Route('/op/instruction', name: 'op.instruction.emit', methods: ['GET'])]
public function __invoke(InstructionEmitter $emitter, ResponseWrapper $response): ResponseInterface
Comment thread
coderabbitai[bot] marked this conversation as resolved.
{
$instruction = $emitter->emit();

$r = $response->create(200)->withHeader('Content-Type', 'text/yaml');

$r->getBody()->write($instruction->toYaml());

return $r;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

declare(strict_types=1);

namespace App\Modules\OPSpiral\Infrastructure;

use App\Modules\OPSpiral\Infrastructure\Web\WebOperationsEmitter;
use Thumbrise\OP\Universal\Schema\Term;

class InstructionEmitter
{
public function __construct(
private readonly WebOperationsEmitter $webOperationsEmitter,
) {}

public function emit(): SerializableInstruction
{
$web = $this->webOperationsEmitter->emit();

$operations = array_merge(
$web,
// TODO cli,
// TODO anything,
);

return new SerializableInstruction(
id: 'Dog shop',
comment: 'Dowg',
version: '1.0.0',
operations: $operations,
trait: [
new Term('my/opinion', 'my honest opinion'),
],
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace App\Modules\OPSpiral\Infrastructure\Internal\Reflection;

use phpDocumentor\Reflection\DocBlockFactory;
use ReflectionMethod;

class DocBlockSummaryReader
{
/**
* @todo Wrong docblock for method WITHOUT docblock, if above exist use trait WITH docblock
*/
public function read(ReflectionMethod $method): string
{
$v = $method->getDocComment();
if (empty($v)) {
return '';
}

$factory = DocBlockFactory::createInstance();
$docBlock = $factory->create($v);

return $docBlock->getSummary();
Comment thread
thumbrise marked this conversation as resolved.
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

declare(strict_types=1);

namespace App\Modules\OPSpiral\Infrastructure\Internal\Reflection;
use ReflectionProperty;

class PropertyReader
{
public function read(object $object, string $property): mixed
{
$ref = new ReflectionProperty($object, $property);

return $ref->getValue($object);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

declare(strict_types=1);

namespace App\Modules\OPSpiral\Infrastructure;

use JsonSerializable;
use Symfony\Component\Yaml\Yaml;
use Thumbrise\OP\Universal\Schema\Instruction;

class SerializableInstruction extends Instruction implements JsonSerializable
{
public function __toString(): string
{
return $this->toYaml();
}

public function toYaml(): string
{
return Yaml::dump($this->toAssoc(), flags: Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE | Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE | Yaml::DUMP_OBJECT_AS_MAP);
}
Comment thread
thumbrise marked this conversation as resolved.

public function jsonSerialize(): array
{
return $this->toAssoc();
}

private function toAssoc(): array
{
$vars = get_object_vars($this);

$json = json_encode($vars);

$assoc = json_decode($json, true);

return $this->recursiveNullFilter($assoc);
Comment thread
thumbrise marked this conversation as resolved.
}

private function recursiveNullFilter(array $data): array
{
$filtered = [];
foreach ($data as $key => $value) {
if (is_array($value)) {
$value = $this->recursiveNullFilter($value);
}
if (null !== $value) {
$filtered[$key] = $value;
}
}

return $filtered;
}
}
Loading