All
This commit is contained in:
4
api/.env
4
api/.env
@@ -14,7 +14,7 @@
|
|||||||
# https://symfony.com/doc/current/best_practices/configuration.html#infrastructure-related-configuration
|
# https://symfony.com/doc/current/best_practices/configuration.html#infrastructure-related-configuration
|
||||||
|
|
||||||
MERCURE_SUBSCRIBE_URL=http://localhost:1337/hub
|
MERCURE_SUBSCRIBE_URL=http://localhost:1337/hub
|
||||||
VARNISH_URL=http://cache-proxy
|
#VARNISH_URL=http://cache-proxy
|
||||||
|
|
||||||
###> symfony/framework-bundle ###
|
###> symfony/framework-bundle ###
|
||||||
APP_ENV=dev
|
APP_ENV=dev
|
||||||
@@ -31,7 +31,7 @@ DATABASE_URL=postgres://api-platform:!ChangeMe!@db/api
|
|||||||
###< doctrine/doctrine-bundle ###
|
###< doctrine/doctrine-bundle ###
|
||||||
|
|
||||||
###> nelmio/cors-bundle ###
|
###> nelmio/cors-bundle ###
|
||||||
CORS_ALLOW_ORIGIN=^https?://localhost(:[0-9]+)?$
|
CORS_ALLOW_ORIGIN=^https?://.*$
|
||||||
###< nelmio/cors-bundle ###
|
###< nelmio/cors-bundle ###
|
||||||
|
|
||||||
###> symfony/mercure-bundle ###
|
###> symfony/mercure-bundle ###
|
||||||
|
|||||||
7
api/Readme.md
Normal file
7
api/Readme.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
Enable prod mode: `docker-compose exec php composer dump-env prod`
|
||||||
|
|
||||||
|
Disable prod mode: delete `.env.local.php`
|
||||||
|
|
||||||
|
Clear Prod cache `docker-compose exec php bin/console cache:clear --env=prod`
|
||||||
|
|
||||||
|
Swagger: https://api-platform.com/docs/core/swagger/#using-the-openapi-and-swagger-contexts
|
||||||
@@ -9,16 +9,12 @@ api_platform:
|
|||||||
mapping:
|
mapping:
|
||||||
paths: ['%kernel.project_dir%/src/Entity']
|
paths: ['%kernel.project_dir%/src/Entity']
|
||||||
title: Hello API Platform
|
title: Hello API Platform
|
||||||
|
description: สวัสดีเพื่อนๆ
|
||||||
version: 1.0.0
|
version: 1.0.0
|
||||||
# Varnish integration, remove if unwanted
|
show_webby: false
|
||||||
http_cache:
|
formats:
|
||||||
invalidation:
|
json: ['application/json']
|
||||||
enabled: true
|
xml: ['application/xml', 'text/xml']
|
||||||
varnish_urls: ['%env(VARNISH_URL)%']
|
yaml: ['application/x-yaml']
|
||||||
max_age: 0
|
csv: ['text/csv']
|
||||||
shared_max_age: 3600
|
html: ['text/html']
|
||||||
vary: ['Content-Type', 'Authorization']
|
|
||||||
public: true
|
|
||||||
# Mercure integration, remove if unwanted
|
|
||||||
mercure:
|
|
||||||
hub_url: '%env(MERCURE_SUBSCRIBE_URL)%'
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ nelmio_cors:
|
|||||||
defaults:
|
defaults:
|
||||||
origin_regex: true
|
origin_regex: true
|
||||||
allow_origin: ['%env(CORS_ALLOW_ORIGIN)%']
|
allow_origin: ['%env(CORS_ALLOW_ORIGIN)%']
|
||||||
allow_methods: ['GET', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE']
|
allow_methods: ['GET', 'OPTIONS']
|
||||||
allow_headers: ['Content-Type', 'Authorization']
|
allow_headers: ['Content-Type', 'Authorization']
|
||||||
expose_headers: ['Link']
|
expose_headers: ['Link']
|
||||||
max_age: 3600
|
max_age: 3600
|
||||||
|
|||||||
71
api/src/DataProvider/CircleDataProvider.php
Normal file
71
api/src/DataProvider/CircleDataProvider.php
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\DataProvider;
|
||||||
|
|
||||||
|
use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface;
|
||||||
|
use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
|
||||||
|
use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
|
||||||
|
use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface;
|
||||||
|
use ApiPlatform\Core\Exception\InvalidValueException;
|
||||||
|
use ApiPlatform\Core\Exception\ResourceClassNotSupportedException;
|
||||||
|
use App\Entity\Creation;
|
||||||
|
use Symfony\Component\HttpFoundation\RequestStack;
|
||||||
|
use App\Entity\Circle;
|
||||||
|
|
||||||
|
final class CircleDataProvider implements CollectionDataProviderInterface, ItemDataProviderInterface, SubresourceDataProviderInterface, RestrictedDataProviderInterface
|
||||||
|
{
|
||||||
|
private $requestStack;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CircleDataProvider constructor.
|
||||||
|
* @param $requestStack
|
||||||
|
*/
|
||||||
|
public function __construct(RequestStack $requestStack)
|
||||||
|
{
|
||||||
|
$this->requestStack = $requestStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
|
||||||
|
{
|
||||||
|
return Circle::class === $resourceClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCollection(string $resourceClass, string $operationName = null): \Generator
|
||||||
|
{
|
||||||
|
$query = $this->requestStack->getCurrentRequest()->query;
|
||||||
|
$ids = $query->get('ids');
|
||||||
|
if ($ids !== null) {
|
||||||
|
if (!preg_match('/^\d+(,\d+)*$/', $ids)) {
|
||||||
|
throw new InvalidValueException('ids must be comma-seperated integers', 400);
|
||||||
|
//BadQueryStringException('ids must be comma-seperated integer', 400);
|
||||||
|
}
|
||||||
|
$ids = explode(',', $ids);
|
||||||
|
foreach ($ids as $id) {
|
||||||
|
yield new Circle((int)$id, $operationName, 'bla');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for($i = 0; $i< 10; $i++) {
|
||||||
|
yield new Circle($i, $operationName, json_encode($ids));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Returning array works too
|
||||||
|
// Return empty array if no data
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getItem(string $resourceClass, $id, string $operationName = null, array $context = [])
|
||||||
|
{
|
||||||
|
//return null; for 404
|
||||||
|
$tmp = new Circle($id, is_string($id)? 'true' : 'false', 'a01');
|
||||||
|
$tmp->creations = [new Creation(55,'55'), new Creation(66,'66')];
|
||||||
|
return $tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSubresource(string $resourceClass, array $identifiers, array $context, string $operationName = null)
|
||||||
|
{
|
||||||
|
return $context['property'];
|
||||||
|
// TODO: Implement getSubresource() method.
|
||||||
|
}
|
||||||
|
}
|
||||||
131
api/src/Entity/Circle.php
Normal file
131
api/src/Entity/Circle.php
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Entity;
|
||||||
|
|
||||||
|
use ApiPlatform\Core\Annotation\ApiProperty;
|
||||||
|
use ApiPlatform\Core\Annotation\ApiResource;
|
||||||
|
use ApiPlatform\Core\Annotation\ApiSubresource;
|
||||||
|
use Symfony\Component\Validator\Constraints as Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A circle
|
||||||
|
* @ApiResource(
|
||||||
|
* attributes={"pagination_enabled"=false},
|
||||||
|
* collectionOperations={
|
||||||
|
* "get"={
|
||||||
|
* "method"="GET",
|
||||||
|
* "swagger_context"={
|
||||||
|
* "summary"="Get the list of circles",
|
||||||
|
* "description"="Get the list of circles",
|
||||||
|
* "parameters" = {
|
||||||
|
* {
|
||||||
|
* "name"="ids",
|
||||||
|
* "in"="query",
|
||||||
|
* "description"="Comma-seperated list of circle ids. If not specified, will return all circles",
|
||||||
|
* "example"="123,456",
|
||||||
|
* "pattern"="^\d+(,\d+)*$",
|
||||||
|
* "type":"string"
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* },
|
||||||
|
* "requirements"={"ids"="\d+(,\d+)*"}
|
||||||
|
* }
|
||||||
|
* },
|
||||||
|
* itemOperations={
|
||||||
|
* "get"={
|
||||||
|
* "method"="GET",
|
||||||
|
* "requirements"={"id"="\d+"}
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* )
|
||||||
|
*/
|
||||||
|
class Circle
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var int Circle Id
|
||||||
|
* @ApiProperty(identifier=true)
|
||||||
|
* @Assert\NotBlank
|
||||||
|
* @Assert\Type(type="int")
|
||||||
|
*/
|
||||||
|
private $id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string Circle name
|
||||||
|
* @Assert\NotBlank
|
||||||
|
*/
|
||||||
|
public $name = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string Booth location
|
||||||
|
* @Assert\NotBlank
|
||||||
|
*/
|
||||||
|
public $booth = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string Description
|
||||||
|
*/
|
||||||
|
public $description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string Cutout image url
|
||||||
|
*/
|
||||||
|
|
||||||
|
public $cutout;
|
||||||
|
/**
|
||||||
|
* @var string Menu image url
|
||||||
|
*/
|
||||||
|
|
||||||
|
public $menu;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string Cover image url
|
||||||
|
*/
|
||||||
|
public $cover;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int Spaces
|
||||||
|
* @Assert\Type(type="int")
|
||||||
|
*/
|
||||||
|
public $sp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string Type of circle
|
||||||
|
*/
|
||||||
|
public $type;
|
||||||
|
|
||||||
|
// Members
|
||||||
|
/**
|
||||||
|
* @ApiSubresource()
|
||||||
|
* @var integer[] Members
|
||||||
|
*/
|
||||||
|
public $members;
|
||||||
|
|
||||||
|
// Creations
|
||||||
|
/**
|
||||||
|
* @ApiSubresource()
|
||||||
|
* @var Creation[] Creations
|
||||||
|
*/
|
||||||
|
public $creations;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Circle constructor.
|
||||||
|
* @param int $id
|
||||||
|
* @param string $name
|
||||||
|
* @param string $booth
|
||||||
|
*/
|
||||||
|
public function __construct(int $id, string $name, string $booth)
|
||||||
|
{
|
||||||
|
$this->id = $id;
|
||||||
|
$this->name = $name;
|
||||||
|
$this->booth = $booth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
public function getId(): int
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
}
|
||||||
62
api/src/Entity/Creation.php
Normal file
62
api/src/Entity/Creation.php
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace App\Entity;
|
||||||
|
|
||||||
|
use ApiPlatform\Core\Annotation\ApiProperty;
|
||||||
|
use ApiPlatform\Core\Annotation\ApiResource;
|
||||||
|
use Symfony\Component\Validator\Constraints as Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Creation
|
||||||
|
* @ApiResource(
|
||||||
|
* attributes={"pagination_enabled"=false},
|
||||||
|
* collectionOperations={"get"},
|
||||||
|
* itemOperations={
|
||||||
|
* "get"={
|
||||||
|
* "method"="GET",
|
||||||
|
* "requirements"={"id"="\d+"}
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* )
|
||||||
|
*/
|
||||||
|
class Creation
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var int Circle Id
|
||||||
|
* @ApiProperty(identifier=true)
|
||||||
|
* @Assert\NotBlank
|
||||||
|
* @Assert\Type(type="int")
|
||||||
|
*/
|
||||||
|
private $id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string Creation name
|
||||||
|
* @Assert\NotBlank
|
||||||
|
*/
|
||||||
|
public $name = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var integer Circle ID
|
||||||
|
* @Assert\NotBlank
|
||||||
|
*/
|
||||||
|
public $circleId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $id
|
||||||
|
* @param string $name
|
||||||
|
*/
|
||||||
|
public function __construct(int $id, string $name)
|
||||||
|
{
|
||||||
|
$this->id = $id;
|
||||||
|
$this->name = $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
public function getId(): int
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Entity;
|
|
||||||
|
|
||||||
use ApiPlatform\Core\Annotation\ApiResource;
|
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
|
||||||
use Symfony\Component\Validator\Constraints as Assert;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a dummy entity. Remove it!
|
|
||||||
*
|
|
||||||
* @ApiResource
|
|
||||||
* @ORM\Entity
|
|
||||||
*/
|
|
||||||
class Greeting
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var int The entity Id
|
|
||||||
*
|
|
||||||
* @ORM\Id
|
|
||||||
* @ORM\GeneratedValue
|
|
||||||
* @ORM\Column(type="integer")
|
|
||||||
*/
|
|
||||||
private $id;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string A nice person
|
|
||||||
*
|
|
||||||
* @ORM\Column
|
|
||||||
* @Assert\NotBlank
|
|
||||||
*/
|
|
||||||
public $name = '';
|
|
||||||
|
|
||||||
public function getId(): int
|
|
||||||
{
|
|
||||||
return $this->id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>{% if title %}{{ title }} - {% endif %}API Platform</title>
|
||||||
|
|
||||||
|
{% block stylesheet %}
|
||||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:400,700|Source+Code+Pro:300,600|Titillium+Web:400,600,700">
|
||||||
|
<link rel="stylesheet" href="{{ asset('bundles/apiplatform/swagger-ui/swagger-ui.css') }}">
|
||||||
|
<link rel="stylesheet" href="{{ asset('bundles/apiplatform/style.css') }}">
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{# json_encode(65) is for JSON_UNESCAPED_SLASHES|JSON_HEX_TAG to avoid JS XSS #}
|
||||||
|
<script id="swagger-data" type="application/json">{{ swagger_data|json_encode(65)|raw }}</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" style="position:absolute;width:0;height:0">
|
||||||
|
<defs>
|
||||||
|
<symbol viewBox="0 0 20 20" id="unlocked">
|
||||||
|
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V6h2v-.801C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8z"></path>
|
||||||
|
</symbol>
|
||||||
|
|
||||||
|
<symbol viewBox="0 0 20 20" id="locked">
|
||||||
|
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8zM12 8H8V5.199C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8z"></path>
|
||||||
|
</symbol>
|
||||||
|
|
||||||
|
<symbol viewBox="0 0 20 20" id="close">
|
||||||
|
<path d="M14.348 14.849c-.469.469-1.229.469-1.697 0L10 11.819l-2.651 3.029c-.469.469-1.229.469-1.697 0-.469-.469-.469-1.229 0-1.697l2.758-3.15-2.759-3.152c-.469-.469-.469-1.228 0-1.697.469-.469 1.228-.469 1.697 0L10 8.183l2.651-3.031c.469-.469 1.228-.469 1.697 0 .469.469.469 1.229 0 1.697l-2.758 3.152 2.758 3.15c.469.469.469 1.229 0 1.698z"></path>
|
||||||
|
</symbol>
|
||||||
|
|
||||||
|
<symbol viewBox="0 0 20 20" id="large-arrow">
|
||||||
|
<path d="M13.25 10L6.109 2.58c-.268-.27-.268-.707 0-.979.268-.27.701-.27.969 0l7.83 7.908c.268.271.268.709 0 .979l-7.83 7.908c-.268.271-.701.27-.969 0-.268-.269-.268-.707 0-.979L13.25 10z"></path>
|
||||||
|
</symbol>
|
||||||
|
|
||||||
|
<symbol viewBox="0 0 20 20" id="large-arrow-down">
|
||||||
|
<path d="M17.418 6.109c.272-.268.709-.268.979 0s.271.701 0 .969l-7.908 7.83c-.27.268-.707.268-.979 0l-7.908-7.83c-.27-.268-.27-.701 0-.969.271-.268.709-.268.979 0L10 13.25l7.418-7.141z"></path>
|
||||||
|
</symbol>
|
||||||
|
|
||||||
|
|
||||||
|
<symbol viewBox="0 0 24 24" id="jump-to">
|
||||||
|
<path d="M19 7v4H5.83l3.58-3.59L8 6l-6 6 6 6 1.41-1.41L5.83 13H21V7z"></path>
|
||||||
|
</symbol>
|
||||||
|
|
||||||
|
<symbol viewBox="0 0 24 24" id="expand">
|
||||||
|
<path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"></path>
|
||||||
|
</symbol>
|
||||||
|
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
<header>
|
||||||
|
<a id="logo" href="https://api-platform.com"><img src="{{ asset('bundles/apiplatform/logo-header.svg') }}" alt="API Platform"></a>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
{% if showWebby %}
|
||||||
|
<div class="web"><img src="{{ asset('bundles/apiplatform/web.png') }}"></div>
|
||||||
|
<div class="webby"><img src="{{ asset('bundles/apiplatform/webby.png') }}"></div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<div id="swagger-ui" class="api-platform"></div>
|
||||||
|
|
||||||
|
<div class="swagger-ui" id="formats">
|
||||||
|
<div class="information-container wrapper">
|
||||||
|
<div class="info">
|
||||||
|
Other API docs:
|
||||||
|
{% set active_ui = app.request.get('ui', 'swagger_ui') %}
|
||||||
|
{% if swaggerUiEnabled and active_ui != 'swagger_ui' %}<a href="{{ path('api_entrypoint') }}">Swagger UI</a>{% endif %}
|
||||||
|
{% if reDocEnabled and active_ui != 're_doc' %}<a href="{{ path('api_entrypoint', {'ui': 're_doc'}) }}">ReDoc</a>{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% block javascript %}
|
||||||
|
{% if (reDocEnabled and not swaggerUiEnabled) or (reDocEnabled and 're_doc' == active_ui) %}
|
||||||
|
<script src="{{ asset('bundles/apiplatform/redoc/redoc.standalone.js') }}"></script>
|
||||||
|
<script src="{{ asset('bundles/apiplatform/init-redoc-ui.js') }}"></script>
|
||||||
|
{% elseif (swaggerUiEnabled) %}
|
||||||
|
<script src="{{ asset('bundles/apiplatform/swagger-ui/swagger-ui-bundle.js') }}"></script>
|
||||||
|
<script src="{{ asset('bundles/apiplatform/swagger-ui/swagger-ui-standalone-preset.js') }}"></script>
|
||||||
|
<script src="{{ asset('bundles/apiplatform/init-swagger-ui.js') }}"></script>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user