WIP: Extend and improve profile editing
This commit is contained in:
+68
-156
@@ -2,24 +2,29 @@
|
||||
|
||||
namespace App\BusProNet;
|
||||
|
||||
use App\BusProNet\Model\BaseResponse;
|
||||
use App\BusProNet\Model\BaseDataResponse;
|
||||
use App\BusProNet\Model\CrmAttributesResponse;
|
||||
use App\BusProNet\Model\NotificationResponse;
|
||||
use App\BusProNet\Model\ProfileResponse;
|
||||
use App\Entity\User;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Serializer\SerializerInterface;
|
||||
use Symfony\Contracts\Cache\CacheInterface;
|
||||
use Symfony\Contracts\Cache\ItemInterface;
|
||||
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||
|
||||
class ApiClient
|
||||
{
|
||||
public const TYPE_NOTIFICATION = 'HINWEIS';
|
||||
public const TYPE_CUSTOMER_DATA = 'KUNDENKONTO';
|
||||
public const TYPE_BASE_DATA_COUNTRIES = 'STAMMLAENDER';
|
||||
public const TYPE_BASE_DATA_PICKUPS = 'STAMMZUSTIEGE';
|
||||
|
||||
private array $config;
|
||||
|
||||
public function __construct(
|
||||
private readonly HttpClientInterface $httpClient,
|
||||
private readonly SerializerInterface $serializer,
|
||||
private readonly ResponseParser $responseParser,
|
||||
private readonly CacheInterface $cache,
|
||||
private readonly LoggerInterface $logger,
|
||||
array $options
|
||||
) {
|
||||
@@ -29,41 +34,26 @@ class ApiClient
|
||||
/**
|
||||
* @throws ApiClientException
|
||||
*/
|
||||
public function getProfile(string $email, string $password): BaseResponse
|
||||
public function getProfile(string $email, string $password): ProfileResponse
|
||||
{
|
||||
$data = [
|
||||
'anfrage' => [
|
||||
'user' => $this->config['bpn_username'],
|
||||
'key' => $this->createKey($this->config['bpn_username'], $this->config['bpn_password'], 'KUNDENKONTO'),
|
||||
'satz' => ['@typ' => 'KUNDENKONTO'],
|
||||
'key' => $this->createKey($this->config['bpn_username'], $this->config['bpn_password'], static::TYPE_CUSTOMER_DATA),
|
||||
'satz' => ['@typ' => static::TYPE_CUSTOMER_DATA],
|
||||
'art' => 'Adressdaten',
|
||||
'email' => $email,
|
||||
'passwort' => md5($password),
|
||||
],
|
||||
];
|
||||
|
||||
$body = $this
|
||||
->serializer
|
||||
->serialize($data, 'xml');
|
||||
|
||||
try {
|
||||
$response = $this->httpClient->request('GET', $this->config['bpn_url'], [
|
||||
'query' => [
|
||||
'operation' => $body,
|
||||
]
|
||||
]);
|
||||
|
||||
$xml = $response->getContent();
|
||||
|
||||
return $this->responseParser->parseXmlString($xml);
|
||||
} catch (\Throwable $e) {
|
||||
}
|
||||
|
||||
$this->logger->error('API error', ['error' => $e->getMessage()]);
|
||||
throw new ApiClientException($e->getMessage());
|
||||
return $this->sendRequest(static::TYPE_CUSTOMER_DATA, $data);
|
||||
}
|
||||
|
||||
public function updateProfile(User $user, string $password): BaseResponse
|
||||
/**
|
||||
* @throws ApiClientException
|
||||
*/
|
||||
public function updateProfile(User $user, string $password): ProfileResponse
|
||||
{
|
||||
if (null === $teamer = $user->getTeamer()) {
|
||||
throw new ApiClientException('Invalid argument');
|
||||
@@ -72,8 +62,8 @@ class ApiClient
|
||||
$data = [
|
||||
'anfrage' => [
|
||||
'user' => $this->config['bpn_username'],
|
||||
'key' => $this->createKey($this->config['bpn_username'], $this->config['bpn_password'], 'KUNDENKONTO'),
|
||||
'satz' => ['@typ' => 'KUNDENKONTO'],
|
||||
'key' => $this->createKey($this->config['bpn_username'], $this->config['bpn_password'], static::TYPE_CUSTOMER_DATA),
|
||||
'satz' => ['@typ' => static::TYPE_CUSTOMER_DATA],
|
||||
'art' => 'Adressdaten_Ändern',
|
||||
'email' => $user->getEmail(),
|
||||
'passwort' => md5($password),
|
||||
@@ -82,79 +72,71 @@ class ApiClient
|
||||
],
|
||||
];
|
||||
|
||||
$body = $this
|
||||
->serializer
|
||||
->serialize($data, 'xml');
|
||||
|
||||
try {
|
||||
$response = $this->httpClient->request('GET', $this->config['bpn_url'], [
|
||||
'query' => [
|
||||
'operation' => $body,
|
||||
]
|
||||
]);
|
||||
|
||||
$xml = $response->getContent();
|
||||
|
||||
return $this->responseParser->parseXmlString($xml);
|
||||
} catch (\Throwable $e) {
|
||||
}
|
||||
|
||||
$this->logger->error('API error', ['error' => $e->getMessage()]);
|
||||
throw new ApiClientException($e->getMessage());
|
||||
}
|
||||
|
||||
public function resetPassword(string $email): BaseResponse
|
||||
{
|
||||
$data = [
|
||||
'anfrage' => [
|
||||
'user' => $this->config['bpn_username'],
|
||||
'key' => $this->createKey($this->config['bpn_username'], $this->config['bpn_password'], 'KUNDENKONTO'),
|
||||
'satz' => ['@typ' => 'KUNDENKONTO'],
|
||||
'art' => 'Passwort_Anfrage',
|
||||
'email' => $email,
|
||||
],
|
||||
];
|
||||
|
||||
$body = $this
|
||||
->serializer
|
||||
->serialize($data, 'xml');
|
||||
|
||||
try {
|
||||
$response = $this->httpClient->request('GET', $this->config['bpn_url'], [
|
||||
'query' => [
|
||||
'operation' => $body,
|
||||
]
|
||||
]);
|
||||
|
||||
$xml = $response->getContent();
|
||||
|
||||
return $this->responseParser->parseXmlString($xml);
|
||||
} catch (\Throwable $e) {
|
||||
}
|
||||
|
||||
$this->logger->error('API error', ['error' => $e->getMessage()]);
|
||||
throw new ApiClientException($e->getMessage());
|
||||
return $this->sendRequest(static::TYPE_CUSTOMER_DATA, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ApiClientException
|
||||
*/
|
||||
public function getCrmAttributes(string $email, string $password): BaseResponse
|
||||
public function resetPassword(string $email): NotificationResponse
|
||||
{
|
||||
$data = [
|
||||
'anfrage' => [
|
||||
'user' => $this->config['bpn_username'],
|
||||
'key' => $this->createKey($this->config['bpn_username'], $this->config['bpn_password'], 'KUNDENKONTO'),
|
||||
'satz' => ['@typ' => 'KUNDENKONTO'],
|
||||
'key' => $this->createKey($this->config['bpn_username'], $this->config['bpn_password'], static::TYPE_CUSTOMER_DATA),
|
||||
'satz' => ['@typ' => static::TYPE_CUSTOMER_DATA],
|
||||
'art' => 'Passwort_Anfrage',
|
||||
'email' => $email,
|
||||
],
|
||||
];
|
||||
|
||||
return $this->sendRequest(static::TYPE_CUSTOMER_DATA, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ApiClientException
|
||||
*/
|
||||
public function getCrmAttributes(string $email, string $password): CrmAttributesResponse
|
||||
{
|
||||
$data = [
|
||||
'anfrage' => [
|
||||
'user' => $this->config['bpn_username'],
|
||||
'key' => $this->createKey($this->config['bpn_username'], $this->config['bpn_password'], static::TYPE_CUSTOMER_DATA),
|
||||
'satz' => ['@typ' => static::TYPE_CUSTOMER_DATA],
|
||||
'art' => 'SelektionCRM',
|
||||
'email' => $email,
|
||||
'passwort' => md5($password),
|
||||
],
|
||||
];
|
||||
|
||||
return $this->sendRequest(static::TYPE_CUSTOMER_DATA, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ApiClientException
|
||||
*/
|
||||
public function getBaseData(string $type): BaseDataResponse
|
||||
{
|
||||
$data = [
|
||||
'anfrage' => [
|
||||
'user' => $this->config['bpn_username'],
|
||||
'key' => $this->createKey($this->config['bpn_username'], $this->config['bpn_password'], $type),
|
||||
'satz' => ['@typ' => $type],
|
||||
],
|
||||
];
|
||||
|
||||
return $this->sendRequest($type, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ApiClientException
|
||||
*/
|
||||
private function sendRequest(string $type, array $data): mixed
|
||||
{
|
||||
$body = $this
|
||||
->serializer
|
||||
->serialize($data, 'xml');
|
||||
->serialize($data, 'xml')
|
||||
;
|
||||
|
||||
try {
|
||||
$response = $this->httpClient->request('GET', $this->config['bpn_url'], [
|
||||
@@ -165,7 +147,7 @@ class ApiClient
|
||||
|
||||
$xml = $response->getContent();
|
||||
|
||||
return $this->responseParser->parseXmlString($xml);
|
||||
return $this->responseParser->parseXmlString($type, $xml);
|
||||
} catch (\Throwable $e) {
|
||||
}
|
||||
|
||||
@@ -173,76 +155,6 @@ class ApiClient
|
||||
throw new ApiClientException($e->getMessage());
|
||||
}
|
||||
|
||||
public function getCountries(): BaseResponse
|
||||
{
|
||||
return $this->cache->get('bpn_countries', function (ItemInterface $item) {
|
||||
$item->expiresAfter(3600);
|
||||
|
||||
$data = [
|
||||
'anfrage' => [
|
||||
'user' => $this->config['bpn_username'],
|
||||
'key' => $this->createKey($this->config['bpn_username'], $this->config['bpn_password'], 'STAMMLAENDER'),
|
||||
'satz' => ['@typ' => 'STAMMLAENDER'],
|
||||
],
|
||||
];
|
||||
|
||||
$body = $this
|
||||
->serializer
|
||||
->serialize($data, 'xml');
|
||||
|
||||
try {
|
||||
$response = $this->httpClient->request('GET', $this->config['bpn_url'], [
|
||||
'query' => [
|
||||
'operation' => $body,
|
||||
]
|
||||
]);
|
||||
|
||||
$xml = $response->getContent();
|
||||
|
||||
return $this->responseParser->parseXmlString($xml);
|
||||
} catch (\Throwable $e) {
|
||||
}
|
||||
|
||||
$this->logger->error('API error', ['error' => $e->getMessage()]);
|
||||
throw new ApiClientException($e->getMessage());
|
||||
});
|
||||
}
|
||||
|
||||
public function getPickups(): BaseResponse
|
||||
{
|
||||
return $this->cache->get('bpn_pickups', function (ItemInterface $item) {
|
||||
$item->expiresAfter(3600);
|
||||
|
||||
$data = [
|
||||
'anfrage' => [
|
||||
'user' => $this->config['bpn_username'],
|
||||
'key' => $this->createKey($this->config['bpn_username'], $this->config['bpn_password'], 'STAMMZUSTIEGE'),
|
||||
'satz' => ['@typ' => 'STAMMZUSTIEGE'],
|
||||
],
|
||||
];
|
||||
|
||||
$body = $this
|
||||
->serializer
|
||||
->serialize($data, 'xml');
|
||||
|
||||
try {
|
||||
$response = $this->httpClient->request('GET', $this->config['bpn_url'], [
|
||||
'query' => [
|
||||
'operation' => $body,
|
||||
]
|
||||
]);
|
||||
|
||||
$xml = $response->getContent();
|
||||
|
||||
return $this->responseParser->parseXmlString($xml);
|
||||
} catch (\Throwable $e) {
|
||||
}
|
||||
|
||||
$this->logger->error('API error', ['error' => $e->getMessage()]);
|
||||
throw new ApiClientException($e->getMessage());
|
||||
});
|
||||
}
|
||||
|
||||
private function createKey(string $username, string $password, string $type): string
|
||||
{
|
||||
$date = (new \DateTimeImmutable())->format('Ymd');
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\DataProvider;
|
||||
|
||||
use App\BusProNet\ApiClient;
|
||||
use App\BusProNet\ApiClientException;
|
||||
use Symfony\Contracts\Cache\CacheInterface;
|
||||
use Symfony\Contracts\Cache\ItemInterface;
|
||||
|
||||
class Countries
|
||||
{
|
||||
public function __construct(private readonly ApiClient $apiClient, private readonly CacheInterface $cache)
|
||||
{}
|
||||
|
||||
public function getAll(): array
|
||||
{
|
||||
try {
|
||||
$countries = $this->cache->get('bpn_countries', function (ItemInterface $item) {
|
||||
$item->expiresAfter(3600);
|
||||
|
||||
return $this
|
||||
->apiClient
|
||||
->getBaseData(ApiClient::TYPE_BASE_DATA_COUNTRIES)
|
||||
->getItems()
|
||||
;
|
||||
});
|
||||
} catch (ApiClientException $e) {
|
||||
$countries = [];
|
||||
}
|
||||
|
||||
return $countries;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\DataProvider;
|
||||
|
||||
use App\BusProNet\ApiClient;
|
||||
use App\BusProNet\ApiClientException;
|
||||
use Symfony\Contracts\Cache\CacheInterface;
|
||||
use Symfony\Contracts\Cache\ItemInterface;
|
||||
|
||||
class Pickups
|
||||
{
|
||||
public function __construct(private readonly ApiClient $apiClient, private readonly CacheInterface $cache)
|
||||
{}
|
||||
|
||||
public function getAll(): array
|
||||
{
|
||||
try {
|
||||
$pickups = $this->cache->get('bpn_pickups', function (ItemInterface $item) {
|
||||
$item->expiresAfter(3600);
|
||||
|
||||
return $this
|
||||
->apiClient
|
||||
->getBaseData(ApiClient::TYPE_BASE_DATA_PICKUPS)
|
||||
->getItems()
|
||||
;
|
||||
});
|
||||
} catch (ApiClientException $e) {
|
||||
$pickups = [];
|
||||
}
|
||||
|
||||
return $pickups;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\Model;
|
||||
|
||||
class BaseDataResponse
|
||||
{
|
||||
private array $items = [];
|
||||
|
||||
public function getItems(): array
|
||||
{
|
||||
return $this->items;
|
||||
}
|
||||
|
||||
public function setItems(array $items): static
|
||||
{
|
||||
$this->items = $items;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\Model;
|
||||
|
||||
class CountriesResponse extends BaseResponse
|
||||
{
|
||||
private array $countries = [];
|
||||
|
||||
public function getCountries(): array
|
||||
{
|
||||
return $this->countries;
|
||||
}
|
||||
|
||||
public function setCountries(array $countries): static
|
||||
{
|
||||
$this->countries = $countries;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace App\BusProNet\Model;
|
||||
|
||||
class CrmAttributesResponse extends BaseResponse
|
||||
class CrmAttributesResponse
|
||||
{
|
||||
private ?array $attributeGroups = null;
|
||||
private bool $admin = false;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace App\BusProNet\Model;
|
||||
|
||||
class BaseResponse
|
||||
class NotificationResponse
|
||||
{
|
||||
private ?int $code;
|
||||
private ?string $message;
|
||||
@@ -1,20 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\Model;
|
||||
|
||||
class PickupsResponse extends BaseResponse
|
||||
{
|
||||
private array $pickups = [];
|
||||
|
||||
public function getPickups(): array
|
||||
{
|
||||
return $this->pickups;
|
||||
}
|
||||
|
||||
public function setPickups(array $pickups): static
|
||||
{
|
||||
$this->pickups = $pickups;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace App\BusProNet\Model;
|
||||
|
||||
class ProfileResponse extends BaseResponse
|
||||
class ProfileResponse
|
||||
{
|
||||
private ?int $addressId = null;
|
||||
private ?int $personId = null;
|
||||
|
||||
@@ -3,16 +3,15 @@
|
||||
namespace App\BusProNet;
|
||||
|
||||
use App\BusProNet\Model\Address;
|
||||
use App\BusProNet\Model\BaseDataResponse;
|
||||
use App\BusProNet\Model\NotificationResponse;
|
||||
use App\BusProNet\Model\Communication;
|
||||
use App\BusProNet\Model\CountriesResponse;
|
||||
use App\BusProNet\Model\Country;
|
||||
use App\BusProNet\Model\CrmAttribute;
|
||||
use App\BusProNet\Model\CrmAttributesResponse;
|
||||
use App\BusProNet\Model\CrmAttributeGroup;
|
||||
use App\BusProNet\Model\CrmAttributesResponse;
|
||||
use App\BusProNet\Model\Pickup;
|
||||
use App\BusProNet\Model\PickupsResponse;
|
||||
use App\BusProNet\Model\ProfileResponse;
|
||||
use App\BusProNet\Model\BaseResponse;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class ResponseParser
|
||||
@@ -27,37 +26,46 @@ class ResponseParser
|
||||
/**
|
||||
* @throws ResponseParserException
|
||||
*/
|
||||
public function parseXmlString(string $content): BaseResponse
|
||||
public function parseXmlString(string $type, string $content): mixed
|
||||
{
|
||||
$xml = simplexml_load_string($content);
|
||||
$type = (string)$xml->xpath('satz/@typ')[0];
|
||||
|
||||
switch ($type) {
|
||||
case 'HINWEIS':
|
||||
return $this->createBaseResponse($xml);
|
||||
case 'KUNDENKONTO':
|
||||
// Override type when present in XML to catch error responses
|
||||
$responseType = $type;
|
||||
$responseTypeXml = $xml->xpath('satz/@typ');
|
||||
if (0 < count($responseTypeXml)) {
|
||||
$responseType = (string)$xml->xpath('satz/@typ')[0];
|
||||
}
|
||||
|
||||
switch ($responseType) {
|
||||
case ApiClient::TYPE_NOTIFICATION:
|
||||
return $this->createNotificationResponse($xml);
|
||||
case ApiClient::TYPE_CUSTOMER_DATA:
|
||||
$subType = (string) $xml->xpath('art')[0];
|
||||
switch ($subType) {
|
||||
case 'Adressdaten':
|
||||
case 'Adressdaten_Ändern':
|
||||
return $this->createProfileResponse($xml);
|
||||
case 'SelektionCRM':
|
||||
case 'SelektionCRM_Ändern':
|
||||
return $this->createCrmAttributesResponse($xml);
|
||||
}
|
||||
case 'STAMMLAENDER':
|
||||
break;
|
||||
case ApiClient::TYPE_BASE_DATA_COUNTRIES:
|
||||
return $this->createCountriesResponse($xml);
|
||||
case 'STAMMZUSTIEGE':
|
||||
case ApiClient::TYPE_BASE_DATA_PICKUPS:
|
||||
return $this->createPickupsResponse($xml);
|
||||
}
|
||||
|
||||
throw new ResponseParserException('Unable to parse XML response');
|
||||
}
|
||||
|
||||
public function createBaseResponse(\SimpleXMLElement $xml): BaseResponse
|
||||
public function createNotificationResponse(\SimpleXMLElement $xml): NotificationResponse
|
||||
{
|
||||
$code = (int) $xml->xpath('satz/nr')[0];
|
||||
$message = (string) $xml->xpath('satz/text')[0];
|
||||
|
||||
return new BaseResponse($code, $message);
|
||||
return new NotificationResponse($code, $message);
|
||||
}
|
||||
|
||||
public function createProfileResponse(\SimpleXMLElement $xml): ProfileResponse
|
||||
@@ -163,7 +171,7 @@ class ResponseParser
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function createCountriesResponse(\SimpleXMLElement $xml): CountriesResponse
|
||||
public function createCountriesResponse(\SimpleXMLElement $xml): BaseDataResponse
|
||||
{
|
||||
$countries = [];
|
||||
|
||||
@@ -178,17 +186,17 @@ class ResponseParser
|
||||
$countries[] = $country;
|
||||
}
|
||||
|
||||
$response = new CountriesResponse();
|
||||
$response->setCountries($countries);
|
||||
$response = new BaseDataResponse();
|
||||
$response->setItems($countries);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function createPickupsResponse(\SimpleXMLElement $xml): PickupsResponse
|
||||
public function createPickupsResponse(\SimpleXMLElement $xml): BaseDataResponse
|
||||
{
|
||||
$pickups = [];
|
||||
|
||||
foreach ($xml->xpath('zustiege/zustieg') as $item) {
|
||||
foreach ($xml->xpath('zustieg') as $item) {
|
||||
$pickup = new Pickup();
|
||||
$pickup
|
||||
->setId((int)$item->attributes()['id'])
|
||||
@@ -200,8 +208,8 @@ class ResponseParser
|
||||
$pickups[] = $pickup;
|
||||
}
|
||||
|
||||
$response = new PickupsResponse();
|
||||
$response->setPickups($pickups);
|
||||
$response = new BaseDataResponse();
|
||||
$response->setItems($pickups);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
@@ -46,9 +46,6 @@ class Assignment implements BlameableEntityInterface, TimestampableEntityInterfa
|
||||
#[ORM\ManyToOne]
|
||||
private ?User $owner = null;
|
||||
|
||||
#[ORM\ManyToMany(targetEntity: Pickup::class)]
|
||||
private Collection $pickups;
|
||||
|
||||
#[ORM\ManyToMany(targetEntity: Fee::class)]
|
||||
private Collection $fees;
|
||||
|
||||
@@ -64,7 +61,6 @@ class Assignment implements BlameableEntityInterface, TimestampableEntityInterfa
|
||||
public function __construct()
|
||||
{
|
||||
$this->uuid = Uuid::v4();
|
||||
$this->pickups = new ArrayCollection();
|
||||
$this->fees = new ArrayCollection();
|
||||
$this->applications = new ArrayCollection();
|
||||
$this->dispositions = new ArrayCollection();
|
||||
@@ -165,30 +161,6 @@ class Assignment implements BlameableEntityInterface, TimestampableEntityInterfa
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, Pickup>
|
||||
*/
|
||||
public function getPickups(): Collection
|
||||
{
|
||||
return $this->pickups;
|
||||
}
|
||||
|
||||
public function addPickup(Pickup $pickup): static
|
||||
{
|
||||
if (!$this->pickups->contains($pickup)) {
|
||||
$this->pickups->add($pickup);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removePickup(Pickup $pickup): static
|
||||
{
|
||||
$this->pickups->removeElement($pickup);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, Fee>
|
||||
*/
|
||||
|
||||
@@ -17,9 +17,6 @@ class DispositionRequirement
|
||||
#[ORM\ManyToOne]
|
||||
private ?Training $training = null;
|
||||
|
||||
#[ORM\ManyToOne]
|
||||
private ?Pickup $pickup = null;
|
||||
|
||||
#[ORM\Column(type: Types::DATE_IMMUTABLE, nullable: true)]
|
||||
private ?\DateTimeImmutable $pickupDate = null;
|
||||
|
||||
@@ -43,18 +40,6 @@ class DispositionRequirement
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPickup(): ?Pickup
|
||||
{
|
||||
return $this->pickup;
|
||||
}
|
||||
|
||||
public function setPickup(?Pickup $pickup): static
|
||||
{
|
||||
$this->pickup = $pickup;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPickupDate(): ?\DateTimeImmutable
|
||||
{
|
||||
return $this->pickupDate;
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Repository\PickupRepository;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: PickupRepository::class)]
|
||||
class Pickup
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column]
|
||||
private ?int $id = null;
|
||||
|
||||
#[ORM\Column(length: 255)]
|
||||
private ?string $name = null;
|
||||
|
||||
#[ORM\Column]
|
||||
private ?int $busProId = null;
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getName(): ?string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName(string $name): static
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getBusProId(): ?int
|
||||
{
|
||||
return $this->busProId;
|
||||
}
|
||||
|
||||
public function setBusProId(int $busProId): static
|
||||
{
|
||||
$this->busProId = $busProId;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -114,6 +114,16 @@ class Teamer implements TimestampableEntityInterface
|
||||
#[ORM\OneToOne(mappedBy: 'teamer')]
|
||||
private ?User $user = null;
|
||||
|
||||
#[ORM\Column]
|
||||
private array $pickups = [];
|
||||
|
||||
#[ORM\Column(length: 255)]
|
||||
#[Assert\NotBlank(message: 'Bitte gib deine Sprache(n) an', groups: ['profile', 'profile_preflight'])]
|
||||
private ?string $language = null;
|
||||
|
||||
#[ORM\Column(length: 2)]
|
||||
private ?string $size = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->uuid = Uuid::v4();
|
||||
@@ -615,4 +625,40 @@ class Teamer implements TimestampableEntityInterface
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPickups(): array
|
||||
{
|
||||
return $this->pickups;
|
||||
}
|
||||
|
||||
public function setPickups(array $pickups): static
|
||||
{
|
||||
$this->pickups = $pickups;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getLanguage(): ?string
|
||||
{
|
||||
return $this->language;
|
||||
}
|
||||
|
||||
public function setLanguage(?string $language): static
|
||||
{
|
||||
$this->language = $language;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSize(): ?string
|
||||
{
|
||||
return $this->size;
|
||||
}
|
||||
|
||||
public function setSize(string $size): static
|
||||
{
|
||||
$this->size = $size;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use App\BusProNet\ApiClient;
|
||||
use App\BusProNet\DataProvider\Countries;
|
||||
use App\Form\ChoiceLoader\BpnCountryChoiceLoader;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\ChoiceList\ChoiceList;
|
||||
@@ -12,7 +12,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class BpnCountryType extends AbstractType
|
||||
{
|
||||
public function __construct(private readonly ApiClient $apiClient)
|
||||
public function __construct(private readonly Countries $countries)
|
||||
{}
|
||||
|
||||
public function getParent(): string
|
||||
@@ -29,7 +29,7 @@ class BpnCountryType extends AbstractType
|
||||
'choice_loader' => function (Options $options) {
|
||||
return ChoiceList::loader(
|
||||
$this,
|
||||
new BpnCountryChoiceLoader($this->apiClient, $options['property']),
|
||||
new BpnCountryChoiceLoader($this->countries, $options['property']),
|
||||
[$options['property']]
|
||||
);
|
||||
},
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use App\BusProNet\DataProvider\Pickups;
|
||||
use App\Form\ChoiceLoader\BpnPickupsChoiceLoader;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class BpnPickupType extends AbstractType
|
||||
{
|
||||
public function __construct(private readonly Pickups $pickups)
|
||||
{}
|
||||
|
||||
public function getParent(): string
|
||||
{
|
||||
return ChoiceType::class;
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'choice_loader' => new BpnPickupsChoiceLoader($this->pickups),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -2,29 +2,22 @@
|
||||
|
||||
namespace App\Form\ChoiceLoader;
|
||||
|
||||
use App\BusProNet\ApiClient;
|
||||
use App\BusProNet\ApiClientException;
|
||||
use App\BusProNet\Model\CountriesResponse;
|
||||
use App\BusProNet\DataProvider\Countries;
|
||||
use App\BusProNet\Model\Country;
|
||||
use Symfony\Component\Form\ChoiceList\ArrayChoiceList;
|
||||
use Symfony\Component\Form\ChoiceList\ChoiceListInterface;
|
||||
use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface;
|
||||
|
||||
class BpnCountryChoiceLoader implements ChoiceLoaderInterface
|
||||
{
|
||||
public function __construct(private readonly ApiClient $apiClient, private readonly string $property)
|
||||
public function __construct(private readonly Countries $countries, private readonly string $property)
|
||||
{}
|
||||
|
||||
public function loadChoiceList(callable $value = null): ChoiceListInterface
|
||||
{
|
||||
try {
|
||||
/** @var CountriesResponse $response */
|
||||
$response = $this->apiClient->getCountries();
|
||||
$countries = $response->getCountries();
|
||||
} catch (ApiClientException $e) {
|
||||
$countries = [];
|
||||
}
|
||||
|
||||
$choices = [];
|
||||
/** @var Country[] $countries */
|
||||
$countries = $this->countries->getAll();
|
||||
|
||||
foreach ($countries as $country) {
|
||||
$key = 'nationality' === $this->property ? $country->getNationality() : $country->getName();
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Form\ChoiceLoader;
|
||||
|
||||
use App\BusProNet\DataProvider\Pickups;
|
||||
use App\BusProNet\Model\Pickup;
|
||||
use Symfony\Component\Form\ChoiceList\ArrayChoiceList;
|
||||
use Symfony\Component\Form\ChoiceList\ChoiceListInterface;
|
||||
use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface;
|
||||
|
||||
class BpnPickupsChoiceLoader implements ChoiceLoaderInterface
|
||||
{
|
||||
public function __construct(private readonly Pickups $pickups)
|
||||
{}
|
||||
|
||||
public function loadChoiceList(callable $value = null): ChoiceListInterface
|
||||
{
|
||||
$choices = [];
|
||||
/** @var Pickup[] $pickups */
|
||||
$pickups = $this->pickups->getAll();
|
||||
|
||||
foreach ($pickups as $pickup) {
|
||||
$choices[$pickup->getCity()] = $pickup->getBusProId();
|
||||
}
|
||||
|
||||
ksort($choices);
|
||||
|
||||
return new ArrayChoiceList($choices);
|
||||
|
||||
}
|
||||
|
||||
public function loadChoicesForValues(array $values, callable $value = null): array
|
||||
{
|
||||
return $values;
|
||||
}
|
||||
|
||||
public function loadValuesForChoices(array $choices, callable $value = null): array
|
||||
{
|
||||
return $choices;
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ use App\Service\Upload\UploadHandler;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\BirthdayType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
@@ -79,6 +80,32 @@ class TeamerProfileType extends AbstractType
|
||||
'label' => false,
|
||||
'error_bubbling' => false,
|
||||
])
|
||||
->add('pickups', CollectionType::class, [
|
||||
'label' => 'Zustiege',
|
||||
'entry_type' => BpnPickupType::class,
|
||||
'allow_add' => true,
|
||||
'allow_delete' => true,
|
||||
])
|
||||
->add('language', TextType::class, [
|
||||
'label' => 'Sprache(n)',
|
||||
])
|
||||
->add('size', ChoiceType::class, [
|
||||
'label' => 'Klamottengröße',
|
||||
'choices' => [
|
||||
'S' => 'S',
|
||||
'M' => 'M',
|
||||
'L' => 'L',
|
||||
'XL' => 'XL',
|
||||
'XXL' => 'XXL',
|
||||
],
|
||||
])
|
||||
->add('status', ChoiceType::class, [
|
||||
'label' => 'Status',
|
||||
'choices' => [
|
||||
'Neuteamer' => Teamer::STATUS_NEW,
|
||||
'Bestandsteamer' => Teamer::STATUS_EXISTING,
|
||||
],
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user