diff --git a/.env b/.env index 8af0520..9aada85 100644 --- a/.env +++ b/.env @@ -49,3 +49,8 @@ APP_BPN_DEBUG=false APP_TRAVEL_INFO_BASE_URL=https://www.ep-reisen.de/reiseinformationen/ API_KEYS= + +SFTP_XML_EXPORT_HOST= +SFTP_XML_EXPORT_PORT= +SFTP_XML_EXPORT_USER= +SFTP_XML_EXPORT_PASSWORD= diff --git a/composer.json b/composer.json index 1a02cba..99fd2da 100644 --- a/composer.json +++ b/composer.json @@ -14,6 +14,8 @@ "doctrine/doctrine-migrations-bundle": "^3.3", "doctrine/orm": "^3.3", "knplabs/knp-menu-bundle": "^3.4", + "league/flysystem-bundle": "^3.4", + "league/flysystem-sftp-v3": "^3.29", "nelexa/zip": "^4.0", "nesbot/carbon": "^3.8", "phpdocumentor/reflection-docblock": "^5.6", diff --git a/composer.lock b/composer.lock index 9417cc3..ba943e2 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b7889b1556dde930fda7eb3acf8e7532", + "content-hash": "75a72111cb05768e7e978a7161b2e0e5", "packages": [ { "name": "carbonphp/carbon-doctrine-types", @@ -1494,6 +1494,313 @@ }, "time": "2024-12-25T16:34:19+00:00" }, + { + "name": "league/flysystem", + "version": "3.29.1", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem.git", + "reference": "edc1bb7c86fab0776c3287dbd19b5fa278347319" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/edc1bb7c86fab0776c3287dbd19b5fa278347319", + "reference": "edc1bb7c86fab0776c3287dbd19b5fa278347319", + "shasum": "" + }, + "require": { + "league/flysystem-local": "^3.0.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" + }, + "conflict": { + "async-aws/core": "<1.19.0", + "async-aws/s3": "<1.14.0", + "aws/aws-sdk-php": "3.209.31 || 3.210.0", + "guzzlehttp/guzzle": "<7.0", + "guzzlehttp/ringphp": "<1.1.1", + "phpseclib/phpseclib": "3.0.15", + "symfony/http-client": "<5.2" + }, + "require-dev": { + "async-aws/s3": "^1.5 || ^2.0", + "async-aws/simple-s3": "^1.1 || ^2.0", + "aws/aws-sdk-php": "^3.295.10", + "composer/semver": "^3.0", + "ext-fileinfo": "*", + "ext-ftp": "*", + "ext-mongodb": "^1.3", + "ext-zip": "*", + "friendsofphp/php-cs-fixer": "^3.5", + "google/cloud-storage": "^1.23", + "guzzlehttp/psr7": "^2.6", + "microsoft/azure-storage-blob": "^1.1", + "mongodb/mongodb": "^1.2", + "phpseclib/phpseclib": "^3.0.36", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.5.11|^10.0", + "sabre/dav": "^4.6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "File storage abstraction for PHP", + "keywords": [ + "WebDAV", + "aws", + "cloud", + "file", + "files", + "filesystem", + "filesystems", + "ftp", + "s3", + "sftp", + "storage" + ], + "support": { + "issues": "https://github.com/thephpleague/flysystem/issues", + "source": "https://github.com/thephpleague/flysystem/tree/3.29.1" + }, + "time": "2024-10-08T08:58:34+00:00" + }, + { + "name": "league/flysystem-bundle", + "version": "3.4.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem-bundle.git", + "reference": "6493f7f2ab49bc5817e4b064b9b971d93faabc12" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem-bundle/zipball/6493f7f2ab49bc5817e4b064b9b971d93faabc12", + "reference": "6493f7f2ab49bc5817e4b064b9b971d93faabc12", + "shasum": "" + }, + "require": { + "league/flysystem": "^3.0", + "php": ">=8.0", + "symfony/config": "^5.4 || ^6.0 || ^7.0", + "symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0", + "symfony/deprecation-contracts": "^2.1 || ^3", + "symfony/http-kernel": "^5.4 || ^6.0 || ^7.0", + "symfony/options-resolver": "^5.4 || ^6.0 || ^7.0" + }, + "require-dev": { + "doctrine/mongodb-odm": "^2.0", + "league/flysystem-async-aws-s3": "^3.1", + "league/flysystem-aws-s3-v3": "^3.1", + "league/flysystem-azure-blob-storage": "^3.1", + "league/flysystem-ftp": "^3.1", + "league/flysystem-google-cloud-storage": "^3.1", + "league/flysystem-gridfs": "^3.28", + "league/flysystem-memory": "^3.1", + "league/flysystem-read-only": "^3.15", + "league/flysystem-sftp-v3": "^3.1", + "league/flysystem-webdav": "^3.29", + "symfony/dotenv": "^5.4 || ^6.0 || ^7.0", + "symfony/framework-bundle": "^5.4 || ^6.0 || ^7.0", + "symfony/phpunit-bridge": "^5.4 || ^6.0 || ^7.0", + "symfony/var-dumper": "^5.4 || ^6.0 || ^7.0", + "symfony/yaml": "^5.4 || ^6.0 || ^7.0" + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "League\\FlysystemBundle\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Titouan Galopin", + "email": "galopintitouan@gmail.com" + } + ], + "description": "Symfony bundle integrating Flysystem into Symfony applications", + "keywords": [ + "Flysystem", + "bundle", + "filesystem", + "symfony" + ], + "support": { + "issues": "https://github.com/thephpleague/flysystem-bundle/issues", + "source": "https://github.com/thephpleague/flysystem-bundle/tree/3.4.0" + }, + "time": "2025-01-23T18:07:31+00:00" + }, + { + "name": "league/flysystem-local", + "version": "3.29.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem-local.git", + "reference": "e0e8d52ce4b2ed154148453d321e97c8e931bd27" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/e0e8d52ce4b2ed154148453d321e97c8e931bd27", + "reference": "e0e8d52ce4b2ed154148453d321e97c8e931bd27", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "league/flysystem": "^3.0.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\Local\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "Local filesystem adapter for Flysystem.", + "keywords": [ + "Flysystem", + "file", + "files", + "filesystem", + "local" + ], + "support": { + "source": "https://github.com/thephpleague/flysystem-local/tree/3.29.0" + }, + "time": "2024-08-09T21:24:39+00:00" + }, + { + "name": "league/flysystem-sftp-v3", + "version": "3.29.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem-sftp-v3.git", + "reference": "ce9b209e2fbe33122c755ffc18eb4d5bd256f252" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem-sftp-v3/zipball/ce9b209e2fbe33122c755ffc18eb4d5bd256f252", + "reference": "ce9b209e2fbe33122c755ffc18eb4d5bd256f252", + "shasum": "" + }, + "require": { + "league/flysystem": "^3.0.14", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2", + "phpseclib/phpseclib": "^3.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\PhpseclibV3\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "SFTP filesystem adapter for Flysystem.", + "keywords": [ + "Flysystem", + "file", + "files", + "filesystem", + "sftp" + ], + "support": { + "source": "https://github.com/thephpleague/flysystem-sftp-v3/tree/3.29.0" + }, + "time": "2024-08-14T19:35:54+00:00" + }, + { + "name": "league/mime-type-detection", + "version": "1.16.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/mime-type-detection.git", + "reference": "2d6702ff215bf922936ccc1ad31007edc76451b9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/2d6702ff215bf922936ccc1ad31007edc76451b9", + "reference": "2d6702ff215bf922936ccc1ad31007edc76451b9", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.2", + "phpstan/phpstan": "^0.12.68", + "phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\MimeTypeDetection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "Mime-type detection for Flysystem", + "support": { + "issues": "https://github.com/thephpleague/mime-type-detection/issues", + "source": "https://github.com/thephpleague/mime-type-detection/tree/1.16.0" + }, + "funding": [ + { + "url": "https://github.com/frankdejonge", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/league/flysystem", + "type": "tidelift" + } + ], + "time": "2024-09-21T08:32:55+00:00" + }, { "name": "masterminds/html5", "version": "2.9.0", @@ -1843,6 +2150,123 @@ ], "time": "2025-02-20T17:33:38+00:00" }, + { + "name": "paragonie/constant_time_encoding", + "version": "v3.0.0", + "source": { + "type": "git", + "url": "https://github.com/paragonie/constant_time_encoding.git", + "reference": "df1e7fde177501eee2037dd159cf04f5f301a512" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/df1e7fde177501eee2037dd159cf04f5f301a512", + "reference": "df1e7fde177501eee2037dd159cf04f5f301a512", + "shasum": "" + }, + "require": { + "php": "^8" + }, + "require-dev": { + "phpunit/phpunit": "^9", + "vimeo/psalm": "^4|^5" + }, + "type": "library", + "autoload": { + "psr-4": { + "ParagonIE\\ConstantTime\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com", + "role": "Maintainer" + }, + { + "name": "Steve 'Sc00bz' Thomas", + "email": "steve@tobtu.com", + "homepage": "https://www.tobtu.com", + "role": "Original Developer" + } + ], + "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)", + "keywords": [ + "base16", + "base32", + "base32_decode", + "base32_encode", + "base64", + "base64_decode", + "base64_encode", + "bin2hex", + "encoding", + "hex", + "hex2bin", + "rfc4648" + ], + "support": { + "email": "info@paragonie.com", + "issues": "https://github.com/paragonie/constant_time_encoding/issues", + "source": "https://github.com/paragonie/constant_time_encoding" + }, + "time": "2024-05-08T12:36:18+00:00" + }, + { + "name": "paragonie/random_compat", + "version": "v9.99.100", + "source": { + "type": "git", + "url": "https://github.com/paragonie/random_compat.git", + "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/996434e5492cb4c3edcb9168db6fbb1359ef965a", + "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a", + "shasum": "" + }, + "require": { + "php": ">= 7" + }, + "require-dev": { + "phpunit/phpunit": "4.*|5.*", + "vimeo/psalm": "^1" + }, + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "keywords": [ + "csprng", + "polyfill", + "pseudorandom", + "random" + ], + "support": { + "email": "info@paragonie.com", + "issues": "https://github.com/paragonie/random_compat/issues", + "source": "https://github.com/paragonie/random_compat" + }, + "time": "2020-10-15T08:29:30+00:00" + }, { "name": "phpdocumentor/reflection-common", "version": "2.2.0", @@ -2018,6 +2442,116 @@ }, "time": "2024-11-09T15:12:26+00:00" }, + { + "name": "phpseclib/phpseclib", + "version": "3.0.43", + "source": { + "type": "git", + "url": "https://github.com/phpseclib/phpseclib.git", + "reference": "709ec107af3cb2f385b9617be72af8cf62441d02" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/709ec107af3cb2f385b9617be72af8cf62441d02", + "reference": "709ec107af3cb2f385b9617be72af8cf62441d02", + "shasum": "" + }, + "require": { + "paragonie/constant_time_encoding": "^1|^2|^3", + "paragonie/random_compat": "^1.4|^2.0|^9.99.99", + "php": ">=5.6.1" + }, + "require-dev": { + "phpunit/phpunit": "*" + }, + "suggest": { + "ext-dom": "Install the DOM extension to load XML formatted public keys.", + "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.", + "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.", + "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.", + "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations." + }, + "type": "library", + "autoload": { + "files": [ + "phpseclib/bootstrap.php" + ], + "psr-4": { + "phpseclib3\\": "phpseclib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jim Wigginton", + "email": "terrafrost@php.net", + "role": "Lead Developer" + }, + { + "name": "Patrick Monnerat", + "email": "pm@datasphere.ch", + "role": "Developer" + }, + { + "name": "Andreas Fischer", + "email": "bantu@phpbb.com", + "role": "Developer" + }, + { + "name": "Hans-Jürgen Petrich", + "email": "petrich@tronic-media.com", + "role": "Developer" + }, + { + "name": "Graham Campbell", + "email": "graham@alt-three.com", + "role": "Developer" + } + ], + "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.", + "homepage": "http://phpseclib.sourceforge.net", + "keywords": [ + "BigInteger", + "aes", + "asn.1", + "asn1", + "blowfish", + "crypto", + "cryptography", + "encryption", + "rsa", + "security", + "sftp", + "signature", + "signing", + "ssh", + "twofish", + "x.509", + "x509" + ], + "support": { + "issues": "https://github.com/phpseclib/phpseclib/issues", + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.43" + }, + "funding": [ + { + "url": "https://github.com/terrafrost", + "type": "github" + }, + { + "url": "https://www.patreon.com/phpseclib", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpseclib/phpseclib", + "type": "tidelift" + } + ], + "time": "2024-12-14T21:12:59+00:00" + }, { "name": "phpstan/phpdoc-parser", "version": "2.1.0", diff --git a/config/bundles.php b/config/bundles.php index 9bed32b..f452abf 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -14,4 +14,5 @@ return [ Symfony\UX\StimulusBundle\StimulusBundle::class => ['all' => true], Symfony\WebpackEncoreBundle\WebpackEncoreBundle::class => ['all' => true], Knp\Bundle\MenuBundle\KnpMenuBundle::class => ['all' => true], + League\FlysystemBundle\FlysystemBundle::class => ['all' => true], ]; diff --git a/config/packages/flysystem.yaml b/config/packages/flysystem.yaml new file mode 100644 index 0000000..c4ed14c --- /dev/null +++ b/config/packages/flysystem.yaml @@ -0,0 +1,20 @@ +flysystem: + storages: + default.storage: + adapter: 'local' + options: + directory: '%kernel.project_dir%/var/storage/default' + xml_export.storage: + adapter: 'local' + options: + directory: '%kernel.project_dir%/var/xmlexport' + xml_dump.storage: + adapter: 'local' + options: + directory: '%kernel.project_dir%/var/bpn' +# adapter: 'sftp' +# options: +# host: '%env(SFTP_XML_EXPORT_HOST)%' +# port: '%env(int:SFTP_XML_EXPORT_PORT)%' +# username: '%env(SFTP_XML_EXPORT_USER)%' +# password: '%env(SFTP_XML_EXPORT_PASSWORD)%' diff --git a/config/services.yaml b/config/services.yaml index 52d13e3..f57043e 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -12,7 +12,8 @@ services: autowire: true # Automatically injects dependencies in your services. autoconfigure: true # Automatically registers your services as commands, event subscribers, etc. bind: - $xmlPath: '%kernel.project_dir%/var/xmlexport' + $xmlExport: '@xml_export.storage' + $xmlDump: '@xml_dump.storage' $travelInfoBaseUrl: '%env(APP_TRAVEL_INFO_BASE_URL)%' $logger: '@monolog.logger.core' @@ -38,7 +39,6 @@ services: bpn_api_ip: '%env(APP_BPN_IP)%' bpn_api_port: '%env(APP_BPN_PORT)%' debug: '%env(bool:APP_BPN_DEBUG)%' - target_folder_dumps: '%kernel.project_dir%/var/bpn' App\Twig\AppRuntime: arguments: diff --git a/src/BusProNet/ApiClient.php b/src/BusProNet/ApiClient.php index b75b918..2310326 100644 --- a/src/BusProNet/ApiClient.php +++ b/src/BusProNet/ApiClient.php @@ -14,6 +14,8 @@ use App\BusProNet\Model\Notification; use App\BusProNet\Model\PersonalData; use App\Form\Model\BookingData; use App\Form\Model\RegistrationData; +use League\Flysystem\FilesystemException; +use League\Flysystem\FilesystemOperator; use Psr\Log\LoggerInterface; use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\Serializer\Encoder\XmlEncoder; @@ -35,6 +37,7 @@ class ApiClient public function __construct( private readonly SerializerInterface $serializer, private readonly ApiResponseParser $responseParser, + private readonly FilesystemOperator $xmlDump, private readonly LoggerInterface $logger, array $options ) { @@ -329,11 +332,10 @@ class ApiClient private function dumpXmlToFile(string $type, string $requestId, string $body): void { - if (false === file_exists($this->config['target_folder_dumps'])) { - mkdir($this->config['target_folder_dumps']); + try { + $this->xmlDump->write($requestId . '_' . $type . '.xml', $body); + } catch (FilesystemException $e) { } - - file_put_contents($this->config['target_folder_dumps'].'/'.$requestId.'_'.$type.'.xml', $body); } private function createKey(string $username, string $password, string $type): string @@ -355,7 +357,6 @@ class ApiClient $optionsResolver->setDefaults([ 'max_retries' => 25, 'debug' => false, - 'target_folder_dumps' => '/tmp/bpn', ]); return $optionsResolver->resolve($options); diff --git a/src/BusProNet/XmlLoader/AbstractLoader.php b/src/BusProNet/XmlLoader/AbstractLoader.php index 4e849f4..b06d9af 100644 --- a/src/BusProNet/XmlLoader/AbstractLoader.php +++ b/src/BusProNet/XmlLoader/AbstractLoader.php @@ -4,6 +4,7 @@ namespace App\BusProNet\XmlLoader; use App\BusProNet\TypeConversionTrait; use App\BusProNet\XmlParserTrait; +use League\Flysystem\FilesystemOperator; use Symfony\Contracts\Cache\CacheInterface; abstract class AbstractLoader @@ -11,7 +12,9 @@ abstract class AbstractLoader use TypeConversionTrait; use XmlParserTrait; - public function __construct(protected readonly CacheInterface $cache, protected readonly ?string $xmlPath = null) - { + public function __construct( + protected readonly CacheInterface $cache, + protected readonly FilesystemOperator $xmlExport, + ) { } -} \ No newline at end of file +} diff --git a/src/BusProNet/XmlLoader/HotelLoader.php b/src/BusProNet/XmlLoader/HotelLoader.php index 0ea14bb..28f6320 100644 --- a/src/BusProNet/XmlLoader/HotelLoader.php +++ b/src/BusProNet/XmlLoader/HotelLoader.php @@ -56,8 +56,7 @@ class HotelLoader extends AbstractLoader private function loadXml(?string $filename = 'hotel.xml'): Crawler { - $filepath = $this->xmlPath.'/'.$filename; - $xml = file_get_contents($filepath); + $xml = $this->xmlExport->read($filename); return new Crawler($xml); } @@ -82,4 +81,4 @@ class HotelLoader extends AbstractLoader $hotel = $this->loadById($hotelId); $travel->hotel = $hotel; } -} \ No newline at end of file +} diff --git a/src/BusProNet/XmlLoader/PickupLoader.php b/src/BusProNet/XmlLoader/PickupLoader.php index e022e35..65c6cf6 100644 --- a/src/BusProNet/XmlLoader/PickupLoader.php +++ b/src/BusProNet/XmlLoader/PickupLoader.php @@ -16,7 +16,7 @@ class PickupLoader extends AbstractLoader return $this->cache->get('bpn_pickups', function (ItemInterface $item) use ($filename) { $item->expiresAfter(3 * 60 * 60); - $crawler = new Crawler(file_get_contents($this->xmlPath . '/' . $filename)); + $crawler = $this->loadXml($filename); $pickupNodes = $crawler->filterXPath('//zustiege/zustieg'); $pickups = []; @@ -40,6 +40,13 @@ class PickupLoader extends AbstractLoader return $pickups[$id] ?? null; } + private function loadXml(?string $filename = 'zustiege.xml'): Crawler + { + $xml = $this->xmlExport->read($filename); + + return new Crawler($xml); + } + public function parseXml(Crawler $node): Pickup { $pickup = new Pickup(); diff --git a/src/BusProNet/XmlLoader/TravelLoader.php b/src/BusProNet/XmlLoader/TravelLoader.php index f9c483a..d7ce749 100644 --- a/src/BusProNet/XmlLoader/TravelLoader.php +++ b/src/BusProNet/XmlLoader/TravelLoader.php @@ -11,9 +11,10 @@ use App\BusProNet\Model\Pickup; use App\BusProNet\Model\Room; use App\BusProNet\Model\Service; use App\BusProNet\Model\Travel; +use League\Flysystem\FilesystemOperator; +use League\Flysystem\StorageAttributes; use Psr\Cache\InvalidArgumentException; use Symfony\Component\DomCrawler\Crawler; -use Symfony\Component\Finder\Finder; use Symfony\Contracts\Cache\CacheInterface; use Symfony\Contracts\Cache\ItemInterface; @@ -23,9 +24,9 @@ class TravelLoader extends AbstractLoader private readonly HotelLoader $hotelDataLoader, CacheInterface $cache, private readonly string $travelInfoBaseUrl, - ?string $xmlPath = null + FileSystemOperator $xmlExport, ) { - parent::__construct($cache, $xmlPath); + parent::__construct($cache, $xmlExport); } public function generateFilesMap(): array @@ -34,14 +35,21 @@ class TravelLoader extends AbstractLoader return $this->cache->get('bpn_travels_mapping', function (ItemInterface $item) { $item->expiresAfter(3 * 60 * 60); - $finder = new Finder(); - $finder->files()->in($this->xmlPath)->name('Ziel_*.xml'); + $xmlFiles = $this + ->xmlExport + ->listContents('.')->filter(fn (StorageAttributes $attributes) => $attributes->isFile()) + ; $mapping = []; $hotels = $this->hotelDataLoader->loadAll(); - foreach ($finder as $file) { - $xml = $file->getContents(); + foreach ($xmlFiles as $file) { + if (false === str_starts_with($file->path(), 'Ziel_')) { + continue; + } + + $xml = $this->xmlExport->read($file->path()); + $crawler = new Crawler($xml); $travelDataNodes = $crawler->filterXPath('//reisen/reise/termin'); @@ -55,7 +63,7 @@ class TravelLoader extends AbstractLoader 'dateFrom' => $this->stringToDate($node->attr('termin')), 'dateTo' => $this->stringToDate($node->attr('bis')), 'hotels' => [], - 'file' => $file->getRealPath(), + 'file' => $file->path(), ]; $node->filterXPath('//hotel') @@ -110,7 +118,7 @@ class TravelLoader extends AbstractLoader private function loadXml(int $id, ?int $hotelId, string $filename): ?Travel { - $xml = file_get_contents($filename); + $xml = $this->xmlExport->read($filename); $crawler = new Crawler($xml); $travelNode = $crawler->filterXPath(sprintf('//reise/termin[@idbuspro="%d"]', $id)); diff --git a/symfony.lock b/symfony.lock index 86647e9..aff7be2 100644 --- a/symfony.lock +++ b/symfony.lock @@ -29,6 +29,19 @@ "knplabs/knp-menu-bundle": { "version": "v3.4.2" }, + "league/flysystem-bundle": { + "version": "3.4", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "1.0", + "ref": "913dc3d7a5a1af0d2b044c5ac3a16e2f851d7380" + }, + "files": [ + "config/packages/flysystem.yaml", + "var/storage/.gitignore" + ] + }, "phpunit/phpunit": { "version": "9.6", "recipe": {