WIP: Extend and improve profile editing

This commit is contained in:
Björn Fromme
2023-10-01 16:39:32 +02:00
parent 6595fbec8a
commit d776d37cd5
27 changed files with 553 additions and 375 deletions
+68 -156
View File
@@ -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');
+33
View File
@@ -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;
}
}
+34
View File
@@ -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;
}
}
+20
View File
@@ -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;
}
}
-20
View File
@@ -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;
-20
View File
@@ -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;
}
}
+1 -1
View File
@@ -2,7 +2,7 @@
namespace App\BusProNet\Model;
class ProfileResponse extends BaseResponse
class ProfileResponse
{
private ?int $addressId = null;
private ?int $personId = null;
+29 -21
View File
@@ -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;
}