feat: integrated OAuth2 server
This commit is contained in:
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\BusProNet;
|
||||
|
||||
use App\BusProNet\XmlParser\ApiResponseParser;
|
||||
use App\BusProNet\DataProcessor\BookingDataProcessor;
|
||||
use App\BusProNet\Exception\ApiClientException;
|
||||
use App\BusProNet\Exception\ResponseParserException;
|
||||
@@ -12,6 +11,8 @@ use App\BusProNet\Model\BookingUpdate;
|
||||
use App\BusProNet\Model\CrmAttributes;
|
||||
use App\BusProNet\Model\Notification;
|
||||
use App\BusProNet\Model\PersonalData;
|
||||
use App\BusProNet\Traits\ApiClientTrait;
|
||||
use App\BusProNet\XmlParser\ApiResponseParser;
|
||||
use App\Form\Model\BookingData;
|
||||
use App\Form\Model\RegistrationData;
|
||||
use League\Flysystem\FilesystemException;
|
||||
@@ -39,7 +40,7 @@ class ApiClient
|
||||
private readonly ApiResponseParser $responseParser,
|
||||
private readonly FilesystemOperator $xmlDump,
|
||||
private readonly LoggerInterface $logger,
|
||||
array $options
|
||||
array $options,
|
||||
) {
|
||||
$this->config = $this->resolveOptions($options);
|
||||
}
|
||||
@@ -107,7 +108,7 @@ class ApiClient
|
||||
string $email,
|
||||
string $password,
|
||||
PersonalData $personalData,
|
||||
bool $debug = false
|
||||
bool $debug = false,
|
||||
): Notification|PersonalData {
|
||||
$data = [
|
||||
'user' => $this->config['bpn_username'],
|
||||
@@ -333,7 +334,7 @@ class ApiClient
|
||||
private function dumpXmlToFile(string $type, string $requestId, string $body): void
|
||||
{
|
||||
try {
|
||||
$this->xmlDump->write($requestId . '_' . $type . '.xml', $body);
|
||||
$this->xmlDump->write($requestId.'_'.$type.'.xml', $body);
|
||||
} catch (FilesystemException $e) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
namespace App\BusProNet\DataProvider;
|
||||
|
||||
use App\BusProNet\ApiClient;
|
||||
use App\BusProNet\Exception\ApiClientException;
|
||||
use App\BusProNet\Model\Country;
|
||||
use Psr\Cache\InvalidArgumentException;
|
||||
use Symfony\Contracts\Cache\CacheInterface;
|
||||
@@ -12,7 +11,8 @@ use Symfony\Contracts\Cache\ItemInterface;
|
||||
class CountryDataProvider
|
||||
{
|
||||
public function __construct(private readonly ApiClient $apiClient, private readonly CacheInterface $cache)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
public function getAll(): array
|
||||
{
|
||||
@@ -39,4 +39,4 @@ class CountryDataProvider
|
||||
|
||||
return $this->getAll()[$token] ?? null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,4 +4,4 @@ namespace App\BusProNet\Exception;
|
||||
|
||||
class ResponseParserException extends \Exception
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,9 +11,10 @@ use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface;
|
||||
class CountryChoiceLoader implements ChoiceLoaderInterface
|
||||
{
|
||||
public function __construct(private readonly CountryDataProvider $countries, private readonly string $property)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
public function loadChoiceList(callable $value = null): ChoiceListInterface
|
||||
public function loadChoiceList(?callable $value = null): ChoiceListInterface
|
||||
{
|
||||
$choices = [];
|
||||
/** @var Country[] $countries */
|
||||
@@ -25,16 +26,15 @@ class CountryChoiceLoader implements ChoiceLoaderInterface
|
||||
}
|
||||
|
||||
return new ArrayChoiceList($choices);
|
||||
|
||||
}
|
||||
|
||||
public function loadChoicesForValues(array $values, callable $value = null): array
|
||||
public function loadChoicesForValues(array $values, ?callable $value = null): array
|
||||
{
|
||||
return $values;
|
||||
}
|
||||
|
||||
public function loadValuesForChoices(array $choices, callable $value = null): array
|
||||
public function loadValuesForChoices(array $choices, ?callable $value = null): array
|
||||
{
|
||||
return $choices;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,8 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
class CountryType extends AbstractType
|
||||
{
|
||||
public function __construct(private readonly CountryDataProvider $countries)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
public function getParent(): string
|
||||
{
|
||||
@@ -35,4 +36,4 @@ class CountryType extends AbstractType
|
||||
},
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,4 +16,4 @@ class Availability implements \JsonSerializable
|
||||
'available' => $this->available,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,8 @@ namespace App\BusProNet\Model;
|
||||
class BaseData
|
||||
{
|
||||
public function __construct(private readonly array $items)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
public function getItems(): array
|
||||
{
|
||||
@@ -16,4 +17,4 @@ class BaseData
|
||||
{
|
||||
return $this->items[$key] ?? null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,4 +8,4 @@ class Country
|
||||
public ?string $name = null;
|
||||
public ?string $token = null;
|
||||
public ?string $nationality = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,4 +12,4 @@ class CrmAttributes
|
||||
public bool $teamer = false;
|
||||
public ?string $hotelCode = null;
|
||||
public array $roles = [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,4 +17,4 @@ class CrmSelection
|
||||
|
||||
#[Groups(['api:single'])]
|
||||
public bool $selected = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,8 @@ class CrmSelectionGroup
|
||||
{
|
||||
/**
|
||||
* Maps BusPro IDs of CRM selection groups representing
|
||||
* included services
|
||||
* included services.
|
||||
*
|
||||
* @var array|string[]
|
||||
*/
|
||||
public static array $includedServicesMapping = [
|
||||
|
||||
@@ -100,4 +100,4 @@ class Error
|
||||
985 => 'Zustieg mit ID #1# nicht fürs Internet buchbar',
|
||||
999 => 'Systemfehler: #1#',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,4 +14,4 @@ class File
|
||||
public ?string $filename = null;
|
||||
public ?string $content = null;
|
||||
public ?string $mimeType = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,4 +6,4 @@ class Guide
|
||||
{
|
||||
public ?string $name = null;
|
||||
public ?string $phone = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,4 +26,4 @@ class Hotel
|
||||
|
||||
#[Groups(['api:list', 'api:single'])]
|
||||
public ?string $country = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,4 +21,4 @@ class MutableData
|
||||
public ?string $category = null;
|
||||
public bool $mutable = false;
|
||||
public ?\DateTimeImmutable $mutableBefore = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,4 +64,36 @@ class PersonalData
|
||||
'bemerkung' => $this->remarks,
|
||||
];
|
||||
}
|
||||
|
||||
public function getClaims(): array
|
||||
{
|
||||
return [
|
||||
'email' => $this->communication->email,
|
||||
'profile' => [
|
||||
'first_name' => $this->firstName,
|
||||
'last_name' => $this->name,
|
||||
'title' => $this->title,
|
||||
'salutation' => $this->salutation,
|
||||
'gender' => $this->gender,
|
||||
'nationality' => $this->nationality,
|
||||
'address' => [
|
||||
'street' => $this->address->street,
|
||||
'postcode' => $this->address->postCode,
|
||||
'city' => $this->address->city,
|
||||
'disctrict' => $this->address->district,
|
||||
'country' => $this->address->country,
|
||||
],
|
||||
'communication' => [
|
||||
'email' => $this->communication->email,
|
||||
'mobile' => $this->communication->mobile,
|
||||
'phone' => $this->communication->phone,
|
||||
'newsletter' => $this->communication->newsletter,
|
||||
],
|
||||
'height' => $this->height,
|
||||
'weight' => $this->weight,
|
||||
'shoe_size' => $this->shoeSize,
|
||||
'remarks' => $this->remarks,
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,4 +32,4 @@ class Pickup
|
||||
|
||||
#[Groups(['api:booking'])]
|
||||
public array $mapping = [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,4 +63,4 @@ class Room
|
||||
|
||||
#[Groups(['booking'])]
|
||||
public array $individualPrice = [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ class Service
|
||||
public ?string $category = null;
|
||||
|
||||
#[Groups(['api:single', 'api:list'])]
|
||||
public ?string $status = null;
|
||||
public ?string $status = null;
|
||||
|
||||
#[Groups(['api:single', 'api:list'])]
|
||||
public bool $mandatory = false;
|
||||
|
||||
@@ -8,4 +8,4 @@ class Surcharge
|
||||
public array $mapping = [];
|
||||
public ?float $totalPrice = null;
|
||||
public array $individualPrice = [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet;
|
||||
namespace App\BusProNet\Traits;
|
||||
|
||||
use App\BusProNet\Exception\ApiClientException;
|
||||
|
||||
@@ -56,7 +56,7 @@ trait ApiClientTrait
|
||||
private function send($socket, string $data): void
|
||||
{
|
||||
// message length is prepended to actual message
|
||||
$send = sprintf('%010s', strlen($data)) . $data;
|
||||
$send = sprintf('%010s', strlen($data)).$data;
|
||||
fwrite($socket, $send);
|
||||
}
|
||||
|
||||
@@ -75,4 +75,4 @@ trait ApiClientTrait
|
||||
{
|
||||
@fclose($socket);
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet;
|
||||
namespace App\BusProNet\Traits;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Carbon\Exceptions\InvalidFormatException;
|
||||
@@ -52,6 +52,7 @@ trait TypeConversionTrait
|
||||
|
||||
try {
|
||||
$date = Carbon::createFromFormat('d.m.Y', $string)->startOfDay();
|
||||
|
||||
return $date->toDateTimeImmutable();
|
||||
} catch (InvalidFormatException $e) {
|
||||
return null;
|
||||
@@ -66,6 +67,7 @@ trait TypeConversionTrait
|
||||
|
||||
try {
|
||||
$dateTime = Carbon::createFromFormat('d.m.Y H:i', substr($string, 0, 16))->startOfDay();
|
||||
|
||||
return $dateTime->toDateTimeImmutable();
|
||||
} catch (InvalidFormatException $e) {
|
||||
return null;
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet;
|
||||
namespace App\BusProNet\Traits;
|
||||
|
||||
use Symfony\Component\DomCrawler\Crawler;
|
||||
|
||||
@@ -15,4 +15,4 @@ trait XmlParserTrait
|
||||
{
|
||||
return 0 < $node->count() ? (int) $node->text() : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
namespace App\BusProNet\XmlLoader;
|
||||
|
||||
use App\BusProNet\TypeConversionTrait;
|
||||
use App\BusProNet\XmlParserTrait;
|
||||
use App\BusProNet\Traits\TypeConversionTrait;
|
||||
use App\BusProNet\Traits\XmlParserTrait;
|
||||
use League\Flysystem\FilesystemOperator;
|
||||
use Symfony\Contracts\Cache\CacheInterface;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ class TravelLoader extends AbstractLoader
|
||||
private readonly HotelLoader $hotelDataLoader,
|
||||
CacheInterface $cache,
|
||||
private readonly string $travelInfoBaseUrl,
|
||||
FileSystemOperator $xmlExport,
|
||||
FilesystemOperator $xmlExport,
|
||||
) {
|
||||
parent::__construct($cache, $xmlExport);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace App\BusProNet\XmlParser;
|
||||
|
||||
use App\BusProNet\TypeConversionTrait;
|
||||
use App\BusProNet\Traits\TypeConversionTrait;
|
||||
use Symfony\Component\DomCrawler\Crawler;
|
||||
|
||||
abstract class AbstractParser
|
||||
@@ -47,4 +47,4 @@ abstract class AbstractParser
|
||||
|
||||
return $this->stringToArray($node->text(), $separator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,4 +61,4 @@ class ApiResponseParser extends AbstractParser
|
||||
|
||||
throw new ResponseParserException('Unable to parse XML response');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,4 +27,4 @@ class AvailabilitiesParser extends AbstractParser
|
||||
|
||||
return new BaseData($availabilities);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,4 +38,4 @@ class BookingsParser extends AbstractParser
|
||||
|
||||
return new BaseData($bookings);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,4 +27,4 @@ class CountriesParser
|
||||
|
||||
return new BaseData($countries);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ use App\BusProNet\Model\CrmAction;
|
||||
use App\BusProNet\Model\CrmAttributes;
|
||||
use App\BusProNet\Model\CrmSelection;
|
||||
use App\BusProNet\Model\CrmSelectionGroup;
|
||||
use App\BusProNet\TypeConversionTrait;
|
||||
use App\BusProNet\Traits\TypeConversionTrait;
|
||||
use Symfony\Component\DomCrawler\Crawler;
|
||||
|
||||
class CrmAttributesResponseParser
|
||||
|
||||
@@ -37,8 +37,7 @@ class DocumentsParser
|
||||
});
|
||||
|
||||
return new File('reisedokumente.zip', $zip->outputAsString(), 'application/zip');
|
||||
}
|
||||
catch (ZipException $e) {
|
||||
} catch (ZipException $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -57,4 +56,4 @@ class DocumentsParser
|
||||
|
||||
return [$filename, $pdfData];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,4 +39,4 @@ class MutableDataParser extends AbstractParser
|
||||
|
||||
return new BaseData($mutableFields);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,4 +14,4 @@ class NotificationParser extends AbstractParser
|
||||
|
||||
return new Notification($number, $text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,8 +36,8 @@ class PersonalDataParser extends AbstractParser
|
||||
$address = new Address();
|
||||
$address->street = $this->getStringOrNullValue($addressNode->filterXPath('//strasse'));
|
||||
$address->postCode = $this->getStringOrNullValue($addressNode->filterXPath('//plz'));
|
||||
$address->city = $this->getStringOrNullValue($addressNode->filterXPath('//ort')) ;
|
||||
$address->country = $this->getStringOrNullValue($addressNode->filterXPath('//land')) ;
|
||||
$address->city = $this->getStringOrNullValue($addressNode->filterXPath('//ort'));
|
||||
$address->country = $this->getStringOrNullValue($addressNode->filterXPath('//land'));
|
||||
|
||||
$personalData->address = $address;
|
||||
}
|
||||
@@ -63,4 +63,4 @@ class PersonalDataParser extends AbstractParser
|
||||
|
||||
return $personalData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,4 +33,4 @@ class PickupsParser extends AbstractParser
|
||||
|
||||
return $pickups;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ class RoomsParser extends AbstractParser
|
||||
|
||||
$result->each(function (Crawler $node) use (&$rooms) {
|
||||
$room = new Room();
|
||||
$room->id = (int) $node->attr('idzimmer');;
|
||||
$room->id = (int) $node->attr('idzimmer');
|
||||
$room->label = $node->attr('zimmer');
|
||||
$room->category = $node->attr('kategorie');
|
||||
$room->boardId = (int) $node->attr('idverpflegung');
|
||||
@@ -38,4 +38,4 @@ class RoomsParser extends AbstractParser
|
||||
|
||||
return $rooms;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,4 +39,4 @@ class ServicesParser extends AbstractParser
|
||||
|
||||
return $services;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,4 +30,4 @@ class SurchargesParser extends AbstractParser
|
||||
|
||||
return $surcharges;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user