Compare commits

...

4 commits

Author SHA1 Message Date
Alexey Skobkin 9747eefe47
Replacing jms/serializer with symfony/serializer and doing some DTO refactoring. 2023-08-19 03:32:43 +03:00
Alexey Skobkin a7c17022dc
app:subscriptions:update --dry-run. 2023-08-19 03:28:45 +03:00
Alexey Skobkin 0a03a9a904
Fixing TelegramWebhookCommand setWebhook() call. 2023-08-19 01:22:37 +03:00
Alexey Skobkin 1c223f7077
Using --dry-run for app commands. 2023-08-19 01:22:09 +03:00
35 changed files with 281 additions and 945 deletions

View file

@ -14,7 +14,6 @@
"doctrine/doctrine-migrations-bundle": "^3.2", "doctrine/doctrine-migrations-bundle": "^3.2",
"doctrine/orm": "^2.14", "doctrine/orm": "^2.14",
"ghunti/highcharts-php": "^5.0", "ghunti/highcharts-php": "^5.0",
"jms/serializer-bundle": "^5.2",
"knplabs/knp-paginator-bundle": "^6.2", "knplabs/knp-paginator-bundle": "^6.2",
"league/commonmark": "^2.4", "league/commonmark": "^2.4",
"phpdocumentor/reflection-docblock": "^5.3", "phpdocumentor/reflection-docblock": "^5.3",
@ -34,6 +33,7 @@
"symfony/property-info": "6.3.*", "symfony/property-info": "6.3.*",
"symfony/runtime": "6.3.*", "symfony/runtime": "6.3.*",
"symfony/security-bundle": "6.3.*", "symfony/security-bundle": "6.3.*",
"symfony/serializer": "6.3.*",
"symfony/string": "6.3.*", "symfony/string": "6.3.*",
"symfony/translation": "6.3.*", "symfony/translation": "6.3.*",
"symfony/twig-bundle": "6.3.*", "symfony/twig-bundle": "6.3.*",

343
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "274812d219a3d19c925c0e67b5f86926", "content-hash": "0cb307d1ad554ab97a56f5805e8c6adb",
"packages": [ "packages": [
{ {
"name": "dflydev/dot-access-data", "name": "dflydev/dot-access-data",
@ -1689,253 +1689,6 @@
}, },
"time": "2023-04-26T21:37:31+00:00" "time": "2023-04-26T21:37:31+00:00"
}, },
{
"name": "jms/metadata",
"version": "2.8.0",
"source": {
"type": "git",
"url": "https://github.com/schmittjoh/metadata.git",
"reference": "7ca240dcac0c655eb15933ee55736ccd2ea0d7a6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/schmittjoh/metadata/zipball/7ca240dcac0c655eb15933ee55736ccd2ea0d7a6",
"reference": "7ca240dcac0c655eb15933ee55736ccd2ea0d7a6",
"shasum": ""
},
"require": {
"php": "^7.2|^8.0"
},
"require-dev": {
"doctrine/cache": "^1.0",
"doctrine/coding-standard": "^8.0",
"mikey179/vfsstream": "^1.6.7",
"phpunit/phpunit": "^8.5|^9.0",
"psr/container": "^1.0|^2.0",
"symfony/cache": "^3.1|^4.0|^5.0",
"symfony/dependency-injection": "^3.1|^4.0|^5.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.x-dev"
}
},
"autoload": {
"psr-4": {
"Metadata\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Johannes M. Schmitt",
"email": "schmittjoh@gmail.com"
},
{
"name": "Asmir Mustafic",
"email": "goetas@gmail.com"
}
],
"description": "Class/method/property metadata management in PHP",
"keywords": [
"annotations",
"metadata",
"xml",
"yaml"
],
"support": {
"issues": "https://github.com/schmittjoh/metadata/issues",
"source": "https://github.com/schmittjoh/metadata/tree/2.8.0"
},
"time": "2023-02-15T13:44:18+00:00"
},
{
"name": "jms/serializer",
"version": "3.27.0",
"source": {
"type": "git",
"url": "https://github.com/schmittjoh/serializer.git",
"reference": "e8c812460d7b47b15bc0ccd78901276bd44ad452"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/schmittjoh/serializer/zipball/e8c812460d7b47b15bc0ccd78901276bd44ad452",
"reference": "e8c812460d7b47b15bc0ccd78901276bd44ad452",
"shasum": ""
},
"require": {
"doctrine/annotations": "^1.13 || ^2.0",
"doctrine/instantiator": "^1.0.3 || ^2.0",
"doctrine/lexer": "^2.0 || ^3.0",
"jms/metadata": "^2.6",
"php": "^7.2||^8.0",
"phpstan/phpdoc-parser": "^0.4 || ^0.5 || ^1.0"
},
"require-dev": {
"doctrine/coding-standard": "^8.1",
"doctrine/orm": "~2.1",
"doctrine/persistence": "^1.3.3|^2.0|^3.0",
"doctrine/phpcr-odm": "^1.3|^2.0",
"ext-pdo_sqlite": "*",
"jackalope/jackalope-doctrine-dbal": "^1.1.5",
"ocramius/proxy-manager": "^1.0|^2.0",
"phpbench/phpbench": "^1.0",
"phpstan/phpstan": "^1.0.2",
"phpunit/phpunit": "^8.5.21||^9.0||^10.0",
"psr/container": "^1.0|^2.0",
"symfony/dependency-injection": "^3.0|^4.0|^5.0|^6.0",
"symfony/expression-language": "^3.2|^4.0|^5.0|^6.0",
"symfony/filesystem": "^3.0|^4.0|^5.0|^6.0",
"symfony/form": "^3.0|^4.0|^5.0|^6.0",
"symfony/translation": "^3.0|^4.0|^5.0|^6.0",
"symfony/uid": "^5.1|^6.0",
"symfony/validator": "^3.1.9|^4.0|^5.0|^6.0",
"symfony/yaml": "^3.3|^4.0|^5.0|^6.0",
"twig/twig": "~1.34|~2.4|^3.0"
},
"suggest": {
"doctrine/collections": "Required if you like to use doctrine collection types as ArrayCollection.",
"symfony/cache": "Required if you like to use cache functionality.",
"symfony/uid": "Required if you'd like to serialize UID objects.",
"symfony/yaml": "Required if you'd like to use the YAML metadata format."
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.x-dev"
}
},
"autoload": {
"psr-4": {
"JMS\\Serializer\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Johannes M. Schmitt",
"email": "schmittjoh@gmail.com"
},
{
"name": "Asmir Mustafic",
"email": "goetas@gmail.com"
}
],
"description": "Library for (de-)serializing data of any complexity; supports XML, and JSON.",
"homepage": "http://jmsyst.com/libs/serializer",
"keywords": [
"deserialization",
"jaxb",
"json",
"serialization",
"xml"
],
"support": {
"issues": "https://github.com/schmittjoh/serializer/issues",
"source": "https://github.com/schmittjoh/serializer/tree/3.27.0"
},
"funding": [
{
"url": "https://github.com/goetas",
"type": "github"
}
],
"time": "2023-07-29T22:33:44+00:00"
},
{
"name": "jms/serializer-bundle",
"version": "5.3.1",
"source": {
"type": "git",
"url": "https://github.com/schmittjoh/JMSSerializerBundle.git",
"reference": "3279738a958454793ca1e318a7dab6cfcff60124"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/schmittjoh/JMSSerializerBundle/zipball/3279738a958454793ca1e318a7dab6cfcff60124",
"reference": "3279738a958454793ca1e318a7dab6cfcff60124",
"shasum": ""
},
"require": {
"jms/metadata": "^2.5",
"jms/serializer": "^3.20",
"php": "^7.2 || ^8.0",
"symfony/dependency-injection": "^3.4 || ^4.0 || ^5.0 || ^6.0",
"symfony/framework-bundle": "^3.4 || ^4.0 || ^5.0 || ^6.0"
},
"require-dev": {
"doctrine/coding-standard": "^8.1",
"doctrine/orm": "^2.4",
"phpunit/phpunit": "^8.0 || ^9.0",
"symfony/expression-language": "^3.4 || ^4.0 || ^5.0 || ^6.0",
"symfony/finder": "^3.4 || ^4.0 || ^5.0 || ^6.0",
"symfony/form": "^3.4 || ^4.0 || ^5.0 || ^6.0",
"symfony/stopwatch": "^3.4 || ^4.0 || ^5.0 || ^6.0",
"symfony/templating": "^3.4 || ^4.0 || ^5.0 || ^6.0",
"symfony/twig-bundle": "^3.4 || ^4.0 || ^5.0 || ^6.0",
"symfony/uid": "^5.1 || ^6.0",
"symfony/validator": "^3.4 || ^4.0 || ^5.0 || ^6.0",
"symfony/yaml": "^3.4 || ^4.0 || ^5.0 || ^6.0"
},
"suggest": {
"symfony/expression-language": "Required for opcache preloading ^3.4 || ^4.0 || ^5.0 || ^6.0",
"symfony/finder": "Required for cache warmup, supported versions ^3.4 || ^4.0 || ^5.0 || ^6.0"
},
"type": "symfony-bundle",
"extra": {
"branch-alias": {
"dev-master": "5.x-dev"
}
},
"autoload": {
"psr-4": {
"JMS\\SerializerBundle\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Johannes M. Schmitt",
"email": "schmittjoh@gmail.com"
},
{
"name": "Asmir Mustafic",
"email": "goetas@gmail.com"
}
],
"description": "Allows you to easily serialize, and deserialize data of any complexity",
"homepage": "http://jmsyst.com/bundles/JMSSerializerBundle",
"keywords": [
"deserialization",
"json",
"serialization",
"xml"
],
"support": {
"issues": "https://github.com/schmittjoh/JMSSerializerBundle/issues",
"source": "https://github.com/schmittjoh/JMSSerializerBundle/tree/5.3.1"
},
"funding": [
{
"url": "https://github.com/goetas",
"type": "github"
}
],
"time": "2023-06-13T14:47:57+00:00"
},
{ {
"name": "knplabs/knp-components", "name": "knplabs/knp-components",
"version": "v4.2.0", "version": "v4.2.0",
@ -6439,6 +6192,100 @@
], ],
"time": "2023-07-13T14:29:38+00:00" "time": "2023-07-13T14:29:38+00:00"
}, },
{
"name": "symfony/serializer",
"version": "v6.3.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/serializer.git",
"reference": "33deb86d212893042d7758d452aa39d19ca0efe3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/serializer/zipball/33deb86d212893042d7758d452aa39d19ca0efe3",
"reference": "33deb86d212893042d7758d452aa39d19ca0efe3",
"shasum": ""
},
"require": {
"php": ">=8.1",
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-ctype": "~1.8"
},
"conflict": {
"doctrine/annotations": "<1.12",
"phpdocumentor/reflection-docblock": "<3.2.2",
"phpdocumentor/type-resolver": "<1.4.0",
"symfony/dependency-injection": "<5.4",
"symfony/property-access": "<5.4",
"symfony/property-info": "<5.4.24|>=6,<6.2.11",
"symfony/uid": "<5.4",
"symfony/yaml": "<5.4"
},
"require-dev": {
"doctrine/annotations": "^1.12|^2",
"phpdocumentor/reflection-docblock": "^3.2|^4.0|^5.0",
"symfony/cache": "^5.4|^6.0",
"symfony/config": "^5.4|^6.0",
"symfony/console": "^5.4|^6.0",
"symfony/dependency-injection": "^5.4|^6.0",
"symfony/error-handler": "^5.4|^6.0",
"symfony/filesystem": "^5.4|^6.0",
"symfony/form": "^5.4|^6.0",
"symfony/http-foundation": "^5.4|^6.0",
"symfony/http-kernel": "^5.4|^6.0",
"symfony/mime": "^5.4|^6.0",
"symfony/property-access": "^5.4|^6.0",
"symfony/property-info": "^5.4.24|^6.2.11",
"symfony/uid": "^5.4|^6.0",
"symfony/validator": "^5.4|^6.0",
"symfony/var-dumper": "^5.4|^6.0",
"symfony/var-exporter": "^5.4|^6.0",
"symfony/yaml": "^5.4|^6.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\Serializer\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/serializer/tree/v6.3.3"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2023-07-31T07:08:24+00:00"
},
{ {
"name": "symfony/service-contracts", "name": "symfony/service-contracts",
"version": "v3.3.0", "version": "v3.3.0",

View file

@ -1,5 +1,4 @@
<?php <?php
declare(strict_types=1);
return [ return [
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true], Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
@ -13,7 +12,6 @@ return [
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true], Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true], Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true], Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true],
JMS\SerializerBundle\JMSSerializerBundle::class => ['all' => true],
Knp\Bundle\PaginatorBundle\KnpPaginatorBundle::class => ['all' => true], Knp\Bundle\PaginatorBundle\KnpPaginatorBundle::class => ['all' => true],
Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'test' => true], Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'test' => true],
]; ];

View file

@ -1,30 +0,0 @@
jms_serializer:
visitors:
xml_serialization:
format_output: '%kernel.debug%'
# metadata:
# auto_detection: false
# directories:
# any-name:
# namespace_prefix: "My\\FooBundle"
# path: "@MyFooBundle/Resources/config/serializer"
# another-name:
# namespace_prefix: "My\\BarBundle"
# path: "@MyBarBundle/Resources/config/serializer"
when@prod:
jms_serializer:
visitors:
json_serialization:
options:
- JSON_UNESCAPED_SLASHES
- JSON_PRESERVE_ZERO_FRACTION
when@dev:
jms_serializer:
visitors:
json_serialization:
options:
- JSON_PRETTY_PRINT
- JSON_UNESCAPED_SLASHES
- JSON_PRESERVE_ZERO_FRACTION

View file

@ -1,11 +0,0 @@
Skobkin\Bundle\PointToolsBundle\DTO\Api\Auth:
exclusion_policy: none
access_type: public_method
properties:
token:
type: string
csRfToken:
type: string
serialized_name: 'csrf_token'
error:
type: string

View file

@ -1,23 +0,0 @@
Skobkin\Bundle\PointToolsBundle\DTO\Api\Comment:
exclusion_policy: none
access_type: public_method
properties:
postId:
serialized_name: 'post_id'
type: 'Skobkin\Bundle\PointToolsBundle\DTO\Api\Post'
max_depth: 2
number:
serialized_name: 'id'
type: integer
toCommentId:
serialized_name: 'to_comment_id'
type: integer
created:
type: string
text:
type: string
author:
type: 'Skobkin\Bundle\PointToolsBundle\DTO\Api\User'
isRec:
serialized_name: 'is_rec'
type: boolean

View file

@ -1,10 +0,0 @@
Skobkin\Bundle\PointToolsBundle\DTO\Api\MetaPost:
exclusion_policy: none
access_type: public_method
properties:
post:
type: 'Skobkin\Bundle\PointToolsBundle\DTO\Api\Post'
max_depth: 2
comments:
type: 'array<Skobkin\Bundle\PointToolsBundle\DTO\Api\Comment>'
max_depth: 2

View file

@ -1,25 +0,0 @@
Skobkin\Bundle\PointToolsBundle\DTO\Api\Post:
exclusion_policy: none
access_type: public_method
properties:
id:
type: string
#groups: []
tags:
type: 'array<string>'
files:
type: 'array<string>'
author:
type: Skobkin\Bundle\PointToolsBundle\DTO\Api\User
max_depth: 1
text:
type: string
created:
type: string
type:
type: string
private:
type: boolean
#callback_methods:
# post_deserialize: [foo, bar]

View file

@ -1,10 +0,0 @@
Skobkin\Bundle\PointToolsBundle\DTO\Api\PostsPage:
exclusion_policy: none
access_type: public_method
properties:
posts:
type: 'array<Skobkin\Bundle\PointToolsBundle\DTO\Api\MetaPost>'
max_depth: 3
hasNext:
serialized_name: 'has_next'
type: boolean

View file

@ -1,49 +0,0 @@
Skobkin\Bundle\PointToolsBundle\DTO\Api\User:
exclusion_policy: none
access_type: public_method
properties:
id:
type: integer
groups: [user_short, user_full]
login:
type: string
groups: [user_short, user_full]
name:
type: string
groups: [user_short, user_full]
about:
type: string
groups: [user_full]
xmpp:
type: string
groups: [user_full]
created:
type: string
groups: [user_full]
gender:
type: boolean
groups: [user_full]
denyAnonymous:
serialized_name: 'deny_anonymous'
type: boolean
groups: [user_full]
private:
type: boolean
groups: [user_full]
birthDate:
serialized_name: 'birthdate'
type: string
groups: [user_full]
homepage:
type: string
groups: [user_full]
email:
type: string
groups: [user_full]
location:
type: string
groups: [user_full]
# TODO automatically convert string date to DateTime
#callback_methods:
# post_deserialize: [foo, bar]

View file

@ -1 +0,0 @@
services:

View file

@ -1,4 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Tests\Skobkin\PointToolsBundle\Service\Factory; namespace Tests\Skobkin\PointToolsBundle\Service\Factory;
@ -7,8 +8,8 @@ use App\Exception\Factory\InvalidUserDataException;
use App\Factory\UserFactory; use App\Factory\UserFactory;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use src\PointToolsBundle\Entity\User; use App\Entity\User;
use src\PointToolsBundle\Repository\UserRepository; use App\Repository\UserRepository;
class UserFactoryTest extends TestCase class UserFactoryTest extends TestCase
{ {
@ -26,8 +27,8 @@ class UserFactoryTest extends TestCase
{ {
$testUser = new User( $testUser = new User(
self::LOCAL_USER_ID, self::LOCAL_USER_ID,
\DateTime::createFromFormat(UserFactory::DATE_FORMAT, self::LOCAL_USER_CREATED),
self::LOCAL_USER_LOGIN, self::LOCAL_USER_LOGIN,
\DateTime::createFromFormat(UserFactory::DATE_FORMAT, self::LOCAL_USER_CREATED),
self::LOCAL_USER_NAME self::LOCAL_USER_NAME
); );

View file

@ -40,7 +40,7 @@ class ImportUsersCommand extends Command
'CSV file path' 'CSV file path'
) )
->addOption( ->addOption(
'check-only', 'dry-run',
null, null,
InputOption::VALUE_NONE, InputOption::VALUE_NONE,
'If set, command will not perform write operations in the database' 'If set, command will not perform write operations in the database'
@ -87,9 +87,9 @@ class ImportUsersCommand extends Command
$createdAt = \DateTime::createFromFormat('Y-m-d_H:i:s', $row[3]) ?: new \DateTime(); $createdAt = \DateTime::createFromFormat('Y-m-d_H:i:s', $row[3]) ?: new \DateTime();
$user = new User($row[0], $createdAt, $row[1], $row[2]); $user = new User($row[0], $row[1], $createdAt, $row[2]);
if (!$input->getOption('check-only')) { if (!$input->getOption('dry-run')) {
$this->em->persist($user); $this->em->persist($user);
$this->em->flush($user); $this->em->flush($user);
$this->em->detach($user); $this->em->detach($user);

View file

@ -50,7 +50,7 @@ class TelegramSendMessageCommand extends Command
try { try {
$this->messenger->sendMessageToChat( $this->messenger->sendMessageToChat(
(int) $input->getOption('chat-id'), (int) $input->getOption('chat-id'),
$message $message,
); );
} catch (\Exception $e) { } catch (\Exception $e) {
$io->error($e->getMessage()); $io->error($e->getMessage());

View file

@ -50,7 +50,7 @@ class TelegramWebhookCommand extends Command
try { try {
$this->client->setWebhook( $this->client->setWebhook(
url: $url, url: $url,
max_connections: $this->telegramWebhookMaxConnections, maxConnections: $this->telegramWebhookMaxConnections,
); );
} catch (\Exception $e) { } catch (\Exception $e) {
$io->error(\sprintf( $io->error(\sprintf(

View file

@ -42,7 +42,7 @@ class UpdateSubscriptionsCommand extends Command
'If set, command will check subscribers of all service users instead of service subscribers only' 'If set, command will check subscribers of all service users instead of service subscribers only'
) )
->addOption( ->addOption(
'check-only', 'dry-run',
null, null,
InputOption::VALUE_NONE, InputOption::VALUE_NONE,
'If set, command will not perform write operations in the database' 'If set, command will not perform write operations in the database'
@ -59,7 +59,7 @@ class UpdateSubscriptionsCommand extends Command
$progress = $io->createProgressBar(); $progress = $io->createProgressBar();
$progress->setFormat(ProgressBar::FORMAT_DEBUG); $progress->setFormat(ProgressBar::FORMAT_DEBUG);
if (!$input->getOption('check-only')) { // Beginning transaction for all changes if (!$input->getOption('dry-run')) { // Beginning transaction for all changes
$this->em->beginTransaction(); $this->em->beginTransaction();
} }
@ -92,7 +92,7 @@ class UpdateSubscriptionsCommand extends Command
$progress->finish(); $progress->finish();
// Flushing all changes at once to the database // Flushing all changes at once to the database
if (!$input->getOption('check-only')) { if (!$input->getOption('dry-run')) {
$this->em->flush(); $this->em->flush();
$this->em->commit(); $this->em->commit();
} }

View file

@ -6,8 +6,8 @@ namespace App\Controller\Api;
use App\DTO\Api\PostsPage; use App\DTO\Api\PostsPage;
use App\Factory\Blog\PostFactory; use App\Factory\Blog\PostFactory;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use JMS\Serializer\SerializerInterface;
use Symfony\Component\HttpFoundation\{Request, Response}; use Symfony\Component\HttpFoundation\{Request, Response};
use Symfony\Component\Serializer\SerializerInterface;
class CrawlerController extends AbstractApiController class CrawlerController extends AbstractApiController
{ {

View file

@ -3,41 +3,18 @@ declare(strict_types=1);
namespace App\DTO\Api; namespace App\DTO\Api;
/** TODO: Refactor to public readonly */ use Symfony\Component\Serializer\Annotation\SerializedName;
class Auth implements ValidableInterface class Auth implements ValidableInterface
{ {
private ?string $token; public function __construct(
private ?string $csRfToken; #[SerializedName('token')]
private ?string $error; public readonly ?string $token,
#[SerializedName('error')]
public function getToken(): ?string public readonly ?string $error,
{ #[SerializedName('csrf_token')]
return $this->token; public readonly ?string $csRfToken,
} ) {
public function setToken(?string $token): void
{
$this->token = $token;
}
public function getCsRfToken(): ?string
{
return $this->csRfToken;
}
public function setCsRfToken(?string $csRfToken): void
{
$this->csRfToken = $csRfToken;
}
public function getError(): ?string
{
return $this->error;
}
public function setError(?string $error): void
{
$this->error = $error;
} }
public function isValid(): bool public function isValid(): bool

View file

@ -3,91 +3,26 @@ declare(strict_types=1);
namespace App\DTO\Api; namespace App\DTO\Api;
/** TODO: Refactor to public readonly */ use Symfony\Component\Serializer\Annotation\SerializedName;
class Comment implements ValidableInterface class Comment implements ValidableInterface
{ {
private ?string $postId; public function __construct(
private ?int $number; #[SerializedName('post_id')]
private ?int $toCommentId; public readonly ?string $postId,
private ?string $created; #[SerializedName('id')]
private ?string $text; public readonly ?int $number,
private ?User $author; #[SerializedName('to_comment_id')]
private ?bool $isRec; public readonly ?int $toCommentId,
#[SerializedName('created')]
public readonly ?\DateTimeImmutable $created,
public function getPostId(): ?string #[SerializedName('text')]
{ public readonly ?string $text,
return $this->postId; #[SerializedName('author')]
} public readonly ?User $author,
#[SerializedName('is_rec')]
public function setPostId(?string $postId): void public readonly ?bool $isRec,
{ ) {
$this->postId = $postId;
}
public function getNumber(): ?int
{
return $this->number;
}
public function setNumber(?int $number): void
{
$this->number = $number;
}
public function getToCommentId(): ?int
{
return $this->toCommentId;
}
public function setToCommentId(?int $toCommentId): void
{
$this->toCommentId = $toCommentId;
}
public function getCreated(): string
{
return $this->created;
}
public function setCreated(?string $created): void
{
$this->created = $created;
}
public function getText(): ?string
{
return $this->text;
}
public function setText(?string $text): void
{
$this->text = $text;
}
public function getAuthor(): ?User
{
return $this->author;
}
public function setAuthor(?User $author): void
{
$this->author = $author;
}
public function isIsRec(): ?bool
{
return $this->isRec;
}
public function getIsRec(): ?bool
{
return $this->isRec;
}
public function setIsRec(?bool $isRec): void
{
$this->isRec = $isRec;
} }
public function isValid(): bool public function isValid(): bool

View file

@ -3,34 +3,21 @@ declare(strict_types=1);
namespace App\DTO\Api; namespace App\DTO\Api;
/** TODO: Refactor to public readonly */ use Symfony\Component\Serializer\Annotation\{MaxDepth, SerializedName};
class MetaPost implements ValidableInterface class MetaPost implements ValidableInterface
{ {
private ?Post $post; /**
/** @var Comment[]|null */ * @param Comment[] $comments
private ?array $comments; */
public function __construct(
#[SerializedName('post')]
public function getPost(): ?Post #[MaxDepth(2)]
{ public readonly ?Post $post,
return $this->post; #[SerializedName('comments')]
} #[MaxDepth(2)]
public readonly ?array $comments,
public function setPost(?Post $post): void ) {
{
$this->post = $post;
}
/** @return Comment[]|null */
public function getComments(): ?array
{
return $this->comments;
}
/** @param Comment[]|null $comments */
public function setComments(?array $comments): void
{
$this->comments = $comments;
} }
public function isValid(): bool public function isValid(): bool

View file

@ -3,108 +3,32 @@ declare(strict_types=1);
namespace App\DTO\Api; namespace App\DTO\Api;
/** TODO: Refactor to public readonly */ use App\Enum\Blog\PostTypeEnum;
use Symfony\Component\Serializer\Annotation\{Context, MaxDepth, SerializedName};
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
class Post implements ValidableInterface class Post implements ValidableInterface
{ {
private ?string $id; public function __construct(
/** @var string[]|null */ #[SerializedName('id')]
private ?array $tags; public readonly ?string $id,
/** @var string[]|null */ #[SerializedName('tags')]
private ?array $files; public readonly ?array $tags,
private ?User $author; #[SerializedName('files')]
private ?string $text; public readonly ?array $files,
private ?string $created; #[SerializedName('author')]
private ?string $type; #[MaxDepth(1)]
private ?bool $private; public readonly ?User $author,
#[SerializedName('text')]
public function getId(): ?string public readonly ?string $text,
{ #[SerializedName('created')]
return $this->id; #[Context([DateTimeNormalizer::FORMAT_KEY => 'Y-m-d_H:i:s'])]
} public readonly ?\DateTimeImmutable $created,
#[SerializedName('type')]
public function setId(?string $id): void public readonly ?PostTypeEnum $type,
{ #[SerializedName('private')]
$this->id = $id; public readonly ?bool $private,
} ) {
/** @return string[]|null */
public function getTags(): ?array
{
return $this->tags;
}
public function setTags(?array $tags): void
{
$this->tags = $tags;
}
/** @return string[]|null */
public function getFiles(): ?array
{
return $this->files;
}
/**
* @param string[]|null $files
*/
public function setFiles(?array $files): void
{
$this->files = $files;
}
public function getAuthor(): ?User
{
return $this->author;
}
public function setAuthor(?User $author): void
{
$this->author = $author;
}
public function getText(): ?string
{
return $this->text;
}
public function setText(?string $text): void
{
$this->text = $text;
}
public function getCreated(): ?string
{
return $this->created;
}
public function setCreated(?string $created): void
{
$this->created = $created;
}
public function getType(): ?string
{
return $this->type;
}
public function setType(?string $type): void
{
$this->type = $type;
}
public function getPrivate(): ?bool
{
return $this->private;
}
public function isPrivate(): ?bool
{
return $this->private;
}
public function setPrivate(?bool $private): void
{
$this->private = $private;
} }
public function isValid(): bool public function isValid(): bool

View file

@ -3,33 +3,15 @@ declare(strict_types=1);
namespace App\DTO\Api; namespace App\DTO\Api;
/** TODO: Refactor to public readonly */
class PostsPage implements ValidableInterface class PostsPage implements ValidableInterface
{ {
/** @var MetaPost[]|null */ /**
private ?array $posts; * @param MetaPost[]|null $posts
private ?bool $hasNext; */
public function __construct(
/** @return MetaPost[]|null */ public readonly ?array $posts,
public function getPosts(): ?array public readonly ?bool $hasNext,
{ ) {
return $this->posts;
}
/** @param MetaPost[]|null $posts */
public function setPosts(?array $posts): void
{
$this->posts = $posts;
}
public function getHasNext(): ?bool
{
return $this->hasNext;
}
public function setHasNext(?bool $hasNext): void
{
$this->hasNext = $hasNext;
} }
public function isValid(): bool public function isValid(): bool

View file

@ -3,166 +3,57 @@ declare(strict_types=1);
namespace App\DTO\Api; namespace App\DTO\Api;
/** TODO: Refactor to public readonly */ use Symfony\Component\Serializer\Annotation\{Context, Groups, SerializedName};
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
class User implements ValidableInterface class User implements ValidableInterface
{ {
private ?string $id; public function __construct(
private ?string $login; #[SerializedName('id')]
private ?string $name; #[Groups(['user_short', 'user_full'])]
private ?string $about; public readonly ?int $id,
private ?string $xmpp; #[SerializedName('login')]
private ?string $created; #[Groups(['user_short', 'user_full'])]
private ?bool $gender; public readonly ?string $login,
private ?bool $denyAnonymous; #[SerializedName('name')]
private ?bool $private; #[Groups(['user_short', 'user_full'])]
private ?string $birthDate; public readonly ?string $name,
private ?string $homepage; #[SerializedName('about')]
private ?string $email; #[Groups(['user_full'])]
private ?string $location; public readonly ?string $about,
private ?string $error; #[SerializedName('xmpp')]
#[Groups(['user_full'])]
public function getId(): ?string public readonly ?string $xmpp,
{ #[SerializedName('created')]
return $this->id; #[Groups(['user_full'])]
} #[Context([DateTimeNormalizer::FORMAT_KEY => 'Y-m-d_H:i:s'])]
public readonly ?\DateTimeImmutable $created,
public function setId(?string $id): void #[SerializedName('gender')]
{ #[Groups(['user_full'])]
$this->id = $id; public readonly ?bool $gender,
} #[SerializedName('deny_anonymous')]
#[Groups(['user_full'])]
public function getLogin(): ?string public readonly ?bool $denyAnonymous,
{ #[SerializedName('private')]
return $this->login; #[Groups(['user_full'])]
} public readonly ?bool $private,
#[SerializedName('birthdate')]
public function setLogin(?string $login): void #[Groups(['user_full'])]
{ public readonly ?string $birthDate,
$this->login = $login; #[SerializedName('homepage')]
} #[Groups(['user_full'])]
public readonly ?string $homepage,
public function getName(): ?string #[SerializedName('email')]
{ #[Groups(['user_full'])]
return $this->name; public readonly ?string $email,
} #[SerializedName('location')]
#[Groups(['user_full'])]
public function setName(?string $name): void public readonly ?string $location,
{ ) {
$this->name = $name;
}
public function getAbout(): ?string
{
return $this->about;
}
public function setAbout(?string $about): void
{
$this->about = $about;
}
public function getXmpp(): ?string
{
return $this->xmpp;
}
public function setXmpp(?string $xmpp): void
{
$this->xmpp = $xmpp;
}
public function getCreated(): ?string
{
return $this->created;
}
public function setCreated(?string $created): void
{
$this->created = $created;
}
public function getGender(): ?bool
{
return $this->gender;
}
public function setGender(?bool $gender): void
{
$this->gender = $gender;
}
public function getDenyAnonymous(): ?bool
{
return $this->denyAnonymous;
}
public function setDenyAnonymous(?bool $denyAnonymous): void
{
$this->denyAnonymous = $denyAnonymous;
}
public function getPrivate(): ?bool
{
return $this->private;
}
public function setPrivate(?bool $private): void
{
$this->private = $private;
}
public function getBirthDate(): ?string
{
return $this->birthDate;
}
public function setBirthDate(?string $birthDate): void
{
$this->birthDate = $birthDate;
}
public function getHomepage(): ?string
{
return $this->homepage;
}
public function setHomepage(?string $homepage): void
{
$this->homepage = $homepage;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(?string $email): void
{
$this->email = $email;
}
public function getLocation(): ?string
{
return $this->location;
}
public function setLocation(?string $location): void
{
$this->location = $location;
}
public function getError(): ?string
{
return $this->error;
}
public function setError(?string $error): void
{
$this->error = $error;
} }
public function isValid(): bool public function isValid(): bool
{ {
return null === $this->error && null !== $this->id && null !== $this->login; return null !== $this->id && null !== $this->login;
} }
} }

View file

@ -3,7 +3,9 @@ declare(strict_types=1);
namespace App\DTO\Api; namespace App\DTO\Api;
/** @deprecated Use Symfony Validator instead */
interface ValidableInterface interface ValidableInterface
{ {
/** @deprecated Use Symfony Validator instead */
public function isValid(): bool; public function isValid(): bool;
} }

View file

@ -29,7 +29,7 @@ class LoadUserData extends Fixture implements OrderedFixtureInterface
public function load(ObjectManager $om) public function load(ObjectManager $om)
{ {
foreach ($this->users as $userData) { foreach ($this->users as $userData) {
$user = new User($userData['id'], new \DateTime(), $userData['login'], $userData['name']); $user = new User($userData['id'], $userData['login'], new \DateTime(), $userData['name']);
$user->updatePrivacy(!$userData['private'], $userData['whitelist-only']); $user->updatePrivacy(!$userData['private'], $userData['whitelist-only']);
$om->persist($user); $om->persist($user);

View file

@ -22,7 +22,7 @@ class Post
private string $text; private string $text;
#[ORM\Column(name: 'created_at', type: 'datetime')] #[ORM\Column(name: 'created_at', type: 'datetime')]
private \DateTime $createdAt; private \DateTimeImmutable $createdAt;
#[ORM\Column(name: 'updated_at', type: 'datetime', nullable: true)] #[ORM\Column(name: 'updated_at', type: 'datetime', nullable: true)]
private ?\DateTime $updatedAt; private ?\DateTime $updatedAt;
@ -56,7 +56,7 @@ class Post
private Collection $comments; private Collection $comments;
public function __construct(string $id, User $author, \DateTime $createdAt, PostTypeEnum $type) public function __construct(string $id, User $author, \DateTimeImmutable $createdAt, PostTypeEnum $type)
{ {
$this->id = $id; $this->id = $id;
$this->author = $author; $this->author = $author;
@ -91,7 +91,7 @@ class Post
return $this->text; return $this->text;
} }
public function getCreatedAt(): \DateTime public function getCreatedAt(): \DateTimeImmutable
{ {
return $this->createdAt; return $this->createdAt;
} }

View file

@ -54,8 +54,8 @@ class User
public function __construct( public function __construct(
int $id, int $id,
string $login,
\DateTime $createdAt = null, \DateTime $createdAt = null,
string $login = null,
string $name = null string $name = null
) { ) {
$this->id = $id; $this->id = $id;

View file

@ -8,7 +8,7 @@ use Psr\Log\LoggerInterface;
abstract class AbstractFactory abstract class AbstractFactory
{ {
public function __construct( public function __construct(
protected LoggerInterface $logger, protected readonly LoggerInterface $logger,
) { ) {
} }
} }

View file

@ -1,21 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Factory\Blog;
use App\Factory\{AbstractFactory};
use App\Factory\UserFactory;
use Psr\Log\LoggerInterface;
use App\Repository\Blog\{CommentRepository, PostRepository};
class CommentFactory extends AbstractFactory
{
public function __construct(
LoggerInterface $logger,
private readonly CommentRepository $commentRepository,
private readonly PostRepository $postRepository,
private readonly UserFactory $userFactory,
) {
parent::__construct($logger);
}
}

View file

@ -4,8 +4,7 @@ declare(strict_types=1);
namespace App\Factory\Blog; namespace App\Factory\Blog;
use App\Enum\Blog\PostTypeEnum; use App\Enum\Blog\PostTypeEnum;
use App\Factory\AbstractFactory; use App\Factory\{AbstractFactory, UserFactory};
use App\Factory\UserFactory;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use App\DTO\Api\{MetaPost, PostsPage, Post as PostDTO}; use App\DTO\Api\{MetaPost, PostsPage, Post as PostDTO};
@ -23,7 +22,6 @@ class PostFactory extends AbstractFactory
private readonly PostRepository $postRepository, private readonly PostRepository $postRepository,
private readonly UserFactory $userFactory, private readonly UserFactory $userFactory,
private readonly FileFactory $fileFactory, private readonly FileFactory $fileFactory,
private readonly CommentFactory $commentFactory,
private readonly TagFactory $tagFactory, private readonly TagFactory $tagFactory,
) { ) {
parent::__construct($logger); parent::__construct($logger);
@ -40,9 +38,10 @@ class PostFactory extends AbstractFactory
$hasNew = false; $hasNew = false;
foreach ((array) $page->getPosts() as $postData) { /** @var MetaPost $postData */
foreach ($page->posts ?? [] as $postData) {
try { try {
if (null === $this->postRepository->find($postData->getPost()->getId())) { if (null === $this->postRepository->find($postData->post->id)) {
$hasNew = true; $hasNew = true;
} }
@ -50,7 +49,7 @@ class PostFactory extends AbstractFactory
$posts[] = $post; $posts[] = $post;
} catch (\Exception $e) { } catch (\Exception $e) {
$this->logger->error('Error while processing post DTO', [ $this->logger->error('Error while processing post DTO', [
'post_id' => $postData->getPost()->getId(), 'post_id' => $postData->post->id,
'exception' => get_class($e), 'exception' => get_class($e),
'message' => $e->getMessage(), 'message' => $e->getMessage(),
'file' => $e->getFile(), 'file' => $e->getFile(),
@ -82,10 +81,10 @@ class PostFactory extends AbstractFactory
throw new InvalidDataException('Invalid post data'); throw new InvalidDataException('Invalid post data');
} }
$postData = $metaPost->getPost(); $postData = $metaPost->post;
try { try {
$author = $this->userFactory->findOrCreateFromDTO($metaPost->getPost()->getAuthor()); $author = $this->userFactory->findOrCreateFromDTO($postData->author);
} catch (\Exception $e) { } catch (\Exception $e) {
$this->logger->error('Error while creating user from DTO'); $this->logger->error('Error while creating user from DTO');
throw $e; throw $e;
@ -94,14 +93,14 @@ class PostFactory extends AbstractFactory
$post = $this->findOrCreateFromDto($postData, $author); $post = $this->findOrCreateFromDto($postData, $author);
try { try {
$this->updatePostTags($post, $postData->getTags() ?: []); $this->updatePostTags($post, $postData->tags ?? []);
} catch (\Exception $e) { } catch (\Exception $e) {
$this->logger->error('Error while updating post tags'); $this->logger->error('Error while updating post tags');
throw $e; throw $e;
} }
try { try {
$this->updatePostFiles($post, $postData->getFiles() ?: []); $this->updatePostFiles($post, $postData->files ?? []);
} catch (\Exception $e) { } catch (\Exception $e) {
$this->logger->error('Error while updating post files'); $this->logger->error('Error while updating post files');
throw $e; throw $e;
@ -112,20 +111,19 @@ class PostFactory extends AbstractFactory
private function findOrCreateFromDto(PostDTO $postData, User $author): Post private function findOrCreateFromDto(PostDTO $postData, User $author): Post
{ {
if (null === ($post = $this->postRepository->find($postData->getId()))) { if (null === ($post = $this->postRepository->find($postData->id))) {
// Creating new post
$post = new Post( $post = new Post(
$postData->getId(), $postData->id,
$author, $author,
new \DateTime($postData->getCreated()), $postData->created,
PostTypeEnum::tryFrom($postData->getType()) ?? PostTypeEnum::Post, $postData->type ?? PostTypeEnum::Post,
); );
$this->postRepository->save($post); $this->postRepository->save($post);
} }
$post $post
->setText($postData->getText()) ->setText($postData->text)
->setPrivate($postData->getPrivate()) ->setPrivate($postData->private)
; ;
return $post; return $post;

View file

@ -29,18 +29,19 @@ class UserFactory extends AbstractFactory
} }
/** @var User $user */ /** @var User $user */
if (null === ($user = $this->userRepository->find($userData->getId()))) { if (null === ($user = $this->userRepository->find($userData->id))) {
$user = new User( $user = new User(
(int) $userData->getId(), $userData->id,
\DateTime::createFromFormat('Y-m-d_H:i:s', $userData->getCreated()) ?: new \DateTime() $userData->login,
$userData->created,
); );
$this->userRepository->add($user); $this->userRepository->save($user);
} }
$user->updateLoginAndName($userData->getLogin(), $userData->getName()); $user->updateLoginAndName($userData->login, $userData->name);
if (null !== $userData->getDenyAnonymous() && null !== $userData->getPrivate()) { if (null !== $userData->denyAnonymous && null !== $userData->private) {
$user->updatePrivacy(!$userData->getDenyAnonymous(), $userData->getPrivate()); $user->updatePrivacy(!$userData->denyAnonymous, $userData->private);
} }
return $user; return $user;

View file

@ -9,14 +9,14 @@ use App\Exception\Api\{ApiException,
NotFoundException, NotFoundException,
UnauthorizedException, UnauthorizedException,
ServerProblemException}; ServerProblemException};
use JMS\Serializer\SerializerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Response as SymfonyResponse; use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
use Symfony\Component\Serializer\Context\Normalizer\ObjectNormalizerContextBuilder;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface; use Symfony\Contracts\HttpClient\{HttpClientInterface, ResponseInterface};
use Symfony\Contracts\HttpClient\ResponseInterface;
class AbstractApi abstract class AbstractApi
{ {
protected HttpClientInterface $client; protected HttpClientInterface $client;
// TODO: check if these are still needed // TODO: check if these are still needed
@ -32,24 +32,24 @@ class AbstractApi
} }
/** Make GET request and return DTO objects */ /** Make GET request and return DTO objects */
public function getGetJsonData(string $path, array $parameters = [], string $type, DeserializationContext $context = null): array|object|null public function getGetJsonData(string $path, array $parameters = [], string $type, array $groups = []): array|object|null
{ {
return $this->serializer->deserialize( return $this->serializer->deserialize(
$this->getGetResponseBody($path, $parameters), $this->getGetResponseBody($path, $parameters),
$type, $type,
'json', 'json',
$context $this->createContext($groups),
); );
} }
/** Make POST request and return DTO objects */ /** Make POST request and return DTO objects */
public function getPostJsonData(string $path, array $parameters = [], string $type, DeserializationContext $context = null): array|object|null public function getPostJsonData(string $path, array $parameters = [], string $type, array $groups = []): array|object|null
{ {
return $this->serializer->deserialize( return $this->serializer->deserialize(
$this->getPostResponseBody($path, $parameters), $this->getPostResponseBody($path, $parameters),
$type, $type,
'json', 'json',
$context $this->createContext($groups)
); );
} }
@ -65,6 +65,13 @@ class AbstractApi
return $this->sendPostRequest($path, $parameters)->getContent(); return $this->sendPostRequest($path, $parameters)->getContent();
} }
private function createContext(array $groups): array
{
return (new ObjectNormalizerContextBuilder())
->withGroups($groups)
->toArray();
}
private function sendGetRequest(string $path, array $parameters = []): ResponseInterface private function sendGetRequest(string $path, array $parameters = []): ResponseInterface
{ {
$this->logger->debug('Sending GET request', ['path' => $path, 'parameters' => $parameters]); $this->logger->debug('Sending GET request', ['path' => $path, 'parameters' => $parameters]);
@ -103,7 +110,7 @@ class AbstractApi
// Temporary fix until @arts fixes this bug // Temporary fix until @arts fixes this bug
if ('{"error": "UserNotFound"}' === $response->getContent()) { if ('{"error": "UserNotFound"}' === $response->getContent()) {
throw new NotFoundException('Not found', SymfonyResponse::HTTP_NOT_FOUND); throw new NotFoundException('Not found', SymfonyResponse::HTTP_NOT_FOUND);
} elseif ('{"message": "Forbidden", "code": 403, "error": "Forbidden"}' === (string) $response->getBody()) { } elseif ('{"message": "Forbidden", "code": 403, "error": "Forbidden"}' === (string) $response->getContent()) {
throw new ForbiddenException('Forbidden', SymfonyResponse::HTTP_FORBIDDEN); throw new ForbiddenException('Forbidden', SymfonyResponse::HTTP_FORBIDDEN);
} }

View file

@ -1,22 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Service\Api;
use JMS\Serializer\SerializerInterface;
use Psr\Log\LoggerInterface;
use App\Factory\Blog\PostFactory;
use Symfony\Contracts\HttpClient\HttpClientInterface;
/** Basic Point.im user API functions from /api/post */
class PostApi extends AbstractApi
{
public function __construct(
HttpClientInterface $pointApiClient,
SerializerInterface $serializer,
LoggerInterface $logger,
private readonly PostFactory $postFactory,
) {
parent::__construct($pointApiClient, $logger, $serializer);
}
}

View file

@ -11,8 +11,8 @@ use App\Exception\Api\{ForbiddenException,
UserNotFoundException UserNotFoundException
}; };
use App\Factory\UserFactory; use App\Factory\UserFactory;
use JMS\Serializer\{DeserializationContext, SerializerInterface};
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface; use Symfony\Contracts\HttpClient\HttpClientInterface;
/** Basic Point.im user API functions from /api/user/* */ /** Basic Point.im user API functions from /api/user/* */
@ -89,8 +89,8 @@ class UserApi extends AbstractApi
$usersList = $this->getGetJsonData( $usersList = $this->getGetJsonData(
self::PREFIX.urlencode($login).'/subscribers', self::PREFIX.urlencode($login).'/subscribers',
[], [],
'array<'.UserDTO::class.'>', UserDTO::class.'[]',
DeserializationContext::create()->setGroups(['user_short']), ['user_short'],
); );
} catch (NotFoundException $e) { } catch (NotFoundException $e) {
throw new UserNotFoundException('User not found', 0, $e, null, $login); throw new UserNotFoundException('User not found', 0, $e, null, $login);
@ -108,8 +108,8 @@ class UserApi extends AbstractApi
$usersList = $this->getGetJsonData( $usersList = $this->getGetJsonData(
self::PREFIX.'id/'.$id.'/subscribers', self::PREFIX.'id/'.$id.'/subscribers',
[], [],
'array<'.UserDTO::class.'>', UserDTO::class.'[]',
DeserializationContext::create()->setGroups(['user_short']), ['user_short'],
); );
} catch (NotFoundException $e) { } catch (NotFoundException $e) {
throw new UserNotFoundException('User not found', 0, $e, $id); throw new UserNotFoundException('User not found', 0, $e, $id);
@ -128,7 +128,7 @@ class UserApi extends AbstractApi
self::PREFIX.'login/'.urlencode($login), self::PREFIX.'login/'.urlencode($login),
[], [],
UserDTO::class, UserDTO::class,
DeserializationContext::create()->setGroups(['user_full']), ['user_full'],
); );
} catch (NotFoundException $e) { } catch (NotFoundException $e) {
throw new UserNotFoundException('User not found', 0, $e, null, $login); throw new UserNotFoundException('User not found', 0, $e, null, $login);
@ -147,7 +147,7 @@ class UserApi extends AbstractApi
self::PREFIX.'id/'.$id, self::PREFIX.'id/'.$id,
[], [],
UserDTO::class, UserDTO::class,
DeserializationContext::create()->setGroups(['user_full']), ['user_full'],
); );
} catch (NotFoundException $e) { } catch (NotFoundException $e) {
throw new UserNotFoundException('User not found', 0, $e, $id); throw new UserNotFoundException('User not found', 0, $e, $id);

View file

@ -47,18 +47,6 @@
"migrations/.gitignore" "migrations/.gitignore"
] ]
}, },
"jms/serializer-bundle": {
"version": "5.2",
"recipe": {
"repo": "github.com/symfony/recipes-contrib",
"branch": "main",
"version": "4.0",
"ref": "cc04e10cf7171525b50c18b36004edf64cb478be"
},
"files": [
"config/packages/jms_serializer.yaml"
]
},
"knplabs/knp-paginator-bundle": { "knplabs/knp-paginator-bundle": {
"version": "v6.2.0" "version": "v6.2.0"
}, },